首页
社区
课程
招聘
[原创]记一次unicorn半自动化逆向——还原某东sign算法
发表于: 2021-3-9 18:41 38949

[原创]记一次unicorn半自动化逆向——还原某东sign算法

2021-3-9 18:41
38949

关于题目。

题目是帖子快写完时候想到的,unicorn节省了极大的劳动力,当然也可以使用其他的虚拟执行引擎,但是使用unicorn你只需要pip install unicorn,然后建一个py文件就可以快乐地写代码跑了。

为什么是半自动化逆向?

因为需要自己写代码去控制unicorn怎么执行。

为什么会想起来还原某东sign算法?

因为已经有很多文章来分析怎么直接调用某东的sign算法了,比如使用frida rpc调的:某东直播弹幕实时抓取 https://www.52pojie.cn/thread-1332545-1-1.html。

让我尤其佩服的是一个老哥把它当作了练手项目玩出花了...

虽然老哥的文章有点散,但是入门极其友好,大家感兴趣可以去学习下,给老哥捧下场。

然后刚好最近想提升自己的汇编分析水平,于是就上手分析了。

http://91fans.com.cn/

image-20210309181744859

image-20210309181824749

image-20210309181902240

image-20210309181940242

为了方便分析和调试,我选择了主动集成生成sign的so文件到自己写的apk中,然后主动调用。

可能是gradle版本的问题,搜索到的文章大都无效,踩坑十分多。

最后配置成功主要是根据两篇文章:http://www.sorgs.cn/post/7510/,https://blog.csdn.net/u011106915/article/details/106543464。

其实配置很简单,在src/main/目录下建立jniLibs/armeabi-v7a/目录,把so文件放在里面。

然后配置好build.gradleCMakeLists.txt就行了,当然,不同的gradle版本会有不同的问题,自己多搜索折腾下就好了。

image-20210309113547443

image-20210309113739384

image-20210309113815561

以及so文件中会有两处简单的校验,直接nop两条跳转指令就解决了,十分简单,就不多说了。

总的加密函数执行流程:

sub_127E4——>sub_126AC——>sub_18B8——>sub_227C

核心的加密算法都在sub_126AC中,传入待加密字符串,待加密字符串长度和两个随机值,

image-20210309105834591

image-20210309105806646

sub_126AC会返回加密后的字节,然后sub_18B8进行base64加密,最后sub_227C会进行标准的md5加密。

sub_126AC只是加密的入口,会根据传入的两个随机数选择加密方式和相应的key。

image-20210309110537742

image-20210309110812935

我们定义三种加密方式为version0,version1和version2,其中version0和version1加密流程全部一样,只不过里面函数传入的常量version0是32,version1是16,我们在分析过程中以Version0为例。

加密函数执行流程:

sub_10E4C——>sub_125F0——>sub_12580——>sub_10EA4——>sub_10D70

待加密字符串会被每8个字节分为一组传进sub_10EA4进行加密,如果最后还有字节剩余,会单独进入sub_10D70加密。

首先看下sub_10EA4函数的流程图,先进行初始化,接着有一个循环,循环次数是传入的key0的长度。

image-20210308171518031

最上面的两个长框框就是初始化过程,做了什么呢,IDA进行f5后比较简洁,我们截取一部分看下。

image-20210308173258806

image-20210308173335943

我们注意到分别传入的8个字节分别和0x80(b'1000 0000'),0x40(b'0100 0000'),0x20(b'0010 0000'),0x10(b'0001 0000'),0x8(b’0000 1000‘),0x4(b'0000 0100'),0x2(b'0000 0010'),0x1(b'0000 0001')进行与操作,然后赋值给一些变量,我们观察这些与操作的对象,会发现其实很有规律,这些变量正是输入的8个字节的64个比特位,后面会进行打乱比特位然后还原。

然后我们来看流程图中很有规律的十六个小框框,

image-20210308174216954

截取一些IDA进行f5后的片段进行分析。

image-20210308174746290

image-20210308174524110

其中key0_i是key0的第i个字符,在循环中key0_i也会和0x80(b'1000 0000'),0x40(b'0100 0000'),0x20(b'0010 0000'),0x10(b'0001 0000'),0x8(b’0000 1000‘),0x4(b'0000 0100'),0x2(b'0000 0010'),0x1(b'0000 0001')进行与操作,结果作为条件判断,也就是判断key0_i二进制的对应比特为是0还是1。然后会进入对应的分支交换初始化过程中得到的变量,也就是打乱比特位。

