android app sig 参数 so 加密逻辑逆向分析

android 逆向 29 / 37

前言

样本下载 https://www.wandoujia.com/apps/37577/history_v9080
搜索接口 sig 参数分析

charles 抓包

就是这个 sig 参数

java 层分析

直接全局搜索 sig 关键词即可

最终是定位到了这个函数 com.meitu.secret.SigEntity.generatorSig

调用 SigEntity.nativeGeneratorSig 执行加密逻辑

native 函数在 librelease_sig.so 文件里

so 分析

librelease_sig so 文件都是静态注册的函数,也没啥对抗分析,打开即可分析

打开 so 可以看到符号都没混淆,逻辑还是比较清晰的。先来看看 ValidateKey::getValidateResult 函数逻辑

进来这里调用了 JavaHelper::getAndroidAPKKeyHash 函数,看起来像是校验 apk 签名

点进来逻辑很清晰一眼望去,确实是获取签名。下面再来看 GeneratorSIG sig 生成函数

刚开始掉用了一个 GetSecretKey 函数,获取 key,接着是拼接一些不明的字符串,最后调用了 MD5_Calculate 计算函数。着重分析下这个

md5 init update final 函数一应俱全,应该是标准的

点进 init 函数,这些常量确实是标准的

frida hook

hook java 函数

var SigEntity = Java.use("com.meitu.secret.SigEntity");

SigEntity.generatorSig.overload('java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.Object').implementation = function (a, b, c, d) {
    printLog('SigEntity.generatorSig.a: ', a);
    printLog('SigEntity.generatorSig.b: ', b);
    printLog('SigEntity.generatorSig.c: ', c);
    printLog('SigEntity.generatorSig.d: ', d);

    var res = this.generatorSig(a, b, c, d);
    printLog('SigEntity.generatorSig.res: ', res.sig.value);

    return res;
}

hook so 函数

里面的一部分 hook 逻辑,在后面使用 unidbg 跑 so 时会用的

var soAddress = Module.findBaseAddress("librelease_sig.so");
console.log('soAddress: ', soAddress);

var sub_6794 = soAddress.add(0x6794 + 1);
console.log('sub_6794: ', sub_6794);

Interceptor.attach(sub_6794, {
    onEnter: function (args) {
        console.log('\nsub_6794 onEnter r0: ', this.context.r0);
    },
    onLeave: function (retval) {
    }
})

var sub_6790 = soAddress.add(0x6790 + 1);
console.log('sub_6790: ', sub_6790);

Interceptor.attach(sub_6790, {
    onEnter: function (args) {
        console.log('\nsub_6790 onEnter r0: ', hexdump(this.context.r0, {length: 64, header: false}));
        console.log('\nsub_6790 onEnter r1: ', hexdump(this.context.r1, {length: 64, header: false}));
    },
    onLeave: function (retval) {
    }
})

var sub_6730 = soAddress.add(0x6730 + 1);
console.log('sub_6730: ', sub_6730);

Interceptor.attach(sub_6730, {
    onEnter: function (args) {
        console.log('\nsub_6730 onEnter r0: ', hexdump(this.context.r0, {length: 64, header: false}));
    },
    onLeave: function (retval) {
    }
})

var sub_4A68 = soAddress.add(0x4A68 + 1);
console.log('sub_4A68: ', sub_4A68);

Interceptor.attach(sub_4A68, {
    onEnter: function (args) {
        console.log('\nmd5_update onEnter r0: ', hexdump(args[0], {length: 32, header: false}));
        console.log('\nmd5_update onEnter r1: ', hexdump(args[1], {length: args[2].toInt32(), header: false}));
        console.log('\nmd5_update onEnter r2: ', args[2].toInt32());
        console.log('\nmd5_update onEnter r3: ', args[3]);
    },
    onLeave: function (retval) {
    }
})

frida hook 命令跑起来,把结果保存到文件中

generatorSig 函数入参

参数比较简单,也就是请求的一些参数

so md5 update 函数

hook 结果 md5 update 函数一共调用了三次。这对 md5 算法有了解的小伙伴就会看的出来,只有第一次是真正的数据,后面两次全是填充的数据

Tips: 不了解的可以看看我之前分享的密码学文章:https://www.qinless.com/1246

最终结果

就是这个 390b028d37b588d2b4380c4aa215be72, 我们来加密下看看是否相同

最终加密结果相同

最后

样本分析结束,加密逻辑也不复杂,还是标准的 md5 算法,下一篇分享下怎么使用 unidbg 跑起来

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

发表评论

返回顶部