查看原文
其他

最右sign-v2签名算法追踪及逆向还原

尐进 看雪学苑 2022-07-01

本文为看雪论坛优秀文章

看雪论坛作者ID:尐进



本篇文章应该于N个月前就写了,由于拖延症一直拖到现在。


其实一直打算写一系列逆向实战,比如某音、某手、某乎、某宝,也不知道会不会有时间且不拖延的写下去。


好了言归正传,上次分析的最右APP版本为4.2.1 已经是18年10月的时候了 当时签名算法只有一个"sign" ,而本次分析的是目前最新版本5.5.9 。


最新版本的变化有两处:

1.新增了"sign-v2"算法

2.request data 以及 response data 内容进行了加密


OK我们直接来抓包,具体如何抓包上篇文章有讲,就不在此具体描述了。



可以看到 请求中"sign=v2-xxxxxxxxxx"老样子 拖入ida中分析 进行字符串搜索"sign=":



第四个看起来比较像双击字符串进入:



按下快捷键X:



只有一处 我们还是双击进入:

继续按下快捷键X:



从函数名来看的话"-[ZYURLRequest obtainMostSuitableRequest]"比较像 此处没什么捷径,只能通过看哪个函数名像,如果选错了就会浪费些时间。


双中双击进入,直接F5查看伪代码:



可以看到通过传参调用"+[libProtocol sign_data:]"函数来进行签名的 参数又是通过传参调用"+[libProtocol encode_aes:]"得到的:


v240 = +[libProtocol encode_aes:](&OBJC_CLASS___libProtocol, "encode_aes:", v239);v241 = objc_retainAutoreleasedReturnValue(v240);v242 = +[libProtocol sign_data:](&OBJC_CLASS___libProtocol, "sign_data:", v241);v243 = objc_retainAutoreleasedReturnValue(v242);v249 = objc_msgSend(&OBJC_CLASS___NSString, "stringWithFormat:", CFSTR("?sign=%@"), v243);

直接HOOK:

%hook libProtocol+ (id)encode_aes:(id)arg1 { %log; id result = %orig; HBLogDebug(@"[Hook] libProtocol encode_aes] ret: %@", result); return result;}+ (id)sign_data:(id)arg1 { %log; id result = %orig; HBLogDebug(@"[Hook] libProtocol sign_data] ret: %@", result); return result;}%end // hook libProtocol class end


日志打印如下:



先复制出encode_aes的参数 保存hex查看:



可以看到参数是明文的,既然是aes加密那就需要key,至于key是什么 如何产生的我们后面再来分析。


我们先进入内部查看签名算法是如何实现的 F5代码如下:



关注点在一个函数"MD5String" 先来看下参数是什么:


v3 = objc_retain(a3, a2);v4 = (void *)objc_retainAutorelease(v3);v5 = objc_msgSend(v4, "bytes");v6 = objc_msgSend(v4, "length");v7 = (size_t)v6;v8 = (void **)operator new(((unsigned __int64)v6 + 16) & 0xFFFFFFFFFFFFFFF0LL);memcpy(v8, v5, v7);v28 = v8;MD5String(&v28);

相信看到这里各位已经明白了参数是什么,参数就是aes加密后的数据,只是做了层转换,从NSData转为byte。

根据函数名得知该算法是md5,那么直接编写代码进行测试:

d = bytes.fromhex('8a07d175 47300202 02ead3bc bcbca5a5 19b21e13 1186e096 2a467fa5 661081c1 65d014f7 2a74a7bf 333c2a27 5937de20 25d2c4f9 c232a50a 3e90affc 319ca0ee b0e34df3 016bf74d a231d5da 41fde907 f6242573 f20d38d2 86e61d42 0487db3b bf029d65 a0733533 198b6194 63db3d3c fe234f84 7dcdee21 2521ab89 7f48e3f2 5d002559 7b5e814b 55fe2581 bec64b24 5082bd16 9910e2f8 e24cf3e8 e4346e3c 40f43237 cc75baff 0d97aea6 9f4c04d9 8f6d9f5f 91c31faa dbbda58d 13664d3a f5d7dd77 625f3559 91e74de9 4fcb3149 f9d54897 b2ac8ee4 2a613df6 cbdeda5e 98c9ba39 cdd717f9 19e7cbad 42c171d6 03d09daa b42aa123 66da3320 eddaf432 b655cc97 93280ee9 94687272 7d724658 8492a7b3 8b6ae9a7 bd33d63f 1f122155')md5 = hashlib.md5()md5.update(d)print(md5.hexdigest())# f94fd832969b8655eab3078e924b989e


结果发现计算结果不对。


好吧,看来它并不是简简单单的MD5算法了。大概率是魔改过的md5算法,那么直接上手,先看下MD5String调用了多少函数:



也没几个函数,那么就不管他改了什么,直接上手还原算法吧。当然你也可以下载MD5算法源码进行调试对比算法差异。


以下是还原出的算法,直接放源码。由于算法过长,论坛发帖无法放下,所以直接放到附件里了。



OK 结果跟手机上算出的一致,到这里sign-v2算法就还原完了。


至于AES加密中key的来源我们大概看下,后续有时间的话我会在帖子中补充。


在之前我们Hook了 +[libProtocol encode_aes:] 。我们直接在IDA中搜索一下类名"libProtocol":



set_portocol_key和get_portocol_key 看起来比较像设置key和获取key的函数,我们直接Hook。


日志打印如下:



抓包工具如下:




抓包工具对比可以看到加密key 在Headers["X-Xc-Proto-Req"]字段中,通过调用[libProtocol get_protocol_key]函数获取。


而request data为[libProtocol encode_aes]加密后的数据,那么具体aes key是如何产生的呢?这个容我日后再做分析。


可以看到response headers['X-Xc-Proto-Res'] 也有疑似加密key的数据,截图对比 [libProtocol set_protocol_key] 设置的参数为respnose headers['X-Xc-Proto-Res']字段的数据。

截取response data hex数据查看对比,可以看到[libProtocol decode_aes]参数就是请求返回的数据,而且[libProtocol decode_aes]函数返回的数据是明文数据:


至此最右的请求及返回数据的加密与解密流程分析完毕,至于aeskey是如何生成的就留到下次分解了。有时间的话我会再编辑到本篇文章末尾。

如果你们有什么APP想看的可以在评论区留言,我可能也会更新哦(有时间的话)。

首发看雪论坛,转载请备注来源。



- End -



看雪ID:尐进

https://bbs.pediy.com/user-home-608025.htm

  *本文由看雪论坛 尐进 原创,转载请注明来自看雪社区。



2.5折优惠票数量有限,先到先得哦!

推荐文章++++

* 浅析一个海莲花样本

* Safe-Linking机制分析及绕过

* 萌新逆向学习笔记——CreateRemoteThread注入Shellcode

* 反汇编代码还原之特殊除法还原

* CVE-2009-0927POC分析







公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



求分享

求点赞

求在看


“阅读原文”一起来充电吧!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存