前⾔
前段时间学习了Android逆向⼊⻔课程,跟着⽼师的步伐去学习,然后找了⽹上的⼀些样本进⾏练 练⼿
环境
APP:泡泡⼿游
APP包名:com.zqhy.xiaomashouyou
版本号:8.3.7
Pixel 3 Android 11 (已root)
HttpCanary v.3.3.6
Jadx v1.2.0
Frida v15.2.2
⾸先⽤HttpCanary进⾏登录抓包分析
账号:18888888888
密码:1234
POST /index.php/App/index?api=login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 1249
Host: appapi-ns1.tsyule.cn
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.10.0
data=XB1a7vJ%252F8Md%252BX7sj%252FsVYbKTWbLZ0EmyevxsyLxygi5AFHR9mLtCkUjZnETsL
可以看到它以 POST ⽅式提交数据包,数据包传的参数为 data ,并且对参数内容进⾏ URL编 码 ,以及⽤base编码形式来展示数据
接着⽤Jadx-gui进⾏APK包分析,进⾏关键词搜索,因为数据包的那个 data 参数关键词太普遍 了,⽆法准确的判断,那么尝试去查找⼀下登录URL的关键词,直接搜索 login ,⽽且找的时候要 找它的 主类 ,主类是以 ⼀个绿⾊的实⼼⼩圆圈显示的 ,然后出现⼀⼤堆结果,再结合上⾯的 api 关键词,最终定位到 com.zqhy.app.audit.data.a.e.a.a(String, String, g) void
双击跟进去看到有 username 和 password 等关键词,按键盘上的 ctrl键 然后,跟进 a函 数 ,再进⼊ treeMap ⾥⾯,看看它⾥⾯是由什么参数组成的
然后看到 data 关键词参数名,继续跟进 a(map) 进⾏跳转
看到它⾥⾯有包含很多关于设备的⼀些参数
然后再往下看,看到它这⾥是进⾏了 URL编码 ,再跟进去 com.zqhy.app.network.d.c.a 这个函 数
这⾥已经可以看到它的加密算法、密钥、模式的信息
算法:DES
模式:CBC
填充:PKCS5Padding
key:qn%49E&E
iv:qn%49E&E
然后把上⾯的数据包进⾏ URL解码 之后,就使⽤DES解密⼯具进⾏解密数据包内容。这⾥有⼀个细节,因为它的key和iv的值⾥⾯是有个 % ,然后后⾯⼜有两位数字 49 ,如果使 ⽤在线解密⼯具进⾏解密的时候,会⾃动把 %49 进⾏URL解码变成 I 字符串,因为它那⾥的iv值 是要求 偏移量最少:8字节⻓度 ,那么它这⾥把 %49解码为I 就⽆法进⾏解密
因此我这⾥就使⽤ WTJS.exe ⼯具进⾏解密,这个⼯具能把这个key和iv的值以⼀个完整的字符串 去进⾏解密, ⽽不会出现上⾯那样⾃动进⾏URL解码的 ,在⽂章的下⾯部分我也对 Login 算法 进⾏编写了hook脚本
androidid=a6d27cdc00793172
api=login
appid=995011
client_id=01e3ed9250515b16ceda3839f0f20d96
client_type=1
device_id=a6d27cdc00793172unknown
device_id_2=3ab4b47d8d9b399757e23c01d38d13ed
imei=
ip=10.1.10.1
is_special=0
mac=xx:xx:xx:xx:xx:xx
oaid=
oldtgid=ga8104004
password=123456
reyun_device_id=unknown
sign=2D5043783788E119BB298879E25FF11E
tgid=ga8104004
ts_device_brand=google
ts_device_id=fbde57df-31dc-3f29-ae28-e68c19ee6193
ts_device_id_2=a6d27cdc00793172unknown
ts_device_model=Pixel+3
ts_device_version=11
ts_device_version_code=30
ts_imei=
ua=Mozilla/5.0+
(Linux;+Android+11;+Pixel+3+Build/RQ2A.210505.002;+wv)+AppleWebKit/537.36+
(KHTML,+like+Gecko)+Version/4.0+Chrome/106.0.5249.126+Mobile+Safari/537.36
umeng_device_id=a6d27cdc00793172
username=18888888888
uuid=a6d27cdc00793172unknown
vc=1
version=83700
这时注意到有⼀个 sign值 ,就是为了保证数据包不被篡改,保持数据包的完整性,但是如果站在 渗透测试⼈员⻆度⽅向,肯定在测试的过程中要对数据包进⾏修改,那么就必须找到它如何⽣成 sign值 的算法,再进⾏的篡改数据包
接下来继续寻找⽣成 sign 算法函数
从第183⾏代码 map.put("sign", com.zqhy.app.network.d.a.b(map)); 它的 sign值 后⾯是指向 ⼀个 b(map) 函数,继续跟进去看看
b(Map map) 这⾥有两个对象,猜测是指向下⾯的 str、str2 ,接着看到下⾯ 的 String str3 = a(treeMap) + "Df1&#%$WT9sGc%^urZO0!XkjglAv!Vel"; 这⾥也看到有⼀ 个 a(treeMap) ,但不确定⾥⾯是有什么内容,然后⼜拼接了⼀串字符串,那么继续看到下⾯ com.mvvm.d.a.a(f12499b, "signstr(MD5前串):" + str3); 有⼀个函数 com.mvvm.d.a.a 跟进 去看看
猜测这⾥就描述了 str、str2 的⻓度,貌似作⽤不⼤。太菜了,看不懂Java的我,呜呜呜。那么我 就先对 com.zqhy.app.network.d.a.b函数 进⾏编写hook脚本,看⼀下 a(treeMap) ⾥⾯究竟有 什么内容,这⾥要注意⼀点就是在 hook脚本 运⾏的整个过程要 全程启动frida服务端程序 ,
//java层hook要求
Java.perform(function () {
//Login登录的数据包解密
var ppsy1 = Java.use('com.zqhy.app.network.d.c');
//⾃定义⼀个变量,代表要hook的类com.zqhy.app.network.d.c
console.log("aaaaaa");
//打印⼀下,看看是否执⾏到这⾥
ppsy1.a.overload('java.lang.String').implementation = function (d){
//定义要hook的函数a()
//.overload('java.lang.String') 代表重载,是因为⼀个同名⽅法可以传⼊多个参数组合,因为这⾥它有
超过⼀个以上使⽤了同名⽅法参数相同,所以返回值不同,如果不指定传⼊的参数组合就会出现编译出
错
//implementation这个属性就是代表实施,对这个a函数进⾏拦截
console.log(d);
return this.a(d);
//打印出来d的值,然后返回this.a(d)的值
};
//Sign值算法的数据包解密
var ppsy2 = Java.use('com.zqhy.app.network.d.a');
//⾃定义⼀个变量,代表要hook的类com.zqhy.app.network.d.a
ppsy2.b.overload('java.lang.String').implementation = function (c){
console.log(c);
var dd = this.b(c);
console.log("sign:" + dd);
return dd;
};
});
因此这就明⽩了 a(treeMap) ⾥⾯的内容就是上⾯ Login登录 解密后的数据包内容 不包括sign 值 ,所以它这⾥的 sign = MD5(Login 登 录 解 密 后 的 数 据 包 内 容 不 包 括 sign 值 + Df1&#%$WT9sGc%^urZO0!XkjglAv!Vel)
那么现在知道它的 sign 是如何⽣成的,之后如果要渗透测试这个APP的话,就对数据包修改必须
要修改两处,例如是登录那个测试点, 1、先修改开始解密后的登录包 2、再修改sign值解密后⾥ ⾯的与第⼀点相对应的值 ,这样才能绕过它的签名值校验,否则它就会出现 签名校验失败
原文始发于微信公众号(云梦安全实验室):Android泡泡⼿游APP逆向Login & Sign 算法分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论