【Android安全- 某加密的a26生成分析全过程】此文章归类为:Android安全。
本帖本着分享逆向思路的初心而发,实际内容是自己随笔录,有些部分已脱敏,本身也是一个思路分析贴,所以不会含有源码
a26有8套算法,这是其中一套,当然我不会说第几套
qbdi-python:https://bbs.kanxue.com/thread-276523.htm
ida:我很少看ida,只是辅助吧,因为现在的so混淆太严重,手动去花费时费力,而且好多地方也反编译不出来,我的选择,铁锭硬刚汇编
unidbg:unidbg的作用是为了看真机的算法,unidbg是否执行,如果有,在还原算法的时候,可以用unidbg代替
已知这个加密中会有26个参数,其他参数的获取相对简单,所以目标也就是第26个参数
通过unidbg的插件traceFunction,找到protobuf第一次生成的位置
在ida中查看,发现是一个跳转
通过对比frida 的日志传参和结果,发现与ida的伪c结果一致,
所以直接hook 0xc4c70
即可
计数器发现,这个函数被调用了4次(unidbg是3次),通过搜索最后一节12字节的数据,有两个结果,找到第一个,
so的逆向肯定离不开日志,我使用的是yang神开源的qbdi-python,
具体看yang神的文章,感谢开源
目前qbdi的工具也有很多,也有速度很快的,但是我感觉都是一样,除非是快了点,打把lol就完事了
我这里trace了三份日志,实际分析只用了两个,
我的逆向习惯,第一份分析,第二份验证
因为换了设备,第一分日志是分析了前两个字节,后面都是以第二份日志分析为主
如果有需要,请留言,
如果有需要,请留言
如果有需要,请留言
因为我分析的日志做全寄存器输出,导致日志很大,上传至云盘再分享出来
1、d2 9e 4b 80 d8 62 cd e8 87 ea 10 bc(第一次trace)
2、e2 55 48 8a e8 a9 ce e2 b7 21 13 b6 (第二次trace)
真机trace的 a26 d2 9e 4b 80 d8 62 cd e8 87 ea 10 bc
一般加密会在组装的附近,所以,先搜d2
因为同时监控了读写,所以,直接搜 = ab就可以
这个距离拼接比较近,记录一下,
= d2 8[w] 7d85d0a600 1[w] 7d85f94d20
如法炮制
= 9e 8[w] 7d85d0a600 1[w] 7d85f94d21
= 4b 8[w] 7d85d0a600 1[w] 7d85f94d22
= 80 8[w] 7d85d0a600 1[w] 7d85f94d23
这个时候就已经可以看到规律了,直接搜这个地址吧
可以直接得到a26的写入,可惜我这次trace,硬扣汇编,板凳流
日志就可以看到,从 0x7d85d0a600
读取的 0xd2 ,看一下其他的是否也是这种情况,
0x7d85d0a600
是不是中间存储
所以,0x7d85d0a600
是存储a26每次计算的结果的,那就好办了,把read改成write,看看写入就可以把a26逐个击破了
0xd2 是由 0x71 和 0xa3 异或而来,追一下x8和x10怎么来的,记录吧
可以看到从 7d85d0a670
读取的值,搜索这个地址什么时候写入的
从这里可以看到 0x71
从 7d85d095b8
读取一个字节,写入 7d85d0a670
看看什么时候写入
从7d85d0b128
读取,继续跟踪
从 7d85d0b1c28
读取,继续跟踪
好像有很多,直接一步到位
从7d85d0b128
读取,继续跟踪
从 7d85d0b1c28
读取,继续跟踪
好像有很多,直接一步到位
可以看到,最终结果是函数返回的,那我们看看这个函数是什么
减4位,然后往上找一位,这个是函数入口
ida看一眼
是个随机数,所以 0x71 是由随机数(0x71314d5e
),反转(0xe54d3171
), 取最低位0x71
0x71314d5e
[0]
像0x71一样,如法炮制
从 7d85d0a688
读取,跟踪看看
从
7d85f94bdb
读取,跟踪看看
从 7d89a8e2e3
读取,跟踪看看
又是加载一个字节,跟踪看看
再次搜索,发现搜索write失效了,只能硬着头破跟了
还是有一定规律在里面的,分析分析
搜索大法失效 - -!跟踪看看x21寄存器怎么赋值的吧
通过搜索,唉,跟上面一样,指令执行这么多,x21都没动过 - - !
可以看到,x21是由地址偏移来的
现在捋一下
0x7dc912258c
ldr 0x0
-> 0xde
0x7dc912258c
ldr 0x1
-> 0x06
0x7dc912258c
ldr 0x2
-> 0xaf
0x7dc912258c
ldr 0x3
-> 0xa3
(目标值)
0x7dc912258c
- 0x7dc9122590
存储着读取的值 0xde06afa3
搜索这个值看看,当前行号 795471
跟踪这个地址看看 memory write at 7d85d08f5b
最终在这里生成
通过不停的滑动
这个看起来像是加密的地方 0x93cf0
ida中,
可以在伪c中,看到两个常量,百度搜一下
都指向了sm3
既然他可能是sm3,在xa的别的地方也用到了sm3,看看用的是否是同一个函数,又到了小工具的高光时刻
14 | 48 e3 40 a3 ad 76 |
通过搜索 a14的值,第一次出现在0x8ff88
中,ida中看看
看不到什么,结合汇编分析吧,看看lr,返回值给了谁
通过分析 traceWrite在写入0xbfffc510
这个地址的时候,断住,然后看汇编,往上找调用(也就是不连续的地址处),同时用unidbg将可疑的函数断住看情况,最终分析出,这个函数是sm3
x0是待加密值
x1是长度
x2是空的,结合写入的日志,这个肯定是buffer了,
在这个地址断住
是标准的sm3了
回到 0xde06afa3
通过分析,这个地址,确实在0x942d4
函数内(因为日志在入参和返回中,且日志行数变化不大)
想了想,不给frida代码,解释的好像很苍白。。。dddd(懂得都懂),so打码了
function hook_so_x() { var soAddr = Module.findBaseAddress("****.so") console.log("模块基址:", soAddr) var four_add = soAddr.add(0x942d4) let result; let num = 0; Interceptor.attach(four_add, { onEnter: function (args) { result = args[2] console.log(result, num, "入参2:", hexdump(args[2])) console.log(result, num, "入参0:", hexdump(args[0])) console.log(result, num, "入参1:", args[1]) } }) Interceptor.attach(soAddr.add(0x95b70), { onEnter: function (args) { console.log(result, num, "入参的出参:", hexdump(result)) num += 1 } }) } function call_x_func() { let baselibEncryptor = Module.findBaseAddress("libmetasec_ov.so"); let addr_8bb80 = baselibEncryptor.add(0x8c4a0); let str0 = "8d2K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2M7r3V1I4y4W2)9J5k6r3y4G2M7X3g2Q4x3X3c8#2M7$3g2S2M7%4b7#2i4K6u0W2N6i4y4Q4x3X3g2@1K9h3E0@1L8$3E0$3i4K6u0W2j5$3!0E0i4K6u0r3j5i4N6W2L8h3g2Q4x3V1k6$3x3g2)9J5c8X3q4%4k6h3#2W2i4K6u0r3M7r3!0K6N6q4)9J5c8W2)9K6c8Y4y4G2N6i4u0U0k6g2)9K6c8o6m8Q4x3U0k6S2L8i4m8Q4x3@1u0#2M7$3g2J5i4K6g2X3j5i4k6S2N6r3q4J5i4K6g2X3M7$3S2J5K9h3&6C8i4K6y4p5z5e0k6Q4y4h3j5&6y4W2)9J5y4X3q4E0M7q4)9K6b7Y4k6A6k6r3g2G2i4K6g2X3j5$3!0$3k6i4u0Q4y4h3k6K6K9s2u0A6L8X3E0Q4x3@1b7J5y4o6S2Q4y4h3j5K6x3K6m8Q4x3U0k6S2L8i4m8Q4x3@1u0E0j5i4S2Q4y4h3k6U0N6i4u0K6L8%4u0Q4x3@1b7H3i4K6t1$3j5h3#2H3i4K6y4n7M7$3g2U0i4K6g2X3N6i4y4W2M7W2)9#2k6X3W2V1i4K6y4p5e0g2x3@1N6@1I4B7b7f1u0m8b7f1q4m8e0g2c8s2g2o6W2#2P5V1b7#2y4X3W2^5d9W2k6D9j5V1Z5@1b7e0W2v1g2h3c8Q4y4h3k6a6g2#2)9#2k6Y4q4c8g2W2W2U0k6e0f1#2x3e0q4U0k6e0b7#2L8f1W2e0b7$3k6a6f1p5c8n7L8U0g2K9h3V1q4K6e0p5!0p5b7$3E0S2b7h3E0Q4x3U0k6S2L8i4m8Q4x3@1u0U0L8%4g2F1N6q4)9K6c8o6W2Q4x3U0k6S2L8i4m8Q4x3@1u0D9L8$3y4S2N6r3g2Q4y4h3k6A6N6r3g2E0i4K6g2X3K9h3c8Q4x3U0k6S2L8i4m8Q4x3@1u0K6L8%4u0@1i4K6g2X3N6s2W2H3k6g2)9K6c8o6m8Q4x3U0k6S2L8i4m8Q4x3@1u0A6K9h3c8Q4x3@1b7%4x3U0V1@1y4e0p5^5y4K6t1@1x3K6x3%4x3e0V1H3y4U0V1^5i4K6t1$3j5h3#2H3i4K6y4n7k6r3g2$3K9h3y4W2i4K6g2X3K9h3c8Q4x3@1b7$3y4U0j5I4x3U0f1^5y4U0b7J5y4o6l9#2x3K6t1^5x3K6R3&6i4K6t1$3j5h3#2H3i4K6y4n7j5h3y4Q4x3@1c8%4K9h3k6A6i4K6t1$3j5h3#2H3i4K6y4n7j5$3S2S2L8X3&6W2L8q4)9K6c8r3N6G2L8$3N6D9k6i4m8D9j5i4W2Q4x3U0k6S2L8i4m8Q4x3@1u0S2K9h3c8Q4x3@1b7I4x3U0x3K6i4K6t1$3j5h3#2H3i4K6y4n7j5i4m8H3i4K6g2X3L8X3q4E0k6g2)9K6c8r3#2#2M7$3W2U0j5h3I4Q4y4h3k6D9P5g2)9J5y4X3q4E0M7q4)9K6b7Y4k6W2M7Y4y4A6L8$3&6Q4y4h3k6U0L8$3c8W2i4K6y4p5x3K6p5H3z5e0l9I4i4K6t1$3j5h3#2H3i4K6y4n7N6X3g2J5M7$3W2G2L8W2)9#2k6X3&6S2L8h3g2Q4x3@1b7K6x3g2)9J5k6e0W2Q4x3X3f1I4i4K6t1$3j5h3#2H3i4K6y4n7k6r3g2$3K9h3y4W2i4K6g2X3M7r3I4S2N6r3k6G2M7X3#2Q4x3@1c8S2L8X3c8J5L8$3W2V1i4K6t1$3j5h3#2H3i4K6y4n7L8%4y4Q4x3@1c8S2L8X3c8J5L8$3W2V1i4K6t1$3j5h3#2H3i4K6y4n7j5h3u0Q4y4h3k6$3k6i4u0K6K9h3!0F1i4K6y4p5x3K6q4Q4x3X3f1&6i4K6u0W2x3g2)9J5y4X3q4E0M7q4)9K6b7Y4y4K6L8h3W2^5i4K6y4p5j5g2)9J5y4X3q4E0M7q4)9K6b7X3c8W2N6X3W2U0k6g2)9#2k6Y4c8&6M7r3g2Q4x3@1c8e0e0g2)9J5k6p5M7&6y4K6N6z5i4K6t1$3j5h3#2H3i4K6y4n7k6r3g2$3K9h3y4W2i4K6g2X3j5Y4u0S2L8X3c8Q4x3@1c8K6j5h3#2K6N6h3&6Y4i4K6t1$3j5h3#2H3i4K6y4n7L8r3q4F1k6%4g2S2k6$3g2Q4x3@1c8W2L8W2)9J5y4X3q4E0M7q4)9K6b7X3!0K6i4K6g2X3j5i4m8A6i4K6y4p5x3U0S2Q4x3U0k6S2L8i4m8Q4x3@1u0G2M7#2)9#2k6Y4k6W2M7Y4y4A6L8$3&6Q4x3@1b7&6i4K6t1$3j5h3#2H3i4K6y4n7L8%4m8W2L8Y4g2V1K9h3c8Q4x3@1c8S2y4U0M7J5z5h3f1K6y4K6m8S2j5$3x3#2j5h3j5#2i4K6t1$3j5h3#2H3i4K6y4n7L8h3q4F1K9h3k6W2M7%4c8Q4y4h3k6$3k6i4u0K6K9h3!0F1i4K6g2X3j5$3!0V1k6g2)9K6c8o6t1H3x3U0x3I4x3o6V1H3x3e0m8Q4x3U0k6S2L8i4m8Q4x3@1u0J5k6i4y4G2L8s2g2@1K9h3!0F1i4K6y4p5x3e0j5H3x3q4)9J5y4e0u0m8z5e0l9H3i4K6t1$3j5h3#2H3i4K6y4n7k6s2m8A6i4K6y4p5x3K6t1H3i4K6t1$3j5h3#2H3i4K6y4n7N6i4m8V1j5i4c8W2i4K6g2X3N6X3g2J5M7$3W2G2L8W2)9#2k6X3y4G2k6r3g2Q4x3@1b7J5x3o6t1K6x3e0l9&6x3o6p5H3i4K6t1$3j5h3#2H3i4K6y4n7i4K6g2X3M7Y4c8A6j5$3E0W2N6q4)9K6c8o6p5%4x3o6p5I4y4o6b7&6y4K6p5$3x3e0m8Q4x3U0k6S2L8i4m8Q4x3@1u0A6M7#2)9#2k6Y4m8S2k6q4)9K6c8o6m8Q4x3U0k6S2L8i4m8Q4x3@1u0U0N6i4u0J5k6h3&6@1i4K6g2X3M7X3g2Y4K9h3!0F1i4K6y4p5g2g2y4Q4x3U0k6S2L8i4m8Q4x3@1u0S2M7s2m8Q4y4h3k6@1P5i4m8W2i4K6y4p5L8X3!0J5L8h3q4D9i4K6t1$3j5h3#2H3i4K6y4n7M7%4W2K6i4K6g2X3M7X3g2Y4K9h3!0F1i4K6y4p5g2g2y4Q4x3U0k6S2L8i4m8Q4x3@1u0E0j5$3y4Q4y4h3k6E0L8X3y4Q4x3@1b7K6x3e0l9I4y4W2)9J5y4X3q4E0M7q4)9K6b7Y4c8A6L8h3g2*7L8$3&6W2i4K6g2X3L8X3q4E0k6g2)9K6c8p5q4E0k6i4u0A6j5$3q4Q4x3U0f1J5y4e0u0r3f1r3S2G2k6h3&6A6P5q4)9J5y4X3q4E0M7q4)9K6b7X3y4S2M7Y4u0A6k6i4u0Q4y4h3k6J5k6h3N6A6L8$3&6Q4y4h3k6$3x3W2)9K6c8o6x3I4x3q4)9J5y4X3q4E0M7q4)9K6b7Y4u0W2M7$3W2V1k6h3&6U0k6g2)9K6c8q4g2e0i4K6t1$3j5h3#2H3i4K6y4n7j5i4m8H3i4K6g2X3L8r3q4F1k6%4g2S2k6$3g2Q4x3@1c8W2L8W2)9J5y4X3q4E0M7q4)9K6b7X3y4S2M7Y4u0A6k6i4u0Q4y4h3k6J5k6h3N6A6L8$3&6Q4x3@1c8g2f1#2)9J5y4X3q4E0M7q4)9K6b7X3q4U0x3W2)9K6c8s2N6A6k6X3V1#2k6#2)9J5y4X3q4E0M7q4)9K6b7Y4g2G2L8#2)9K6c8o6m8Q4x3U0k6S2L8i4m8Q4x3@1u0G2M7q4)9#2k6Y4u0W2k6$3W2G2L8W2)9K6c8q4g2e0i4K6t1$3j5h3#2H3i4K6y4n7N6r3W2E0k6i4A6G2L8X3g2Q4y4h3k6G2k6X3k6K6k6i4c8Q4x3@1c8Q4x3X3b7J5y4e0t1H3x3q4)9J5y4X3q4E0M7q4)9K6b7X3u0#2K9h3I4V1i4K6g2X3L8Y4g2E0j5X3g2J5i4K6y4p5x3K6q4Q4x3X3f1&6i4K6u0W2x3g2)9J5y4X3q4E0M7q4)9K6b7X3S2G2M7%4c8Q4y4h3k6S2j5X3W2Q4x3@1c8S2M7X3@1$3y4q4)9J5k6s2j5^5j5g2)9J5y4X3q4E0M7q4)9K6b7X3I4G2j5$3q4D9k6g2)9K6c8r3g2F1i4K6t1$3j5h3#2H3i4K6y4n7M7X3g2Y4K9h3!0F1i4K6y4p5g2g2y4Q4x3U0k6S2L8i4m8Q4x3@1u0@1M7#2)9K6c8o6p5%4x3o6p5I4y4o6b7&6y4K6g2Q4x3U0k6S2L8i4m8Q4x3@1u0U0k6r3W2V1i4K6y4p5z5o6R3@1z5o6M7@1y4K6u0Q4x3X3b7%4y4o6S2S2i4K6u0V1y4r3j5&6j5#2)9J5k6r3t1&6y4o6g2Q4x3X3b7^5k6h3u0W2y4o6l9#2x3X3u0U0x3e0S2Q4x3U0k6I4N6h3!0@1i4K6y4n7 let arg0 = Memory.allocUtf8String(str0); let str1 = decodeURIComponent("x-tt-bypass-dp%0D%0A1%0D%0Asdk-version%0D%0A2%0D%0Apassport-sdk-version%0D%0A19%0D%0Ax-ss-req-ticket%0D%0A1717052656600%0D%0Ax-vc-bdturing-sdk-version%0D%0A2.3.0.i18n%0D%0Ax-tt-dm-status%0D%0Alogin%3D0%3Bct%3D0%3Brt%3D7%0D%0Acontent-type%0D%0Aapplication%2Fx-www-form-urlencoded%3B%20charset%3DUTF-8%0D%0Ax-ss-stub%0D%0AE10ADC3949BA59ABBE56E057F20F883E%0D%0Acontent-length%0D%0A81%0D%0Ax-tt-trace-id%0D%0A00-c8504d6c010de75c6a96840a3f9a04d1-c8504d6c010de75c-01%0D%0Auser-agent%0D%0Acom.zhiliaoapp.musically%2F2022900010%20(Linux%3B%20U%3B%20Android%208.1.0%3B%20en_US%3B%20AOSP%20on%20taimen%3B%20Build%2FOPM1.171019.011%3B%20Cronet%2FTTNetVersion%3A55e3b3c8%202023-03-20%20QuicVersion%3Ad298137e%202023-02-13)%0D%0Aaccept-encoding%0D%0Agzip%2C%20deflate\n") let arg1 = Memory.allocUtf8String(str1); var sub9ad50 = new NativeFunction(addr_8bb80, "pointer", ["pointer", "pointer"]); var result = sub9ad50(arg0, arg1) console.log(result.readCString()) }
因为我多次不改参数调用和发现a3似乎固定,想着可能与入参有关,于是在统一参数之后,
直接搜索0xde06afa3
,可以看到是第五次(号有问题,入参是调用次数,出参是+1次数),看看入参(4)
入参是 0x00000001
0x72ff34bd20 4 入参0: 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 73020fab00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ 73020fab10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
python复现一下看看
确实对上了,
a3 就是 0x 00 00 00 01的sm3了
0xa3
是 0x00000001的sm3最后一组结果的最后一位
0xde06afa3
[3]
0x9e 是由 0x31 与 0xaf 异或 而来,分开追
搜索写入,
结果有点多,搜索最近一次的写入,可以看到是从0x7d85d095b9
地址取第一个字节,0x31
通过搜索发现,从 0x7d85d095b8, 4
读取四个字节,读了好几次,然后地址连续之后,对应的值是 0x71314d5e
,看看在哪里生成
地址减一下,看看调用位置,懵逼了,这Timi的不是随机数吗,后知后觉,这不就是d2的随机数,亏我跟这么久,都快放弃了,还好没放弃,睡前在挣扎一下
取跟d2用的随机数一样的数(0x71314de5
),取第2位 0x31
0x71314de5
[1]
从 0x77e110a688
读取值,为0xaf,跟上去
又是加载了一个字节,看看能不能跟这个地址0x77e0e4431a
继续跟
继续
发现,跟到这个地址,线索就中断了,看看这个0xaf
从哪来的
通过不看最后一位,发现,这个也是连续的读取, 0x782278306c, 4
,又仔细一看,这不是00 00 00 01,sm3的结果吗
0xaf
是从0xde06afa3
取的第3位
0xde06afa3
[2]
继续回到搜索关键词
memory read at 77e110a600, data size = 4,
可以看到0x48
是直接读出来的,看看哪里读的
搜索写入,又回到异或分支
memory write at 77e110a670
跟踪,又是加载一个字节
搜索 0x77e11095ba
依旧没有目标值,所以,还是不看最后一位搜索
其实第一次搜索,就已经看出来端倪,这个还是随机数(0x41fa4e54
)的第3位 0x4e
0x41fa4e54
[2]
看看0x06从哪来的,结合上面规律,大概率还是0x00 00 00 01
的sm3的最后4字节的第二位
可以看到,读取的地址都是一样的
所以 0x06
应该就是 0xde06afa3
的第二位
0xde06afa3
[1]
搜索关键词 memory read at 77e110a600, data size = 4,
按照规律,这次应该也是随机数与sm3的结果异或,验证看看
按照规律,随机数该取[3],sm3取[0]
随机数:41 fa 4e 54
sm3: de 06 af a3
对上了,确实如此
随机数:41 fa 4e 54
00000001_sm3: de 06 af a3
第一个:0x41 xor 0xa3 = e2
第二个:0xfa xor 0xaf = 55
第三个:0x4e xor 0x06 = 48
第四个:0x54 xor 0xde = 8a
手动计算后,对比前四个字节,确实可以对上
也是异或出来的,分开跟踪看看
这个0x41的地址有点眼熟,好像是随机数。。。
可以看到从 0x77e11095b8
读取一个字节
随机数的反转
读取随机数
继续加载
还有读取,继续跟
继续
最终跟到 0x77e110c008
接收了随机数的返回值,
地址 -4, 来到了 调用随机数的方法
读取了随机数 0x41fa4e54
的第1个字节
0x41fa4e54
[0]
已经知道了,为什么还要跟呢,因为日志不一样,d2 跟随机数的时候,用的是trace1的日志
跟踪看看,哪里写入
加载了一个字节,搜索看看
通过搜索 memory read at 77e0e4431
,可以看到规律
从0x77e0e44310
开始, 0x77e0e44318
开始是sm3结果的最后一组
先不考虑这么多,继续往上跟,跟到这里,没有写入了,看看这个 0xa9
怎么来的
通过搜索,也是一组数据,直接搜搜看
最终异或出来,并且组成8字节的,有点像分组运算,这里应该是加密算法了,
看执行流程,感觉像是sm3加密,往上搜了一下sm3的入口,和sm3的结束,发现,这个值生成在sm3中,
通过查看寄存器,长度是 0x10 ,大概率是body了,
python实现一下,确实如此,body的sm3的最后一个分组
body 经过 sm3 加密后(b68053a9
),取的最后一个字节
b68053a9
[3]
老规矩,先定位到位置,然后read 改成write
看到0xfa,想到了随机数 41 fa 4e 54
还是跟一下看看吧
跟到最后,也是这样,所以还是同一个随机数了
随机数的第2个字节
41 fa 4e 54
[1]
跟踪生成吧
读取一个字节,继续跟踪看看
继续跟踪
跟到这里,就到顶了,看看0x53
怎么来的
ps:结合上面的规律,这个0x53
应该也是body的sm3结果,也确实在里面,为了严谨,还是自己跟吧
确实是body_ sm3的结果,因为地址连续,且顺序一样
body 经过 sm3 加密后(b68053a9
),取的第3个字节
b68053a9
[2]
按照规律,这个应该是
随机数:41 fa 4e 54
[2]
body_sm3: b6 80 53 a9
[1]
可以自己尝试逆向看看
是的
按照规律,这个应该是
随机数:41 fa 4e 54
[3]
body_sm3: b6 80 53 a9
[0]
是的
随机数:41 fa 4e 54
00000001_sm3: b6 80 53 a9
第一个:0x41 xor 0xa9 = e8
第二个:0xfa xor 0x53 = a9
第三个:0x4e xor 0x80 = ce
第四个:0x54 xor 0xb6 = e2
手动计算后,对比前四个字节,确实可以对上
通过搜索,看到同样是异或,看到
0x41
还有规律,最后一部分,不会是query的sm3的异或吧。。
ps:这个不会还是随机数吧,根据前面的经验。。。
跟上看看
还是随机数,只不过这里是被反转了,上面还有rev反转,其实通过内存地址,也看出来了,跟随机数用一个地址
随机数:41 fa 4e 54
[0]
0xf6
的开始
继续跟
跟到这里,就没有结果了,看看规律
雀食,就是quert的sm3的最后
query_sm3的最后一组:e2 5d db f6
[3]
结合上面规律,最后一组可能是这样
随机数:41 fa 4e 54
query_sm3: e2 5d db f6
第一个:0x41 xor 0xf6 = b7
第二个:0xfa xor 0xdb = 21
第三个:0x4e xor 0x5d = 13
第四个:0x54 xor 0xe2 = b6
最后一部分:b7 21 13 b6
,正好对上,所以就不需要找了
吐槽:现在的圈子有个现象,分享思路的越来越少了,取而代之的就是发帖、引流、拉群、开星球、卖课,再也没见到相对于龙哥之外质量更好的文章了,强烈推荐一下龙哥星球,当然我的质量也不行哈哈哈,我这是随笔录和分享思路
更多【Android安全- 某加密的a26生成分析全过程】相关视频教程:www.yxfzedu.com