在函数最后进行的是比特位复原,四轮循环,每轮还原两个字节。

image-20210308175646222

image-20210308175711322

如有不清楚的地方,可以自行调试观察。

我们怎么还原sub_10EA4中的算法呢,过程不难就是量多,难道真的要一点点对比着IDA的f5反编译手动写出一样的逻辑吗?当然不是,这里有更简单的方法,我们可以借助unicorn来快速还原。

我们已经分析出来sub_10EA4算法做的不过是打乱传入八个字节的比特位,生成新的八个字节,也就说总的比特位只是顺便变了,并没有被改变值,那么我们可不可以找到每个比特位在打乱前和被打乱后的映射关系呢?当然可以。

我们只要借助unicorn,控制sub_10EA4函数输入的八个字节的64个二进制比特位,如果64个比特中只有一个是1,那么结果的比特位中会有几个1呢?也是只有一个,然后计算前和计算后比特位的1的索引位置就是要找的映射关系,我们进行64次计算,然后每次计算1的索引位置不同,最后就能得到全部比特位的计算前和计算后的映射关系了。

篇幅所限,unicorn的使用就不多说了。

可以得到映射表,例如[1,4]表示64个比特位在打乱后第1个位置的比特位会到第4个位置。

然后可轻松还原sub_10EA4算法。

sub_10D70函数在IDA反编译也比较清晰,我们来看下。

image-20210308212310967

前面有说,待加密字符串会被每8个字节分为一组传进sub_10EA4进行加密,sub_10D70会加密最后余出来的几个字节,这6个case就是加密余出来的1到7个字节。case 0到case 6对应的六个函数都是一个模板,我们以case 0为例来分析,即sub_4B7C。

sub_4B87只会加密处理一个字节,首先我们来看下sub_4B7C的流程图。

image-20210308212954647

可以看到密密麻麻,其他五个case也都长这样,看到后首先第一个反应就是,这是ollvm吗?在经过仔细的分析以及动态调试之后,我判断这个并不是ollvm,没有看到控制流平坦化会带有的标志性大量的常量,也没有找到不可到达的分支,虚假控制流以及指令替换的痕迹,当然也可能是我水平太低了,没有认出来这种ollvm,总之,我还是铁着头把整个流程从头到尾看了一遍。

来看下初始化,

image-20210308214035243

看样子有点像sub_10EA4,但仔细一看又很多不一样,上半部分取了传入的一个字节的比特位,还做了些其他的计算操作,赋值给变量。

而下半部分呢,则是取一些变量的地址,然后放到另一些变量地址加偏移处,这些说起来可能很模糊,但是如果看一下sub_4B7C的栈空间就会清晰很多。

为了方便理解,我们把这样连着五个变量在一起的当作一个数组,这样的数组往下拉可以看到是有八个,每个数组的前四个位置都存放着其他数组首的地址,而第五个位置则存放着前面说的输入字节的比特位经过计算后的值,其实分析后面的case就会发现,有多少输入的比特位,就会有多少个这样的数组。

image-20210308214910555

初始化就这么多,而后面就开始根据这些东西进行大量的循环计算。

image-20210308215648511

整个循环是根据key0的每个字节的每个比特位作为判断条件来选择分支,然后进行循环的,所有的计算类型只有两种,就是下面的两个大方框,是两个小循环。

它们的汇编如下。

这两个小循环做了什么呢?其实十分简单,就是不断地查刚才我们定义的数组的前四个位置存放的变量地址值,判断是否等于另一个变量的地址值,只不过判断的过程中会不断地移动这些数组的第五个位置的值。

这个算法似乎很难搞,确实很难搞,不同于sub_10EA4的对输入字节的比特位进行简单的交换,在获取了比特位后又进行了很多计算。

该怎么办呢,我们来看下sub_4B7C算法的最后部分。

image-20210308220953273

可以看到和sub_10EA4函数最后的比特位还原部分几乎是一样的,这时候我们进行下大胆的猜测,sub_4B7C函数其实也是打乱输入字节的比特位进行了还原,只不过比特位在打乱后还进行了计算,而且每个比特位进行计算的规则都是一样的。即输入的字节第x个比特位是0的话,打乱计算还原后,第y个比特位会是m;如果输入的字节第x个比特位是1的话,第y个比特位则会是n,(x, 0)——>(y,m)(x,1)——>(y,n)。后面经过实践,证明了这样的猜想是正确的。

