可以看到 请求中"sign=v2-xxxxxxxxxx"老样子 拖入ida中分析 进行字符串搜索"sign="
第四个看起来比较像 双击字符串进入
按下快捷键X
只有一处 我们还是双击进入
继续按下快捷键X
从函数名来看的话"-[ZYURLRequest obtainMostSuitableRequest]"比较像 此处没什么捷径 只能通过看哪个函数名像 如果选错了就会浪费些时间
双中双击进入 直接F5查看伪代码
可以看到通过传参调用"+[libProtocol sign_data:]"函数来进行签名的 参数又是通过传参调用"+[libProtocol encode_aes:]"得到的
1 2 3 4 5 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | %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" 先来看下参数是什么
1 2 3 4 5 6 7 8 9 | 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
那么直接编写代码进行测试
1 2 3 4 5 | 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]函数返回的数据是明文数据
最新版本的变化有两处
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:]"得到的
1 2 3 4 5 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | %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" 先来看下参数是什么
1 2 3 4 5 6 7 8 9 | 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
那么直接编写代码进行测试
1 2 3 4 5 | 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是如何生成的就留到下次分解了 有时间的话我会再编辑到本篇文章末尾
至此某右的请求及返回数据的加密与解密流程分析完毕 至于aeskey是如何生成的就留到下次分解了 有时间的话我会再编辑到本篇文章末尾