Y29tLnNhbmt1YWkubWVpdHVhbg==
[1]我是小三大佬对2.0版本的参数分析https://www.cnblogs.com/2014asm/p/15391247.html[2]qxpy大佬对1.5版本的a2分析https://mp.weixin.qq.com/s/S_3tM_TbOfbBRprmQGDwrA[3]qxpy大佬对2.1版本的a5分析https://mp.weixin.qq.com/s/bfGvUyIN8aS4Y1KkOWwRpQ[4]TS大佬对风控参数的分析https://blog.vivcms.com/2021/01/07/429.html[5]houjingyi大佬对libmtguard.so混淆的还原分析https://bbs.kanxue.com/thread-271853.htm
a0:mtgsig版本号(这里分析2.4)a1:appkey(相同版本app此值固定)a3:Android设备版本a4:时间戳a5:加密的设备信息1a6:固定值a7:xida8:dfpa9:加密的设备信息2a10:a2参数加密时需xor的随机数x0:固定值a2:sign值
基于对libmtguard.so的JNI方法main函数hook,如下图:
以上图片分析:1.调用main(47)前就已经生成过mtgsig参数,证明dfp已经生成并通过对比main(47)返回值和mtgsig['a8']相等,验证猜想2.unidbg模拟执行时,如果main(47)前调用了main(1),则会在全局变量中存储dfp并在main(47)调用用时存储到/data/data/xxx/file/.mtg_dfpid文件中3.unidbg模拟执行时,如果只调用main(47),则会自行生成uuid和时间戳等参数构造dfp并存储到上述文件中4.后续会发现mtgsig['a8']值会发生改变(通过后续分析则是请求返回)
这里分析来源unidbg只调用main(47)的逻辑,猜测main(1)中生成dfp算法一致
dfp算法步骤1."0000"+uuid(去除'-')+时间戳(十六进制)+"0"+CRC(前面部分)2.0000 8a8921de5fc14ed1b428d1d7485f99c1 18bc6958715 0 eb79a8ab3.以上内容转成hex4.00 00 8a 89 21 de 5f c1 4e d1 b4 28 d1 d7 48 5f 99 c1 18 bc 69 58 71 50 eb 79 a8 ab5.固定hex(多次测试目前版本app该值固定)6.两组hex进行xor得到结果取大写
1.从生成时间戳入手,分析地址0x17bf5(GetStringUtfChars),全局一共两处调用,第一次是uuid,第二次是时间戳2.结合ida代码和unidbg调试代码分析方法的执行逻辑
1.0x6F68E -> bl sub_17bc42.0x17bc4 -> GetStringUtfChars3.0x6f2bb -> bl #0x40006e22(解密字符串得到'0000')4.0x6f2e1 -> bl #0x40012aa4(拼接字符串:'0000'+uuid)5.0x6f333 -> bl #0x4002aa18(CRC算法,查看入参:"0000"+uuid(去除'-')+时间戳(十六进制)+"0")6.0x6f375 -> bl #0x4000c8f4(拼接"0000"+uuid(去除'-')+时间戳(十六进制)+"0"+CRC(前面部分))7.0x6f389 -> bl #0x4006ee60(入参:上诉拼接好的字符串,返回:dfp)8.0x6efe7 -> bl #0x4006e968(String to Hex)9.0x6ef61 -> eors r1, r0(r1则是so中固定hex,r0则是StringToHex内容)
这里描述的xid是指在请求fingerprint/v1/info/report获取真正的xid之前使用的a7构造main(1)和main(2)的时候,都会生成a7,如果指定了.mtg_dfpid_com.sankuai.meituan文件,可以发现生成的a7并非此文件的xid(文件中的xid是请求返回的,抓包时的a7就是该值) 猜测我构造的unidbg可能并不完善,并没有读取到已经返回的a7,那么此时的a7有可能是自己加密生成的,分析代码,看a7如何构造,然后抓包分析获取真正xid之前的mtgsig参数中的a7,对比加密是否一致【以下分析是在分析a9参数时,发现的一个aes算法中打印发现,具体如何寻找aes算法后续a9参数分析】
xid算法步骤1.AES_data = '0'+dfp+'1'+时间戳(10进制hex)2.AES_KEY='meituan1sankuai0'3.AES_IV='0102030405060708'4.AES_CBC(AES_data) -> base64
1.unidbg对标准AES算法0x9dfc5下断点调试 2.通过入参很容易分析出'0'+dfp+'1'+时间戳(10进制hex),至于后面的1+6551f39f,根据经验分析8位6xxxxx这样的hex,可能就是时间戳10位的hex 还有时间戳13位的hex,就是11位的18cxxxx这样的开头(后续也会用到)3.通过unidbg的blr指令查看调用AES算法0x9dfc5的位置,并分析so层,找到key初始化的地方和iv的地方 4.0x2ABF6 -> bl sub_9D32C 就是key初始化的地方,可以获取到key,至于iv,则mt大部分iv都是'0102030405060708'
1.设备信息进行zlib压缩2.压缩内容进行魔改RC4算法3.最后结果进行base644.魔改RC4的key:固定hex xor (a1+a3+a4)
1.a5='EGQJ3E...VR6X=',明显的base64编码,在so文件中定位base64编码进行分析2.搜索'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 3.交叉引用定位引用位置 4.unidbg对0xfe6c下断点进行调试,并且blr找到调用base64的位置 5.定位base64的入参哪里来,如上图发现是0xbdc2调用一个方法来的(分析后是魔改RC4),如果不严谨还可以结合trace日志向上分析 6.分析0xbdc2调用方法内部逻辑,结合RC4源码,发现类似:v9 = *(result + v7); *(result + v8) = v9这样的代码,猜测就是RC4算法,而RC4算法在加密前会进行密钥初始化,上面的图片中可以知道在调用RC4算法前还有一个0xbdb8调用了0x2af9c方法,明显这个就是rc4_init方法,而参数2就是key,参数3就是key_len 7.unidbg验证猜想 8.使用RC4算法工具去计算,发现结果还是不对,这是因为魔改了RC4,在RC4方法代码对比没有问题,那么可能问题出现在rc4_init上 9.下面分析RC4的KEY怎么来的,对key的地址0x402ed090进行tracewrite,搜索哪里对这个地址进行了写入 10.分析0x2b8a8地址前后的代码,看该值如何获得 11.Key是xor而来,分析xor的数据内容,很容易分析出是a1+a3+a4的值xor固定值,至于rc4的入参,直接unidbg 下断点看内容就知道是0x78、0x9c开头的zlib压缩数据,解压缩得设备信息
1.设备信息zlib压缩2.crc32获取校验值3.AES_KEY=crc32+'MXMYBS@H'4.AES_CBC(zlib压缩信息,iv='0102030405060708')5.a9=crc32+aes加密结果
1.a9:"c0ee827xGyF...pJrn4",对base64方法hook,获取和a9一样的返回值 2.发现和a9很像的部分,猜测a9是两部分组成;找到base64的入参地址,tracewrite看哪里对这个地址进行了赋值 0x402ff100 3.通过ida发现这个地址0x9d800方法很像aes算法,但是是否魔改还不知道,继续hook分析 4.末尾看,aes的赋值肯定是在最后,所有搜索*a2 = HIBYTE(v7);的地址,并且存在0x1b的,a2[1] = BYTE2(v7);地址,并且存在0x21的,则代表是我们要找的执行方法(过滤一下是因为其他地方可能也会调用到这个地址,并且值刚好一样) 5.交叉引用sub_9d800发现两个方法调用,通过上面的定位,确定是哪个方法调用的,也可以unidbg进行blr,但是如果是aes算法,可能很多地方都调到这个函数,太麻烦了,所以使用静态分析 6.最终发现是:0x9DFC4方法中调用了0x9e05f: "bl #0x4009d800" 这个方法,直接通过unidbg对0x9DFC4进行调试,可以得出这个就是标准的aes算法(最终定位到调用逻辑 0x2ac11 -> 0x9DFC4 -> 0x9d800)(aes算法前后对key进行了初始化) 7.对aes加密入参进行分析,发现也是0x78 0x9c开头,zlib压缩了,解开就是设备信息明文8.对key进行分析,发现key是0x402d950c这个地址(分析这个地址的赋值情况,和上面一样tracewrite分析) 9.memcpy (目标地址,拷贝地址,len)(000AD960 MOVS R0, R6 分析这个地址的r0是0x402d950c的时候,并且看拷贝地址,再次找拷贝地址的值的来源) 10.发现两处来源,最终根据r1定位到第二处。因为r1 0x4037fcc0 存在0xbc的赋值(最终发现key也是xor来的,固定hex xor 未知hex) 11.接下来找xor另外部分的来源 0x402d952c(可以发现0x402d952c的内容,也就是xor部分的前半部分和a9的前缀一样 c0ee827)(0xad3dd地址也是定位到memcpy,所以找r1) 12.以上办法定位r10xbffff4a4时,定位到libc去了,找不到哪里赋值(搜索地址0xbffff4a4,如下,对一些push存在该地址的时候进行断点打印该地址是否赋值) 13.发现了r2=0xc0ee827(搜索0xc0ee827查找来源) 13.结合ida分析,发现该位置就是CRC算法 0x2AA18,而入参则是设备信息 14.key后半部分'MXMYBS@H'则是固定值,如下:此数据来源于app中的文件解密得来,a2还原时详细说明
1.获取xor随机数(获取时间戳-设置随机数种子-生成随机数-计算随机值并结果+1)(该值还体现在mtgsig['a10'])2.计算hmac_sha1_key(pic解密获取a0并重新排序 - xor appkey - xor 上面随机数)3.hmac_sha1加密(body是请求body+mtgsig(除a2))4.hmac_sha1的结果做AES加密(白盒AES)(起初以为魔改AES,后续通过DFA差分法攻击拿到了key)5.AES结果后16位重新计算得最终结果
1.unidbg模拟执行得到a2= ... 2a e1 a6 5f cc ac 28 30;直接010中查找哪里生成和赋值得位置;结果非常多,关键赋值位置附近是否还有对其他得几个值赋值,(搜索str.=0x30)最终定位到0x0e033这个位置 2.向上找到该地址所在得方法,0xdf04方法入参是0x10字节大小内容,返回值则是构造好得a2,经过代码分析发现是将后16位进行计算得到a23.通过对tracewrite定位到赋值位置(入参0x4037fe10赋值得位置) 4.返回地址前是blx r2,证明该方法内进行了赋值;定位发现r2的地址都一样,查看内部哪里有str之类的赋值指令,并且详细搜索0xdf对指定地址的赋值 5.接下来要找这个地址所在的方法,其中传入参数,最后能够生成结果的大方法;找方法的思路:从该地址向上找bl调用方法的地方,unidbg进行调试分析返回值、找到生成的末尾,根据lr返回地址判断哪里调用的(在最末尾赋值处搜索赋值地址) 6.分析以下包括赋值地址的位置,是否赋值完成,以及,该地址附近的方法是否方法的末尾,最终定位到0x0db56是方法末尾,而0xDB52则是方法调用位置(hook该地址看入参和出参) 7.参看入参哪里返回,根据tracewrite搜索对该地址写入位置,定位到0x10044地址,而0x10044地址所在的方法很像sha1,hook验证一下 8.通过hook 0xFFA8 地址,发现就是sha1,并且调用了两次,第一次入参是一段内容+body,第二次入参则是一段内容+前一次sha1结果 9.这里想看ida伪代码但是没有恢复混淆,所以看不了,但是到这里可以发现这个特征和xxx其中用到的一个算法很像,hmac算法 10.直接hook 调用sha1的方法,看入参和出参(通过在线算法工具测试) 11.分析key得来源:除了tracewrite来定位对某个地址写入,还可以在trea日志中搜索(str.=0x6f.*0x402da280) 12.仔细分析会发现,0x0e3ad地址异或后的结果在0x0e3b1地址进行异或0x14
00000000 42 49 37 34 46 49 66 64 39 30 4b 6c 54 69 6c 31 |BI74FIfd90KlTil1|00000010 6d 30 69 37 46 46 2f 6e 30 62 68 59 69 68 4e 6b |m0i7FF/n0bhYihNk|00000020 72 4a 2b 75 |rJ+u|xor00000000 39 62 36 39 66 38 36 31 2d 65 30 35 34 2d 34 62 |9b69f861-e054-4b|00000010 63 34 2d 39 64 61 66 2d 64 33 36 61 65 32 30 35 |c4-9daf-d36ae205|00000020 65 64 33 65 |ed3e|xor0x14
13.0x0e3ad地址其中一个内容是appkey,另外一处并不指定,还有就是0x14怎么来的?(如下搜索0x14赋值指定地址位置,定位到地址,在Ida分析,发现如下特征:时间戳作为随机数种子,生成随机数传入0x11a58调用的方法进行计算,得到的值在加1) 14.而另外一组xor的内容,通过ldrb r0, [r0, r5]" r0=0x405b82dc取值可以知道是在0x405b82dc这个地址进行获取内容,并且分析这几次的取值,发现是在这个地址内取几段数据拼接起来 15.通过tracewrite定位到0xad96b这个地址返回,而在这个地址上面调用的是memcpy,明显是拷贝赋值,那么查找r0=0x405b82dc时的memcpy,并且地址则是在0xad96b上面的memcpy的r0赋值处 16.定位到地址0x405b81e0 (发现是 0x4037647b这个地址赋值) 17.而在unidbg中查看该地址的内容发现并不是内容开始位置,应该还有很多内容;最终定位到0x40376300这个地址开头 18.到这里基本确定该值也是固定得,具体解法并未深入分析
[dfp]:https://appsec-mobile.meituan.com/v5/sign[xid]:https://appsec-mobile.meituan.com/fingerprint/v1/info/report1.重点是data的加密,分两部分,两个base64相加,而main(41)返回data数据2.通过unidbg分析到0x92653这个地址进行了iv和data的异或(向下分析发现类似aes的查表法,白盒aes)3.多次hook发现有概率走了aes正常算法,但是key会改变,经测试发现,base64前部分应该是rsa加密的key,如果这部分不变则key不变4.而正常的aes算法走的是0x2ac11地址,和上面正常的aes_cbc算法地址一致5.dfp和xid得请求body算法一致,区别在于设备信息不同
1.根据trace日志,定位到10轮的循环2.其中0x2bdfd地址找到对input内容的读取(这里注释Input内容就是上面hamc_sha1的结果前16字节)3.通过对input内容左移后找到表中数据,最终通过表的数据进行异或得到AES查表法中TE表的内容,之后进行异或得到,每一轮的结果(4字节input数据获取到4个TE表的内容进行异或)4.0x2bea3地址是开始xor得到TE表的数据,后续通过其他算法来模拟了异或运算,得到最终每一轮的结果5.其中在input内容获取TE表内容时,和轮数还有当前Input内容的下标都关联了运算6.差分法攻击是在第9轮时,随机修改1个字节得Input,然后得到结果,通过系列公式计算(可参考资料差分故障攻击的原理.pdf)7.使用工具:https://github.com/SideChannelMarvels/JeanGrey/tree/master/phoenixAES;参考文章:https://bbs.kanxue.com/thread-254042.htm8.其中重点定位到第九轮,和AES算法得结果,也就是第10轮后得结果;使用方式:先获取正确得结果,在随机修改第九轮入参中Input得一个字节,并获取错误得故障结果;使用python脚本进行key10得获取;如果正确会获取到key,否则得不到key,如果得不到key则分析aes算法前后,是否选择得结果不对 9.通过key10获取key得工具链接:https://github.com/SideChannelMarvels/Stark
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
wx_墨_198 大佬 解密PNG得到PIC的关键代码是怎么定位的?
shmilyaxy 请求dfp的加密算法能讲讲吗
OnlyThen 你确认DFA恢复出来的密钥是正确的嘛[em_87]
mb_fssslkzs tql 评论区 肯定有故事
mb_rjdrqvpa mt难点是风控,算法很多人有,但是就算算法再完美,过不了风控没什么用。
我只是没人要 mt的vmp真是一点没说….