app sign-v2 签名算法 aes 加解密分析

android 逆向 23 / 38

本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!

推荐阅读

这个样本 unidbg 部分可以参考龙哥的 csdn 教程,这里就不再赘述了
龙哥 csdn 样本
更多 Unidbg 使用和算法还原的教程可见星球: 点击加入龙哥星球

前言

某右 app 参数分析,版本 5.7.3

charles 抓包

一共有三个加密参数 sign request response 一个一个来看,java 层的就不再分析了,可以参考龙哥样本

so 分析

先使用 unidbg 加载 so 查看动态注册的函数地址,先来分析 encodeAES 函数

0x1 encodeAES

ida 跳过来,主要查看这个函数

点进来可以看到,这里是标准的 AES_128_cbc 算法,调用的是 openssl

通过查找 openssl 相关的资料得知,j_EVP_EncryptInit_ex 此函数的 后面两个参数 分别是 aes 的 key iv
可以参考此文章: https://blog.csdn.net/viewsky11/article/details/78983234

0x2 sign

此函数是变形的 md5,龙哥的 csdn 已经放出 python 源码,这里就不再分析了

0x3 decodeAES

ida 跳转到 decodeAES 函数,主要分析此函数

这里跟加密逻辑相同,使用的 openssl 库解密,下面使用 frida hook 一下

frida hook

具体的 hook 代码,俺就不贴出来,大家自行写一下,有啥问题一起讨论哈,我这里主要是 hook 了 java 层的几个 native 函数,跟 so aes key iv 相关的函数

先来看下 encodeAES 函数部分

1、encodeAES 参数
2、aes key
3、aes iv
4、aes encrypt result,最后会把 aes iv 拼接到加密结果前面

这里是 sign 比较简单,就是拿着 aes 加密结果进行 md5 运算

这是 decodeAES 部分

1、decodeAES 参数,也是请求的响应值
2、aes key
3、aes iv,这里的 iv 正是 参数一的前 16 个字节
4、aes 解密结果,但不是明文,显然后面还有其他的处理
5、最后才是最终的明文

unidbg

下面开始使用 unidbg 跑起来,不过这个样本的 aes key iv 都是动态生产的,所以需要先把 key iv 固定才行
下面的话我就直接贴代码了,具体含义可以参考龙哥的文章
unidbg hook 使用大全

public void ReplaceArgByConsoleDebugger() {
    emulator.attach().addBreakPoint(module.base + 0x5E1A2, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            String fakeInput = "1b 4a 4a 59 59 59 59 e9 e9 f8 f8 f8 f8 09 09 09".replace(" ", "");
            emulator.getBackend().mem_write(0x403d2700, hexToByteArray(fakeInput));
            Inspector.inspect(emulator.getBackend().mem_read(0x403d2700, 16), " 0x403d2700 ");

            return true;
        }
    });

    emulator.attach().addBreakPoint(module.base + 0x5E140, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            String fakeInput = "c1 10 90 90 90 90 9f 9f 9f 9f be be be be ce ce ".replace(" ", "");
            emulator.getBackend().mem_write(0x403df040, hexToByteArray(fakeInput));
            Inspector.inspect(emulator.getBackend().mem_read(0x403df040, 16), " 0x403df040 ");

            return true;
        }
    });

    emulator.attach().addBreakPoint(module.base + 0x5d22a, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            String fakeInput = "de fd fd 0d 0d 0d 0d 1d 1d ac ac ac ac bc bc bc".replace(" ", "");
            int length = fakeInput.length();
            MemoryBlock fakeInputBlock = emulator.getMemory().malloc(length, true);
            fakeInputBlock.getPointer().write(hexToByteArray(fakeInput));

            emulator.getBackend().reg_write(ArmConst.UC_ARM_REG_R6, fakeInputBlock.getPointer().peer);

            return true;
        }
    });
}

代码写完跑起来,调用 encodeAES 函数,正常运行,结果跟 frida hook 出来的结果相同

在调用 sign 签名函数,结果也是相同的

最后便是 decodeAES 结果也是正常解密出来

最后

某右的分析到此结束,这里还有一个坑,就是 aes 解密之后还有一步处理,这个大家自行分析吧,总之就是要细心,不然可能会走很多弯路
此样本难度不高,主要是 key iv 动态生成的,会影响到 unidbg 的动态调试,这个搞完也算是,对 unidbg 的使用有了进一步的了解

最后附上 python 还原的效果图,有啥问题可以一起讨论哦

暂无评论
本文作者:
本文链接: https://www.qinless.com/?p=922
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 qinless 的博客!
100

发表评论

返回顶部