跳转至

App 逆向之川观新闻 sign 获取

本文非工作中的项目,用来熟悉 frida hook 命令(hook java 应用层及 native 的 so 层方法),ida 静态分析 so 文件的用法。

1. 前提准备

以下工具都可换成自己顺手的替代工具,看个人喜好。

川观新闻 app 逆向 sign 参数前的准备如下:

  • jadx v1.3.3
  • gda v3.99(可选)
  • ida v7.5.2
  • 川观新闻 v8.0.0v8.2.1 都可
  • HttpCanary 等抓包软件
  • 配置好逆向环境的安卓模拟器或完成安卓真机,我用的是一加 7 pro 安卓 9。
  • 查壳工具:自己找,不限制使用某个软件
  • 脱壳工具:BlackDex32,使用其它的比如反射大师之类的 xp 插件脱壳,或用 Frida-DEXDump 之类的也可。看自己的安卓版本,加固类型和个人喜好。

2. 逆向步骤

以下为当前软件的逆向步骤

2.1. 抓包

image-20220314165508608

详细请求包数据如下,自己 py 发包可以确定需要 sign 值:

image-20220316100737877

可以尝试下自吐脚本,但没用的,处理逻辑在 so 层。

2.2. 查壳

由下图可知为 360 加固

image-20220316115708297

2.3. 脱壳

这里使用 BlackDex32 来脱壳,提取 dex 文件后在 jadx 中反编译分析。

image-20220316091513678

2.4. jadx 定位

将上步脱出来的 dex 文件放到 jadx 中调试

然后开始定位 sign 生成位置,这里稍微提下搜索定位方法:

  • 不能直接搜 sign,结果太多了,可以搜 "sign", put("sign", &sign= 之类的格式
  • 可以搜请求包中其它比较有特征的参数,比如 app_vnochannel 之类的参数
  • 尽量排除 android, baidu 等开头的搜索结果

定位到 app_vno 参数的声明处,也找到了 sign 参数声明,查找其用例。

image-20220316102301012

其用例如下:

image-20220316102410672

进入详情后,就可以看到 sign 生成的方法位置了。

image-20220316102511908

2.5. frida hook

fridahook getSign 函数,打印其参数及其结果,主要看这个方法是否定位正确。

# frida hook 脚本示例
setImmediate(function() {
    Java.perform(function() {
        var targetClass='cn.thecover.lib.http.data.entity.HttpRequestEntity';
        var methodName='getSign';
        var gclass = Java.use(targetClass);
        gclass[methodName].overload('java.lang.String','java.lang.String','java.lang.String').implementation = function(arg0,arg1,arg2) {
            console.log('\n[Hook getSign(java.lang.String,java.lang.String,java.lang.String)]'+'\n\targ0 = '+arg0+'\n\targ1 = '+arg1+'\n\targ2 = '+arg2);
            var i=this[methodName](arg0,arg1,arg2);
            console.log('\treturn '+i);
            return i;
        }
    })
})

hook 结果如下,hook 结果和抓包数据一致(说明定位正确),接下来就需要分析这个 getSign 方法。

image-20220316103917592

2.6. 分析 getSign 方法

这时候,有两类解决思路,一种 rpcunidbg 之类的方法,不用分析 so 文件逻辑;第二种就需要静态分析和动态调试 so 文件了,最后用 py 算法实现逻辑。

这里选择分析 so 文件,对应 rpc 方法和 unidbg 的解决方法后面有时间也会另开文章详细介绍

2.6.1. 定位 so 文件

我们需要通过 java 应用层方法定位到具体哪个 so 文件,自己在 github 上找找这类 hook 脚本

  • so 动态注册定位:Hook_RegisterNatives
  • 静态注册定位:hook dlsym

这里 so 的情况是静态注册的,所以 frida 走起:

frida -U -f com.sichuanol.cbgc --no-pause -l hook_so_jingtai.js

定位 so 位置结果:

image-20220316110049518

2.6.2. ida 静态分析 so

ida 静态分析 libwtf.so 的文件,ida 的一些常规配置及操作这里先不讲,以后另开文章介绍。

image-20220316110347342

进入详情,找到 if 判断的正常分支中。比较重要的是下图中的两个方法,我们要打印其所有参数和结果。

image-20220316111804947

进到 MD5Digest 方法中就可以知道这是个标准 md5 算法。

image-20220316112456722

要查看函数对应地址:

image-20220316112722001

image-20220316113016735

2.6.3. Hook so 关键方法

Hook 上步中的 MD5Digestget32MD5String 方法,打印其所有参数和结果值。

var nativePointer_C90 = Module.findBaseAddress("libwtf.so");
var funcAddr_C90 = nativePointer_C90.add(0xC90 + 1);
Interceptor.attach(funcAddr_C90, {
    onEnter: function (args) {
        console.log("funcAddr_C90 args[0]:", hexdump(args[0]));
        console.log("funcAddr_C90 args[1]:", args[1].toInt32());
        console.log("funcAddr_C90 args[2]:", hexdump(args[2]));
        this.args2 = args[2];
    },
    onLeave: function (retval){
        console.log("funcAddr_C90 this.args2:", this.args);
    }
});

var nativePointer = Module.findBaseAddress("libwtf.so");
var funcAddr = nativePointer.add(0x8BC + 1);
Interceptor.attach(funcAddr, {
    onEnter: function (args) {
        console.log("funcAddr args[0]:", hexdump(args[0]));
        console.log("funcAddr args[1]:", hexdump(args[1]));
        this.args1 = args[1];
    },
    onLeave: function (retval){
        console.log("funcAddr this.args1:", hexdump(this.args1));
    }
})

结果如下:

image-20220316113553828

image-20220316113740635

到这里就已经结束了,就是对 C90 args[0] 的值 md5 后的结果,而 C90 的参数就是 0093CB6721DAF15D31CFBC9BBE3A2B79 加上时间戳。如下图,与上图抓包数据一致

image-20220316114850926

3. 总结

  • 要熟悉 ida 操作,熟悉 c 语言和汇编代码对 so 分析会有很大帮助
  • 若碰到复杂的自写或魔改算法的 so 时,优先推荐使用 unidbg 来调通后,用 py 运行 unidbg 打包后的 jar 包最好

评论

回到页面顶部