然后我们还是可以借助unicorn来找到所有的映射关系,还原sub_4B7C算法。思路我们进行下改变,我们可以unicorn控制输入字节的比特位,用八个比特位只有一个1的计算结果和八个比特位全是0的计算结果进行对比从而得到所有的映射关系。

就结果为

我们可以得到为[[0, 6, 0, 1], [1, 4, 1, 0], [2, 5, 0, 1], [3, 0, 0, 1], [4, 2, 0, 1], [5, 3, 0, 1], [6, 1, 1, 0], [7, 7, 0, 1]],里面的列表每个即为[x,y,m,n],比如[6, 1, 0, 1]意味,第6个比特位在打乱计算后会放到第1个比特位上,如果第6个比特位是0,则在打乱计算后会放到第6个比特位上是0,反之是1。

然后可轻松还原sub_4B7C算法。

好了,现在我们已经还原出第一个case,我们再会过头来看下sub_10D70,可以看到一共有七个case,分别对应的七个函数不同的只有函数起始结束地址,以及要处理的字节数,开拓下思维,这时候我们完全可以all in one,一次得到所有case的映射关系。

image-20210308212310967

代码如下:

运行结果:

加密执行函数流程:sub_10DE4——>sub_12FF0——>sub_12ECC——>sub_130D0,其中sub_12ECC是重点,我们直接看sub_12ECC。

进入函数sub_12ECC,先看下开始处的汇编片段。r1寄存器存放着key2字符串地址,r2寄存器存放着常量1,r3寄存器存放着待加密字符串地址,在开辟栈空间后SP,#0x48+arg_0地址存放着是待加密字节的长度。

我们注意到下面这四句汇编指令,是把待加密字符串存放的地址放到r10寄存器中,key2字符串地址放到r7寄存器中,常量1放到r9寄存器,从SP,#0x48+arg_0地址取出待加密字符串长度后放到r8寄存器中。

然后我们在函数sub_12ECC中往下走,找到0x12F68地址处开始的关键汇编片段,即sign算法加密部分,这里是一个循环。

r10寄存器

我们抓重点,看待加密字符串是怎么被加密的,待加密字符串地址放在了r10寄存器中,涉及r10寄存器的汇编指令有三条。

00012F74处的LDRB.W R0, [R10]是取出待加密字符串的一个字节放到r0寄存器中随后会进行计算操作;

00012F92处的STRB.W R2, [R10],#1,这条指令首先会把放在r2寄存器中的计算结果值放到r10寄存器当前存储的地址上,这个并不重要,因为还没有计算完成,后面的指令才是把最后的计算值存放值到这个地址上,重要的是这条指令随后r10寄存器中的地址值会加一,因为这是一个基于索引后置修改取址模式;

00012F9200012F9C之间,我们可以看到取了r7寄存器存放的地址值的一个偏移地址的值(偏移值为r1寄存器中的值)放到了r1寄存器中,随后把r1r2寄存器中的值进行亦或,结果存放在r2寄存器中。

