本文主要是介绍某团App之mtgsig2.4算法分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.3mtgsig参数分析:
a0:mtgsig版本号(这里分析2.4)
a1:appkey(相同版本app此值固定)
a3:Android设备版本
a4:时间戳
a5:加密的设备信息1
a6:固定值
a7:xid
a8:dfp
a9:加密的设备信息2
a10:a2参数加密时需xor的随机数
x0:固定值
a2:sign值
2.dfp参数构造
基于对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算法一致
2.1算法流程
dfp算法步骤
1."0000"+uuid(去除'-')+时间戳(十六进制)+"0"+CRC(前面部分)
2.0000 8a8921de5fc14ed1b428d1d7485f99c1 18bc6958715 0 eb79a8ab
3.以上内容转成hex
4.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 ab
5.固定hex(多次测试目前版本app该值固定)
6.两组hex进行xor得到结果取大写
2.2算法分析
2.2.1unidbg模拟执行并寻找切入点
1.从生成时间戳入手,分析地址0x17bf5(GetStringUtfChars),全局一共两处调用,第一次是uuid,第二次是时间戳
2.结合ida代码和unidbg调试代码分析方法的执行逻辑
2.2.2结合trace日志分析GetStringUtfChars前后调用逻辑
1.0x6F68E -> bl sub_17bc4
2.0x17bc4 -> GetStringUtfChars
3.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内容)
3.Xid参数构造
这里描述的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参数分析】
3.1算法流程
xid算法步骤
1.AES_data = '0'+dfp+'1'+时间戳(10进制hex)
2.AES_KEY='meituan1sankuai0'
3.AES_IV='0102030405060708'
4.AES_CBC(AES_data) -> base64
3.2算法分析
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'
4.a5参数构造
4.1算法流程
1.设备信息进行zlib压缩
2.压缩内容进行魔改RC4算法
3.最后结果进行base64
4.魔改RC4的key:固定hex xor (a1+a3+a4)
4.2算法分析
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压缩数据,解压缩得设备信息
5.a9参数构造
5.1算法流程
1.设备信息zlib压缩
2.crc32获取校验值
3.AES_KEY=crc32+'MXMYBS@H'
4.AES_CBC(zlib压缩信息,iv='0102030405060708')
5.a9=crc32+aes加密结果
5.2算法分析
1.a9:"c0ee827xGyF...pJrn4",对base64方法hook,获取和a9一样的返回值2.发现和a9很像的部分,猜测a9是两部分组成;找到base64的入参地址,tracewrite看哪里对这个地址进行了赋值 0x402ff1003.通过ida发现这个地址0x9d800方法很像aes算法,但是是否魔改还不知道,继续hook分析4.末尾看,aes的赋值肯定是在最后,所有搜索*a2 = HIBYTE(v7);的地址,并且存在0x1b的,a2[1] = BYTE2(v7);地址,并且存在0x21的,则代表是我们要找的执行方法(过滤一下是因为其他地方可能也会调用到这个地址,并且值刚好一样)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存在该地址的时候进行断点打印该地址是否赋值)
6.a2算法构造
6.1算法流程
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位重新计算得最终结果
6.2算法分析
1.unidbg模拟执行得到a2= ... 2a e1 a6 5f cc ac 28 30;直接010中查找哪里生成和赋值得位置;结果非常多,关键赋值位置附近是否还有对其他得几个值赋值,(搜索str.=0x30)最终定位到0x0e033这个位置2.向上找到该地址所在得方法,0xdf04方法入参是0x10字节大小内容,返回值则是构造好得a2,经过代码分析发现是将后16位进行计算得到a2
3.通过对tracewrite定位到赋值位置(入参0x4037fe10赋值得位置)
4.返回地址前是blx r2,证明该方法内进行了赋值;定位发现r2的地址都一样,查看内部哪里有str之类的赋值指令,并且详细搜索0xdf对指定地址的赋值
5.接下来要找这个地址所在的方法,其中传入参数,最后能够生成结果的大方法;找方法的思路:从该地址向上找bl调用方法的地方,unidbg进行调试分析返回值、找到生成的末尾,根据lr返回地址判断哪里调用的(在最末尾赋值处搜索赋值地址)
6.分析以下包括赋值地址的位置,是否赋值完成,以及,该地址附近的方法是否方法的末尾,最终定位到0x0db56是方法末尾,而0xDB52则是方法调用位置(hook该地址看入参和出参)
.参看入参哪里返回,根据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|
xor
00000000 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|
xor
0x14
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这个地址赋值)
18.到这里基本确定该值也是固定得,具体解法并未深入分析
7.获取dfp请求和获取xid请求
[dfp]:https://appsec-mobile.meituan.com/v5/sign
[xid]:https://appsec-mobile.meituan.com/fingerprint/v1/info/report
1.重点是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算法一致,区别在于设备信息不同
8.a2中DFA差分法获取AES_KEY
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.htm
8.其中重点定位到第九轮,和AES算法得结果,也就是第10轮后得结果;使用方式:先获取正确得结果,在随机修改第九轮入参中Input得一个字节,并获取错误得故障结果;使用python脚本进行key10得获取;如果正确会获取到key,否则得不到key,如果得不到key则分析aes算法前后,是否选择得结果不对9.通过key10获取key得工具链接:GitHub - SideChannelMarvels/Stark: Repository of small utilities related to key recovery
这篇关于某团App之mtgsig2.4算法分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!