某右app协议的防护主要是两大块,请求签名 sign 字段,以及请求体和返回体的加密
设备: ios8,
ios版本:14.7.1
app:某右6.2.6
frida: 14.1.8
ida: 9.0
抓包分析
由上图看出从协议层面看出,有 sign / body / response body的这些防护
app脱壳
使用巨魔安装 AppsDump2进行脱壳
使用 Filza 打开文件目录,利用爱思助手导出到电脑
协议分析
这块内容主要是使用frida + ida 进行动静态分析。
3.1 使用frida-trace 定位代码关键点
frida-trace 使用方法,参考 frida-trace使用方法
frida-trace -UF -m "+[NSURL URLWithString:]"
// +[NSURL URLWithString:] 是ios中构造URL的方法
// + 代表类方法
// NSURL 是类名
// URLWithString: 是方法名
使用该命令会在当前目录生成文件夹
修改 URLWithString_.js
{
onEnter(log, args, state)
{
// 为什么是第3个参数?在oc方法中, args[0] 是表示 self, 就是自身
// args[1] 表示 _cmd,即当前方法的选择器(selector)
var args2 = new ObjC.Object(args[2]);
// 筛选相关URL, 避免输出过多内容
if (args2.toString().indexOf('account/login') !== -1) {
// 打印出请求url
log(`+[NSURL URLWithString:${args2}]`);
// 打印出调用堆栈,向上跟踪关键点
log('NSURL URLWithString: called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
}
}
,
onLeave(log, retval, state)
{
}
}
以上就是 frida-trace
打印出来的调用堆栈,根据 偏移地址
来定位代码位置,每一行有两个地址,第一个是在内存中的实际地址,第二个则是偏移地址,可以使用偏移地址来定位的代码点
打开 ida输入 G
来地址 跳转, 我们先定位一个地址 0x2de2084
, ida中的基址是 0x100000000
既在ida中输入的地址应该是 0x102de2084
跳转到堆栈点,进行 F5
返汇编进行查看
找到关键信息 sign
使用 frida-trace
我们很快就找到了代码的关键点
3.2 sign代码分析
可以看到是导入的动态库,我们去ipa中打开看看
使用 ida 打开该动态库
找到 sign代码的实现,代码中有 MD5String字眼,先盲猜md5。
进到函数去看看, 看起来和普通的也没什么差别, 我们看一下 MD5 的魔数
发现该魔数和常正常MD5不一样
正常的魔数是这样的。
替换魔数测试与app生成结果一致,签名算法分析完毕
python版本md5
3.3 body加密分析
可以看到这是请求体加密的关键代码,从函数名来看就是aes的加密,知道aes加密我们接下来需要确定 key, iv(ecb模式不需要iv),加密模式
跟进 cipher_encode_aes 方法
查看对应的逻辑
Tips: EVP_CIPHER_CTX_init/EVP_EncryptUpdate 这种 EVP开头的都是openssl里面的函数
hook得到 key 和 iv
现在来查看加密前的明文是什么
加密前明文
加密后密文
与抓包中的一致
这里发现密文的头部16位与 iv 值一致,怀疑是将iv加在头部,发送给服务端,服务端能顺利解密。
接下来我们去试一试能不能顺利解密
顺利解密成功,但发现前面部分有乱码,这大概率是内容填充,我们正常填充是填充在尾部的,他这里填充到了头部。
使用python复现该填充方法。
经过多次调试发现,key,和 iv 都是变动的,key是每次打开app会变,iv是每次加密都是随机的,所以说为什么要把iv加在密文前面。后续在分析key是怎么生成得来的。
3.4 返回体解密分析
从函数名来看 +[libProtocol decode_aes:ungzip:] 这是一个aes 的gzip 的算法
Tips gzip压缩的特征开头为 1f 8b
这是返回的文本,我们接下来看如何把他解密成明文
进入 cipher_decode_aes
可以看到解密的逻辑是正常的, hook EVP_DecryptUpdate 函数来看看key 和 iv
hook到了key 和 iv 了,通过仔细观察,返回的密文也是将 iv 放在了消息头部,那么我们现在有了key和iv就可以去解密试试
解密成功,但是还是一段看不懂的内容,前面我们提到通过函数名来看,还有gzip压缩算法。
代码里面也有体现,那我们现在去解压缩一下试试。
发现压缩失败!!
看一下十六进制内容,发现 1f 8b 的关键信息, 1f 8b 是gzip 压缩的开头,我们从这开始解压缩试一试。
咦!发现解压缩成功。到此返回体解密结束
3.5 aes key 分析
按 x
查找引用
发现是在 init_cipher
中初始化的。
然后将 aes key 进行 rsa 加密,经过调试发现,经过 rsa 加密的 aes key 是在请求头中带着的
x-xc-proto-req
rsa加密逻辑可以看出是获取公钥,然后使用 rsa sha256加密的。
分析完毕!