要逆向的是一款叫shengqian快报的app,具体要分析sign签名的加密过程。
系统:macOS 10.14.1
模拟器:mac版夜神模拟器 3.0.3.0
抓包工具:Charles
逆向工具:apk-tool、JD-GUI、frida、adb、dex2jar、objection
从网上下载shengqian快报的apk保存到电脑上,打开夜神模拟器,将apk拖到夜神模拟器里面安装。
使用Charles对夜神模拟器进行抓包。(需要在夜神模拟器上安装好Charles的证书然后配置好代理)
打开shengqian快报app,对需要分析的页面进行抓包。
分析抓到的包,发现目标接口:
返回的json就是需要的数据:
ok。到这里目标接口就找到了,接下来要对这个接口进行分析。
分析发现这个接口接收一个post请求,包含了30多个参数,其中最重要的就是我们要分析的sign参数了。
我们可以先尝试用postman或者python脚本向这个接口发送一个post请求试试,结果返回的是{"status_code":-1,"message":"invalid sign"},可以证明在服务器端进行了sign的校验,所以我们想要得到这个接口的数据就需要将sign加密过程找到然后伪造一个合法的post请求。
用apktool反编译apk文件为smali
apktool d jz_dsp_ydcx_zcw17.apk
将反编译后的文件夹后缀名修改为zip,然后进行解压,解压后的文件夹里含有classes.dex的文件。最后使用dex2jar工具将classes.dex文件转换为classes-dex2jar.jar文件。
用JD-GUI打开最后的jar文件,发现代码是经过混淆的。
点开左上角的手电筒全局搜索sign,
发现一处比较可疑的地方,这个e函数猜测应该就是用parama来加密,
接下来进入e方法,可以确定这就是加密的方法了。stringBuilder创建了一个用&连接所有参数的字符串,最后又添加了一个32位的字符串,通过b.a()方法来加密。
接下来进入b类查看,可以看出来这就是md5加密,
确认完加密算法,就需要分析parama里面都是什么了。
打开夜神模拟器,adb shell进入命令行(模拟器的root启动要开启),运行frida-server。
模拟器里打开shengqian快报app,新开一个命令行输入下面命令查看进程,
frida-ps -U
找到对应进程就可以开始hook了。
输入下面命令进入objection,
objection -g com.****.coupon explore
watch一下e方法看看返回值、调用栈和传入参数的内容都是啥。
android hooking watch class_method com.****.coupon.httptask.a.a.e --dump-args --dump-backtrace --dump-return
点击进入详情页后,发现e方法被调用了很多次,返回值其实就是加密后生成的sign(调用栈就不截图了)
同时在Charles的抓到的目标接口中,发现sign和hook到的返回值一样。
因此可以确认接口的sign是通过e这里生成的了。
接下来就要去分析传入e的parama是什么了。
读一下e方法里面的代码,可以看出来parama.k()可以获得一个List类型的对象,然后遍历这个对象并且生成一个url参数格式的字符串(name1=value1&name2=value2……)
知道了这些就可以写一个简单的hook脚本来打印一下parama里面的内容了。
python脚本:
import sys
import frida
PACKAGE = 'com.****.coupon'
def hook():
jscode = open('script.js', 'r').read()
# 查找USB设备并附加到目标进程
session = frida.get_usb_device().attach(PACKAGE)
# 在目标进程里创建脚本
script = session.create_script(jscode)
print('[*] Start attach')
# 加载创建好的javascript脚本
script.load()
# 读取系统输入
sys.stdin.read()
if __name__ == '__main__':
hook()
script.js:
function hook(){
Java.perform(function(){
var a = Java.use("com.****.coupon.httptask.a.a");
a.e.implementation = function(parama){
var result = this.e(parama);
var l = parama.k().size();
console.log("len:",l,"len:",l);
// 随便打印几个参数
console.log("parama1",parama.k().get(1));
console.log("parama31",parama.k().get(31));
console.log("parama34",parama.k().get(34));
return result;
}
});
};
setImmediate(function(){
setTimeout(hook, 2000);
});
hook好之后,发现加密的这些参数其实就是post里面提交的参数,到这里sign分析就结束了。
我们要实现sign加密算法的话,就保留关键的参数,然后将这些键值进行拼接,字符串的末尾要拼接"81f454ac98956541b195f2c7f9e53a06",最后再对字符串进行一次MD5就可以了。