jadx 反编译
AndroidManifest.xml 查看入口 Activity
io.dcloud.PandoraEntry

adb shell dumpsys window | findstr CurrentFocus
抓包-未证书校验
为进行签名校验时,可以正常抓包
抓包,代理到 yakit 上
抓包-证书校验
从网站https://vue.ruoyi.vip/login导出 crt 证书,然后 crt 转 cer
参考:
- • 导出证书 https://blog.csdn.net/c5113620/article/details/80384660
- • 证书转换 https://www.zhihu.com/question/401504013
在RuoYi-App-v1.2.0\\utils\\request.js中配置单向证书校验

uni.configMTLS({
certificates: [{
'host': 'vue.ruoyi.vip',
'server': ['/static/ruoyi.cer'],
}],
success ({code}) {}
});
Hbuilder 运行代码到 Android 设备,未代理到 yakit 时
uniapp 抓包
Frida 脚本:https://github.com/windy-purple/uni\_app-Packet-capture
项目中的 uni-app.js 脚本,有一点需要注意的,就是在函数printResponse。该函数的目的是打印响应包,但在打印响应体的时候,用到了
var bodystr = bufferobj.readUtf8();
而在OkHttp中,response.body().source().readUtf8() 这种读取方式是一次性的,一旦你读取了数据流,它就不会再被应用程序读取到了。直接使用上述的脚本,app 无法正常接收响应包。
替换脚本中的函数printResponse,新代码如下:
function printResponse(response) {
var code = response.code();
var Headers = response.headers();
var message = response.message();
var Protocol = response.protocol();
var content_type = Headers.get(\"Content-Type\");
var headers = Headers.toString();
var protocol = Protocol.toString();
console.log(\"[Response]:\")
console.log(protocol + \" \" + code + \" \" + message);
console.log(headers);
var responseBody = response.body();
if (!responseBody) return response;
var source = responseBody.source();
var Long = Java.use(\"java.lang.Long\");
source.request(Long.MAX_VALUE.value); // 缓冲整个内容
var buffer = source.buffer().clone(); // 克隆一个新的缓存,不消耗原有的
if (ContentTypeIsPrint(content_type) == 1) {
console.log(buffer.readUtf8());
} else {
console.log(buffer.readByteString().hex());
}
return response;
}
执行脚本:
frida -U -f com.ruoyi.labs -l uni-app.js
成功打印了请求和响应

./ecapture tls
也可以抓包包
uniapp 导出 JS 文件
原本
if (Java.available) {
Java.perform(function () {
let WXSDKInstance = Java.use(\"com.taobao.weex.WXSDKInstance\");
WXSDKInstance[\"render\"].overload('java.lang.String', 'java.lang.String', 'java.util.Map', 'java.lang.String', 'com.taobao.weex.common.WXRenderStrategy').implementation = function (str, str2, map, str3, wXRenderStrategy) {
console.log(`WXSDKInstance.render is called: str=${str}, str2=${str2}, map=${map}, str3=${str3}, wXRenderStrategy=${wXRenderStrategy}`);
this[\"render\"](str, str2, map, str3, wXRenderStrategy);
};
});
}

mkdir /sdcard/Download/demo-js
chmod 777 /sdcard/Download/demo-js
if (Java.available) {
Java.perform(function () {
let WXSDKInstance = Java.use('com.taobao.weex.WXSDKInstance')
WXSDKInstance['render'].overload(
'java.lang.String',
'java.lang.String',
'java.util.Map',
'java.lang.String',
'com.taobao.weex.common.WXRenderStrategy'
).implementation = function (str, str2, map, str3, wXRenderStrategy) {
// console.log(`WXSDKInstance.render is called: str=${str}, str2=${str2}, map=${map}, str3=${str3}, wXRenderStrategy=${wXRenderStrategy}`);
this['render'](str, str2, map, str3, wXRenderStrategy)
write_file_1(str3, str2)
}
})
}
function sanitizeFileName(fileName) {
// 移除路径分隔符等非法字符
return fileName.replace(/[\\/\\\\:*?\"<>|{}]/g, '_')
}
function trimUnderscores(str) {
// 先去除空白字符,再去去除下划线
return str.trim().replace(/^_+|_+$/g, '')
}
function write_file_1(filename, data) {
//frida 的api来写文件
filename = sanitizeFileName(filename)
filename = trimUnderscores(filename)
console.log(filename)
// 先检查文件是否存在,如果存在则删除
try {
var existingFile = new File('/sdcard/Download/demo-js/' + filename, 'r')
if (existingFile) {
existingFile.close()
// 删除已存在的文件
File.remove('/sdcard/Download/demo-js/' + filename)
}
} catch (e) {}
var file = new File('/sdcard/Download/demo-js/' + filename, 'w')
file.write(data)
file.flush()
file.close()
}
评论