有侵权烦请告知,我们会立即删除并致歉,谢谢。
挂代理无法正常通信
http代理:
socket代理
Frida hook Spawn模式
frida-trace -H 127.0.0.1:1234 -n xx -j "*!request/i"
#frida-trace -j 中!前面写类,后面写函数。"class!function"
不太行,触发的时候没有不一样的数据
-j "*!post/i"
触发的时候出现 com.example.super_network_kit.WsManager$2$2 这个类
Hook 下 WsManager
frida-trace -H 127.0.0.1:1234 -n xx -j "*WsManager*!*/i"
成功获取到我们需要的请求包
接下来编写脚本,在这里我们使用盲写的方法。
首先,我们需要确定完整的类名。使用stack()去获取调用栈。
搜索WsManager.sendMessage
这是由frida-trace 自动生成的脚本,接下来添加打印调用栈的代码
#打印调用栈
var Exception = Java.use('java.lang.Exception');
var Log = Java.use('android.util.Log');
var stackinfo = Log.getStackTraceString(Exception.$new());
console.log(stackinfo)
重新trace一下,就可以看到调用栈了
com.example.super_network_kit.WsManager.sendMessage
下面编写js代码
function demo(){
Java.perform(function () {
//请求
console.log(`start!`);
let WsManager = Java.use("com.example.super_network_kit.WsManager");
WsManager["sendMessage"].implementation = function () {
console.log(`WsManager.sendMessage is called: str=${}`);
let result = this["sendMessage"]();
console.log(`WsManager.sendMessage result=${result}`);
return result;
}
})
}
demo()
由于我们是盲打,所以假设这里我们不知道函数的参数,故参数直接写空。
然后注入脚本
frida -H 127.0.0.1:1234 -n xx -l .hook_scripthook.js
触发报错,我们可以看到我们需要重载
.overload('java.lang.String')或者.overload('okio.ByteString')
通过尝试可知是.overload('java.lang.String')
而且从frida-trace的内容也可以猜出来是String类型
我们需要修改脚本如下:
function demo(){
Java.perform(function () {
//请求
console.log(`start!`);
let WsManager = Java.use("com.example.super_network_kit.WsManager");
//添加.overload('java.lang.String') 和 参数 str(可以随意命名)
WsManager["sendMessage"].overload('java.lang.String').implementation = function (str) {
console.log(`WsManager.sendMessage is called: str=${str}`);
//我们可以在这里修改参数str,即实现了修改数据包的需求。
let result = this["sendMessage"](str);//这里调用app里的函数,也需要重新传入str
console.log(`WsManager.sendMessage result=${result}`);
return result;
}
})
}
demo()
修改并保存文件后,控制台已经可以成功打印数据包。
frida -H 127.0.0.1:1234 -n xx -l .hook_scripthook.js
接下来寻找返回包
再看之前的WsManager的trace中,当我们触发的时候,存在这样一个调用onMessage,虽然没有明文显示,但是从方法名中可以看出很有可能就是响应。
我们用代码来看下。
let WsManager2 = Java.use("com.example.super_network_kit.WsManager$2");
WsManager2["onMessage"].overload('okhttp3.WebSocket', 'okio.ByteString').implementation = function (str,str2) {
console.log(`WsManager2.onMessage is called: str=${str2}`);
let result = this["onMessage"](str,str2);
console.log(`WsManager2.onMessage result=${result}`);
return result;
}
通过测试发现重载ByteString overload('okhttp3.WebSocket', 'okio.ByteString')
利用gpt帮忙解析
解码后发现是乱码,需要继续找
我们看看这个的调用栈
可以看到使用加密的方式,而且可以推断出这个是发送消息的加密
那好办了,我们trace加密
frida-trace -H 127.0.0.1:1234 -n xxx -j "*!encrypt/i"
果然是他,这里cf123xxxxxxxxc294897e2ed718就是加密密钥了,看看解密
frida-trace -H 127.0.0.1:1234 -n xx -j "*!decrypt/i"
可恶,没反应。那我们来看看util类
很棒有结果了,可以看出也印证了gpt的说法,调用的是解压缩decompress(gpt牛逼)
解码看看,伟大无需多言。
写下代码,拿下!
let Util = Java.use("com.example.super_network_kit.Util");
Util["decompress"].overload('[B').implementation = function (str) {
//console.log(`WsManager.sendMessage is called: str=${str}`);
let result = this["decompress"](str);
console.log(`Util.decompress result=${array2str(result)}`);
return result;
}
完整脚本
function demo(){
Java.perform(function () {
//请求
console.log(`start!`);
let WsManager = Java.use("com.example.super_network_kit.WsManager");
WsManager["sendMessage"].overload('java.lang.String').implementation = function (str) {
console.log(`WsManager.sendMessage is called: str=${str}`);
let result = this["sendMessage"](str);
console.log(`WsManager.sendMessage result=${result}`);
return result;
}
let Util = Java.use("com.example.super_network_kit.Util");
Util["decompress"].overload('[B').implementation = function (str) {
let result = this["decompress"](str);
console.log(`Util.decompress result=${array2str(result)}`);
return result;
}
})
}
demo()
原文始发于微信公众号(安全小圈):Frida从hook websocket协议看通杀流量加密
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论