最后是涉及到r10寄存器的第三条指令00012F9C处,STRB.W R2, [R10,#-1],把计算结果值放到R10,#-1地址处,注意到r10寄存器中的地址值刚才已经加一,所以现在减一后还是刚才存储的地址,所以这里才是计算结果最后存放的指令。

r3寄存器

好了,我们已经知道计算结果是放到了r2寄存器中,我们从00012F66开始看,一步步看是怎么计算出来的。

可以看到,r3作为计数器,每轮循环会在.text:00012F78 ADDS R3, #1处加一,并在.text:00012F7E CMP R3, R8处和r8寄存器值即加密字符串长度进行比较。

r2寄存器

在开始处,r3首先和0xf进行与操作,结果放在r2寄存器中,随后将与操作的结果值和SP, #0x48+var_28地址值进行相加,相加结果仍放在r2寄存器中,随后会进行.text:00012F7A LDRB.W R2, [R2,#-0x14],也就是说现在r2寄存器中存放的是SP, #0x48+var_28地址加上一个偏移值(即(i &0xf) - 0x14)这个地址上存放的值。

r4寄存器

然后在.text:00012F70 AND.W R1, R3, #7处把r3寄存器中的值和7进行与操作,结果放在r1寄存器中,然后在.text:00012F80 LDRB R4, [R7,R1]处把r1寄存器中的地址值作为偏移加上r7寄存器中的值,取出这个地址中的值放在r4寄存器中,r7寄存器前面我们说了放的是key2,所以放在r4寄存器中这个的值即是key2[i&7]

计算部分

随后便是计算部分:

此时,涉及计算的r0 r2 r4我们都已经知道是什么了,r0寄存器中的值我们在提r10寄存器时候有知道它是待加密字符串取出的一个字节。

IDA F5

这部分使用IDA进行f5的效果是这样的。

image-20210308163440724

现在我们想还原这个加密过程该怎么办,要看我们缺什么。待加密字符串,key2和加密计算过程我们都有了,只有一个SP, #0x48+var_28地址加上一个偏移 -0x14,这个地址存放有一个数组,每轮加密循环会取出一个值(数组偏移(i & 0xf)处)放在r2寄存器中然后进行计算,我们通过静态分析无法知道这个数组值是什么,所以进行ida动态调试,可以得到这个地方存放的数组值为[0x37, 0x92, 0x44, 0x68, 0xA5, 0x3D, 0xCC, 0x7F, 0xBB, 0xF, 0xD9, 0x88, 0xEE, 0x9A, 0xE9, 0x5A]。

image-20210309140639735

随后可python写出sub_12ECC函数中的加密计算过程。

好了,到现在所有的关键函数已经被我们分析出来了,想还原出来所有的sign加密流程已经成了一个时间问题的体力劳动了,本来想放个半成品给大家参考下,经评论区老哥友情提醒,分析流程已经足够了,这部分就先和谐掉吧...

以及文章目的是学习交流的,请勿不正确使用,用于违法行为。

最近经常会在想自己大部分时候只会用frida去hook十分像一个脚本小子(逃,迫切需要提升汇编分析水平,分析到这里对我自己来说进步不小,但是要学习的东西还很多,如果有什么希望的话,就是希望能早一点摆脱对IDA f5的依赖,可以手撕汇编:)

最后,如果你有学到有用的东西,请不要忘记点赞,不枉我写了这么多。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
from unicorn import *
from unicorn.arm_const import *
 
table = []
 
def bytes2bin(bytes):
    arr = []
    for v in [m for m in bytes]:
        arr.append(
            [(v & 128) >> 7, (v & 64) >> 6, (v & 32) >> 5, (v & 16) >> 4, (v & 8) >> 3, (v & 4) >> 2, (v & 2) >> 1,
             v & 1])
    return [i for j in arr for i in j]
 
 
def bin2bytes(arr):
    length = len(arr) // 8
    arr1 = [0 for _ in range(length)]
    for j in range(length):
        arr1[j] = arr[j * 8] << 7 | arr[j * 8 + 1] << 6 | arr[j * 8 + 2] << 5 | arr[j * 8 + 3] << 4 | arr[
            j * 8 + 4] << 3 | arr[j * 8 + 5] << 2 | arr[j * 8 + 6] << 1 | arr[j * 8 + 7]
    return bytes(arr1)
 
 
def read(name):
    with open(name, 'rb') as f:
        return f.read()
 
 
def hook_code(mu, address, size, user_data):
    if address == BASE + 0x119cc:
        arr2 = []
        for byte in mu.mem_read(PLAINTEXT_ADDR, 8):
            arr2.append(byte)
        table.append([user_data.index(1), bytes2bin(arr2).index(1)])
 
 
if __name__ == "__main__":
    key0 = b'44e715a6e322ccb7d028f7a42fa55040'
    mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
    BASE = 0x400000
    STACK_ADDR = 0x0
    STACK_SIZE = 1024
    PLAINTEXT_ADDR = 1024 * 2
    PLAINTEXT_SIZE = 1024
    KEY_ADDR = 1024 * 3
    KEY_SIZE = 1024
    mu.mem_map(BASE, 1024 * 1024)
    mu.mem_map(STACK_ADDR, STACK_SIZE)
    mu.mem_map(PLAINTEXT_ADDR, PLAINTEXT_SIZE)
    mu.mem_map(KEY_ADDR, KEY_SIZE)
    mu.reg_write(UC_ARM_REG_SP, STACK_ADDR + STACK_SIZE - 1)
    # mu.mem_write(BASE, read("F:\\Code\\Pycharm\\JDSign\\libjdbitmapkit.so"))
    mu.mem_write(BASE, read("./libjdbitmapkit.so"))
    mu.mem_write(KEY_ADDR, key0)
 
    for i in range(64):
        arr1 = [0 for j in range(64)]
        arr1[i] = 1
        h = mu.hook_add(UC_HOOK_CODE, hook_code, arr1)
        mu.mem_write(PLAINTEXT_ADDR, bin2bytes(arr1))
        mu.reg_write(UC_ARM_REG_R1, KEY_ADDR)
        mu.reg_write(UC_ARM_REG_R2, 32)
        mu.reg_write(UC_ARM_REG_R3, PLAINTEXT_ADDR)
        mu.emu_start(BASE + 0x00010EA4 + 1, BASE + 0x000119D0)
        mu.hook_del(h)
    print(table)
from unicorn import *
from unicorn.arm_const import *
 
table = []
 
def bytes2bin(bytes):
    arr = []
    for v in [m for m in bytes]:
        arr.append(
            [(v & 128) >> 7, (v & 64) >> 6, (v & 32) >> 5, (v & 16) >> 4, (v & 8) >> 3, (v & 4) >> 2, (v & 2) >> 1,
             v & 1])
    return [i for j in arr for i in j]
 
 
def bin2bytes(arr):
    length = len(arr) // 8
    arr1 = [0 for _ in range(length)]
    for j in range(length):
        arr1[j] = arr[j * 8] << 7 | arr[j * 8 + 1] << 6 | arr[j * 8 + 2] << 5 | arr[j * 8 + 3] << 4 | arr[
            j * 8 + 4] << 3 | arr[j * 8 + 5] << 2 | arr[j * 8 + 6] << 1 | arr[j * 8 + 7]
    return bytes(arr1)
 
 
def read(name):
    with open(name, 'rb') as f:
        return f.read()
 
 
def hook_code(mu, address, size, user_data):
    if address == BASE + 0x119cc:
        arr2 = []
        for byte in mu.mem_read(PLAINTEXT_ADDR, 8):
            arr2.append(byte)
        table.append([user_data.index(1), bytes2bin(arr2).index(1)])
 
 
if __name__ == "__main__":
    key0 = b'44e715a6e322ccb7d028f7a42fa55040'
    mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
    BASE = 0x400000
    STACK_ADDR = 0x0
    STACK_SIZE = 1024
    PLAINTEXT_ADDR = 1024 * 2
    PLAINTEXT_SIZE = 1024
    KEY_ADDR = 1024 * 3
    KEY_SIZE = 1024
    mu.mem_map(BASE, 1024 * 1024)
    mu.mem_map(STACK_ADDR, STACK_SIZE)
    mu.mem_map(PLAINTEXT_ADDR, PLAINTEXT_SIZE)
    mu.mem_map(KEY_ADDR, KEY_SIZE)
    mu.reg_write(UC_ARM_REG_SP, STACK_ADDR + STACK_SIZE - 1)
    # mu.mem_write(BASE, read("F:\\Code\\Pycharm\\JDSign\\libjdbitmapkit.so"))
    mu.mem_write(BASE, read("./libjdbitmapkit.so"))
    mu.mem_write(KEY_ADDR, key0)
 
    for i in range(64):
        arr1 = [0 for j in range(64)]
        arr1[i] = 1
        h = mu.hook_add(UC_HOOK_CODE, hook_code, arr1)
        mu.mem_write(PLAINTEXT_ADDR, bin2bytes(arr1))
        mu.reg_write(UC_ARM_REG_R1, KEY_ADDR)
        mu.reg_write(UC_ARM_REG_R2, 32)
        mu.reg_write(UC_ARM_REG_R3, PLAINTEXT_ADDR)
        mu.emu_start(BASE + 0x00010EA4 + 1, BASE + 0x000119D0)
        mu.hook_del(h)
    print(table)
[[0, 0], [1, 4], [2, 61], [3, 15], [4, 56], [5, 40], [6, 6], [7, 59], [8, 62], [9, 58], [10, 17], [11, 2], [12, 12], [13, 8], [14, 32], [15, 60], [16, 13], [17, 45], [18, 34], [19, 14], [20, 36], [21, 21], [22, 22], [23, 39], [24, 23], [25, 25], [26, 26], [27, 20], [28, 1], [29, 33], [30, 46], [31, 55], [32, 35], [33, 24], [34, 57], [35, 19], [36, 53], [37, 37], [38, 38], [39, 5], [40, 30], [41, 41], [42, 42], [43, 18], [44, 47], [45, 27], [46, 9], [47, 44], [48, 51], [49, 7], [50, 49], [51, 63], [52, 28], [53, 43], [54, 54], [55, 52], [56, 31], [57, 10], [58, 29], [59, 11], [60, 3], [61, 16], [62, 50], [63, 48]]
[[0, 0], [1, 4], [2, 61], [3, 15], [4, 56], [5, 40], [6, 6], [7, 59], [8, 62], [9, 58], [10, 17], [11, 2], [12, 12], [13, 8], [14, 32], [15, 60], [16, 13], [17, 45], [18, 34], [19, 14], [20, 36], [21, 21], [22, 22], [23, 39], [24, 23], [25, 25], [26, 26], [27, 20], [28, 1], [29, 33], [30, 46], [31, 55], [32, 35], [33, 24], [34, 57], [35, 19], [36, 53], [37, 37], [38, 38], [39, 5], [40, 30], [41, 41], [42, 42], [43, 18], [44, 47], [45, 27], [46, 9], [47, 44], [48, 51], [49, 7], [50, 49], [51, 63], [52, 28], [53, 43], [54, 54], [55, 52], [56, 31], [57, 10], [58, 29], [59, 11], [60, 3], [61, 16], [62, 50], [63, 48]]
def sub_10EA4(input):
    table = [[0, 0], [1, 4], [2, 61], [3, 15], [4, 56], [5, 40], [6, 6], [7, 59], [8, 62], [9, 58], [10, 17], [11, 2],
             [12, 12], [13, 8], [14, 32], [15, 60], [16, 13], [17, 45], [18, 34], [19, 14], [20, 36], [21, 21],
             [22, 22], [23, 39], [24, 23], [25, 25], [26, 26], [27, 20], [28, 1], [29, 33], [30, 46], [31, 55],
             [32, 35], [33, 24], [34, 57], [35, 19], [36, 53], [37, 37], [38, 38], [39, 5], [40, 30], [41, 41],
             [42, 42], [43, 18], [44, 47], [45, 27], [46, 9], [47, 44], [48, 51], [49, 7], [50, 49], [51, 63], [52, 28],
             [53, 43], [54, 54], [55, 52], [56, 31], [57, 10], [58, 29], [59, 11], [60, 3], [61, 16], [62, 50],
             [63, 48]]
    arr = bytes2bin(input)
    arr1 = [0 for i in range(len(arr))]
    for i in range(len(table)):
        arr1[table[i][1]] = arr[table[i][0]]
    return bin2bytes(arr1)
def sub_10EA4(input):
    table = [[0, 0], [1, 4], [2, 61], [3, 15], [4, 56], [5, 40], [6, 6], [7, 59], [8, 62], [9, 58], [10, 17], [11, 2],
             [12, 12], [13, 8], [14, 32], [15, 60], [16, 13], [17, 45], [18, 34], [19, 14], [20, 36], [21, 21],
             [22, 22], [23, 39], [24, 23], [25, 25], [26, 26], [27, 20], [28, 1], [29, 33], [30, 46], [31, 55],
             [32, 35], [33, 24], [34, 57], [35, 19], [36, 53], [37, 37], [38, 38], [39, 5], [40, 30], [41, 41],
             [42, 42], [43, 18], [44, 47], [45, 27], [46, 9], [47, 44], [48, 51], [49, 7], [50, 49], [51, 63], [52, 28],
             [53, 43], [54, 54], [55, 52], [56, 31], [57, 10], [58, 29], [59, 11], [60, 3], [61, 16], [62, 50],
             [63, 48]]
    arr = bytes2bin(input)
    arr1 = [0 for i in range(len(arr))]
    for i in range(len(table)):
        arr1[table[i][1]] = arr[table[i][0]]
    return bin2bytes(arr1)
 
 
 
 
 
 
 
 
 
 
 
 
 
.text:00005BE2 loc_5BE2                                ; CODE XREF: sub_4B7C+104↑j
.text:00005BE2                 CMP             R1, R2
.text:00005BE4                 MOV             R12, R1
.text:00005BE6                 BEQ             loc_5C00
.text:00005BE8                 MOV             R6, R1
.text:00005BEA                 MOV             R8, R2
.text:00005BEC                 B               loc_5BF0
.text:00005BEE ; ---------------------------------------------------------------------------
.text:00005BEE
.text:00005BEE loc_5BEE                                ; CODE XREF: sub_4B7C+1082↓j
.text:00005BEE                 MOV             R12, R6
.text:00005BF0
.text:00005BF0 loc_5BF0                                ; CODE XREF: sub_4B7C+1070↑j
.text:00005BF0                 LDRB            R6, [R6,#0x10]
.text:00005BF2                 STRB.W          R6, [R8,#0x10]
.text:00005BF6                 MOV             R8, R12
.text:00005BF8                 LDR.W           R6, [R12,#0xC]
.text:00005BFC                 CMP             R6, R2
.text:00005BFE                 BNE             loc_5BEE
.text:00005C00
.text:00005BE2 loc_5BE2                                ; CODE XREF: sub_4B7C+104↑j
.text:00005BE2                 CMP             R1, R2
.text:00005BE4                 MOV             R12, R1
.text:00005BE6                 BEQ             loc_5C00
.text:00005BE8                 MOV             R6, R1
.text:00005BEA                 MOV             R8, R2
.text:00005BEC                 B               loc_5BF0
.text:00005BEE ; ---------------------------------------------------------------------------
.text:00005BEE
.text:00005BEE loc_5BEE                                ; CODE XREF: sub_4B7C+1082↓j
.text:00005BEE                 MOV             R12, R6
.text:00005BF0
.text:00005BF0 loc_5BF0                                ; CODE XREF: sub_4B7C+1070↑j
.text:00005BF0                 LDRB            R6, [R6,#0x10]
.text:00005BF2                 STRB.W          R6, [R8,#0x10]
.text:00005BF6                 MOV             R8, R12
.text:00005BF8                 LDR.W           R6, [R12,#0xC]
.text:00005BFC                 CMP             R6, R2
.text:00005BFE                 BNE             loc_5BEE
.text:00005C00
text:00005C00                 CMP             R11, R2
.text:00005C02                 STRB.W          R4, [R12,#0x10]
.text:00005C06                 MOV             R4, R11
.text:00005C08                 LDRB.W          R8, [SP,#0xE0+var_98]
.text:00005C0C                 IT NE
.text:00005C0E                 MOVNE           R12, R2
.text:00005C10                 BNE             loc_5C16
.text:00005C12                 B               loc_5C2C
.text:00005C14 ; ---------------------------------------------------------------------------
.text:00005C14
.text:00005C14 loc_5C14                                ; CODE XREF: sub_4B7C+10AE↓j
.text:00005C14                 MOV             R4, R6
.text:00005C16
.text:00005C16 loc_5C16                                ; CODE XREF: sub_4B7C+1094↑j
.text:00005C16                 LDRB            R6, [R4,#0x10]
.text:00005C18                 RSBS.W          R6, R6, #1
.text:00005C1C                 IT CC
.text:00005C1E                 MOVCC           R6, #0
.text:00005C20                 STRB.W          R6, [R12,#0x10]
.text:00005C24                 LDR             R6, [R4,#4]
.text:00005C26                 MOV             R12, R4
.text:00005C28                 CMP             R6, R2
.text:00005C2A                 BNE             loc_5C14
text:00005C00                 CMP             R11, R2
.text:00005C02                 STRB.W          R4, [R12,#0x10]
.text:00005C06                 MOV             R4, R11
.text:00005C08                 LDRB.W          R8, [SP,#0xE0+var_98]
.text:00005C0C                 IT NE
.text:00005C0E                 MOVNE           R12, R2
.text:00005C10                 BNE             loc_5C16
.text:00005C12                 B               loc_5C2C
.text:00005C14 ; ---------------------------------------------------------------------------
.text:00005C14
.text:00005C14 loc_5C14                                ; CODE XREF: sub_4B7C+10AE↓j
.text:00005C14                 MOV             R4, R6
.text:00005C16
.text:00005C16 loc_5C16                                ; CODE XREF: sub_4B7C+1094↑j
.text:00005C16                 LDRB            R6, [R4,#0x10]
.text:00005C18                 RSBS.W          R6, R6, #1
.text:00005C1C                 IT CC
.text:00005C1E                 MOVCC           R6, #0
.text:00005C20                 STRB.W          R6, [R12,#0x10]

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-3-14 11:16 被0x指纹编辑 ,原因:
上传的附件:
收藏
免费 48
支持
分享
打赏 + 40.00雪花
打赏次数 4 雪花 + 40.00
 
赞赏  wx_小毛球   +10.00 2021/03/13 精品文章~大佬请回复一下我,谢谢。qq911657507
赞赏  Gwyn9   +10.00 2021/03/11 精品文章~
赞赏  _air   +10.00 2021/03/10 感谢分享~
赞赏  又见飞刀z   +10.00 2021/03/10 感谢分享~
最新回复 (52)
雪    币: 530
活跃值: (975)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
前排学习
2021-3-9 19:36
0
雪    币: 211
活跃值: (511)
能力值: ( LV9,RANK:172 )
在线值:
发帖
回帖
粉丝
3

以前完整还原过某东算法, 上面的sv格式是 1XX (X在[0, 2]随机取值), 不同的值最后一个快padding&算法不一样,分析了其中2种。

最后于 2021-3-10 10:12 被vmtest编辑 ,原因:
2021-3-9 20:52
0
雪    币: 4515
活跃值: (2136)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
插眼 
2021-3-10 09:24
0
雪    币: 295
活跃值: (920)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5

指纹大佬优秀 还以为某东那个某是“精”

最后于 2021-3-10 11:12 被darbra编辑 ,原因:
2021-3-10 11:11
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
6
vmtest 以前完整还原过某东算法,&nbsp;上面的sv格式是 1XX (X在[0, 2]随机取值), 不同的值最后一个快padding&amp;算法不一样,分析了其中2种。
不知道分析的是不是一个版本,不同的sv会选择三种加密流程中的一种,最后的几个字节处理分析起来确实比较头疼
2021-3-10 11:24
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
7
darbra 指纹大佬优秀&nbsp;还以为某东那个某是“精”
看完文章就知道是哪个某了
2021-3-10 11:24
0
雪    币: 5330
活跃值: (5464)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
8
前排给指纹大佬点烟!
2021-3-10 16:26
0
雪    币: 26399
活跃值: (63277)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
9
感谢分享!赞!
2021-3-10 16:41
0
雪    币: 373
活跃值: (2183)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
感谢分享,必须赞一个
2021-3-10 18:24
1
雪    币: 128
活跃值: (111)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢分享,学习学习
2021-3-11 22:44
0
雪    币: 6911
活跃值: (9064)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
12
太肝了,我什么时候才能这么有耐心
2021-3-11 23:36
0
雪    币: 6573
活跃值: (3873)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
13
感谢分享,强悍! 
2021-3-12 10:29
0
雪    币: 224
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
我想知道这一套流程分析下来花了多久时间
2021-3-12 10:59
0
雪    币: 1420
活跃值: (2151)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
色流大佬 转战电商了?
2021-3-12 12:08
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
16
fenfei331 感谢分享,必须赞一个[em_28]
把sign玩出花的老哥 你出现了
2021-3-12 12:14
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
17
无名侠 太肝了,我什么时候才能这么有耐心
大师傅就不来要笑我了
2021-3-12 12:15
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
18
LowRebSwrd 感谢分享,强悍!
感谢斑竹,斑竹辛苦了
2021-3-12 12:19
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
19
感谢你曾来过 我想知道这一套流程分析下来花了多久时间
如果能看出来,两三天就够了,我是开始没看出来,分析了很久,后面才看出来
2021-3-12 12:20
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
20
青丝梦 色流大佬 转战电商了?
转战汇编
2021-3-12 12:21
0
雪    币: 986
活跃值: (6167)
能力值: ( LV7,RANK:115 )
在线值:
发帖
回帖
粉丝
21
膜!
2021-3-12 16:22
0
雪    币: 3139
活跃值: (588)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
插眼
2021-3-12 18:45
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
大佬为什么我用你的代码post请求总是signature verification failed,但是get请求却成功了,可不可以给我解答一下?qq911657507
2021-3-13 23:25
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
大佬急着等你回复呢
2021-3-13 23:33
0
雪    币: 3862
活跃值: (1504)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25

不错的文章。。跟后面重现了下流程,完美成功。

最后于 2021-3-14 00:25 被braintrust编辑 ,原因:
2021-3-13 23:43
1
游客
登录 | 注册 方可回帖
返回
//