本文仅供学习交流,只提供关键思路不会给出完整代码,严禁用于非法用途,若有侵权请联系我删除!
目标app: 5aSn6bqm572ROC41LjQ=
目标接口:aHR0cHM6Ly9hY3MubS50YW9iYW8uY29tL2d3L210b3AuZGFtYWkud2lyZWxlc3MuZGlzY292ZXJ5LmRldGFpbC5nZXQvMS40Lw==
一、引言
接上一篇 安卓逆向 - Frida Hook(抓包实践)_小馒头yy的博客-CSDN博客
我们抓到了某麦网帖子详情的包,发现其中存在 x-mini-wua x-sgext x-sign x-umt x-utdid等加密参数,今天来分析其签名生成(al系app通用签名套路),并搭建RPC实现主动调用。
二、搜索大法,定位关键代码
1、打开 jadx,点击文本搜索 - 选择代码 - 输入x-sign字段,发现如下多个关键位置。我们依次点开分析。并使用Frida hook主要方法,判断是否有走这一段代码。
定位到如下关键代码:
String str9 = unifiedSign.get("x-sign");
关注这段代码的上下文,我们发现 x-mini-wua x-sgext x-sign x-umt x-utdid等参数都是由 iSign.getUnifiedSig() 生成。
HashMap<String, String> unifiedSign = iSign.getUnifiedSign(hashMap3, hashMap4, str5, str6, z2);
三、动态调试
我们跟进去,发现这是一个接口,继续找该接口的实现类。
HashMap<String, String> getUnifiedSign(HashMap<String, String> hashMap, HashMap<String, String> hashMap2, String str, String str2, boolean z);
选中接口 ISign,右键查找用例,寻找该接口的实现类。
最终我们定位到 mtopsdk.security.InnerSignImpl类的 getUnifiedSign()
hook 之:
// mtopsdk.security.InnerSignImpl
function hook5() {
console.log("hook5 start..")
var Build = Java.use('mtopsdk.security.InnerSignImpl');
var JSONObject = Java.use("com.alibaba.fastjson.JSONObject");
Build.getUnifiedSign.overload('java.util.HashMap', 'java.util.HashMap', 'java.lang.String', 'java.lang.String', 'boolean').implementation = function (a, b, c, d, e) {
console.log('参数 a: ' + a)
console.log('参数 b: ' + b)
console.log('参数 c: ' + c)
console.log('参数 d: ' + d)
console.log('参数 e: ' + e)
// showStacks()
var res = this.getUnifiedSign(a, b, c, d, e)
console.log("res: " + res)
return res;
}
}
console.log("res: " + res) 语句输出的内容和我们抓包得到的数据一致。观察其入参都是明文,我们可以以此搭建RPC环境, 实现主动调用。
四、搭建 RPC,实现主动调用
1、获取内存中的 InnerSignImpl类对象
getMemoryObj: function (result) {
if (result == null || result === '' || result === undefined) {
Java.perform(function () {
console.log("begin");
Java.choose("mtopsdk.security.InnerSignImpl", {
onMatch: function (x) {
console.log("choose" + x);
result = x;
},
onComplete: function () {
console.log("end");
}
})
})
}
return result;
}
2、封装参数:主要是 hashMap, hashMap2这两个参数,其他三个写死即可。特别注意data参数传的是一个json字符串,需要转义
var HashMap1 = Java.use('java.util.HashMap').$new();
HashMap1.put("deviceId", null);
HashMap1.put("appKey", "23781390");
HashMap1.put("utdid", "ZL4dqtfxPh0DALSURGw7eDIY");
HashMap1.put("x-features", "27");
HashMap1.put("ttid", "10005884@damai_android_8.5.4");
HashMap1.put("v", "1.4");
HashMap1.put("sid", null);
HashMap1.put("t", "1691142277");
HashMap1.put("api", "mtop.damai.wireless.discovery.detail.get");
HashMap1.put("data", "{\"contentId\":\"10726085\",\"appType\":\"1\",\"source\":\"10101\",\"osType\":\"2\",\"pageSize\":\"30\",\"pageIndex\":\"1\",\"version\":\"6000168\",\"channel_from\":\"damai_market\"}");
HashMap1.put("uid", null);
var HashMap2 = Java.use('java.util.HashMap').$new();
HashMap2.put("pageName", "");
HashMap2.put("pageId", "");
3、调用
res = rpc.exports.remoteObj.getUnifiedSign(HashMap1, HashMap2, "23781390", "", false);
4、搭建Python服务,加载 dm_rpc.js 代码
def begin():
global script
# 加载 js
while True:
try:
process = frida.get_device_manager().get_device(ip + ":" + port).attach(package)
break
except BaseException as e:
print('获取。。。')
with open("dm_rpc.js", 'r', encoding='utf-8') as js:
jscode = js.read()
script = process.create_script(jscode)
script.load()
# 启动服务
app.run(debug=True, port=8006)
if __name__ == "__main__":
ip = '127.0.0.1'
port = '21563'
package = 'cn.damai'
begin()
5、开放接口给外部访问:
@app.route('/sign', methods=['get'])
def sign():
par = request.args.get("key")
params = str(par)
res = script.exports.signature(params)
return res
完结!