如何逆向 React Native 应用

By dwj1210 at

在工作或者兴趣研究中,我们经常会遇到一些带有签名字段或者是加密后的数据包。

而数据的加密,是为了保证数据在链路传输过程中即便被中间人攻击,也无法获取到明文的用户信息。签名字段则是为了保证数据传输的完整性,保证数据不会被中间人篡改。

今天就拿一个简单的 RN 应用来分享下,对于 RN 应用如何逆向出数据包的签名字段算法。

抓包

img 可以看到 “sign” 字段应就是签名字段。

逆向

0x00

我们先用 IDA 反编译一下二进制,然后尝试搜索下 “trParam” 字符串发现并没有我们需要的结果。

0x01

然后用 lldb 挂上应用看下视图发现,应用视图类使用了大量 RCTxxx 。

img

由此可以推断出应用使用了 React Native 混合开发模式。而 RN 应用的主要逻辑代码均为 js 实现。

0x02

解压缩安装包,进入 .app 目录,可以找到应用的 js 源代码,应该就是这个文件。

img

打开查看 jsbundle 的代码发现全部经过了压缩混淆,可读性为 0。

img

0x03

这个时候我们需要一个 js 在线格式化 帮我们格式化一下 js 代码。虽然变量名字和函数名都经过了无意义的混淆,但是经过格式化后的代码还是有很强的可读性。

0x04

在 js 代码中搜索数据包中的字符串发现可以直接定位到字段拼接的位置。

img

从代码片段中可以看到 timestamp 是一个时间戳,nonce 是一个随机数,而 sign 则是由 nonce 拼接 timestamp 最后 md5 后的结果。

img

在这里可以看到 trParam 是对传入的变量 e md5 后的结果。但是我们并不知道这个 e 代表什么。

0x05

我们尝试在 js 代码中添加 console.log 来打印关键信息,但是发现日志并没有输出到日志中。

另起思路,给 JSContext 类添加方法来通过 js 调用 OC 方法来打印。

#import <JavaScriptCore/JavaScriptCore.h>
CHDeclareClass(JSContext)
CHOptimizedMethod0(self, id, JSContext, init) {

    self = CHSuper0(JSContext, init);
    self[@"NSLog"] = ^(NSString *format){
        NSLog(@"%@",format);
    };
    return self;
}

CHConstructor{

    CHLoadLateClass(JSContext);
    CHClassHook0(JSContext, init);
}

如果你发现你的代码报错了,可能是忘记在 hook 代码中导入头文件。

实际插入的代码:

img

0x06

我们使用 MonKeyDev 重打包安装到手机,在实际运行过程中就能在控制台看到相应的日志输出了。

而此处的变量 e 其实就是用户手机号经过 AES 加密之后的数据,而 trParam 则是手机号经过 AES 然后 md5 后的数据了。该部分就不在展示了。

总结

对于 RN 应用确实存在无法动态调试 js 代码的问题。但是我们可以通过插入 log 的方式动态追踪关键函数的入参和返回值。