本帖最后由 LucasBarthak 于 2026-9-1 20:47 编辑
前言
在配置好bp的代理设置后(配置过程详见上一篇),抓取app流量包的过程中,发现登录app时畅通无阻。确定配置没问题却无法抓取登录流量包,最后发现是app设置了无代理,导致流量不经过bp。
前置准备
root机:安卓14+KernelSU+frida-server
windows:bp+frida+jadx
问题分析
以下使用一个app作为例子,不同app业务逻辑不同,具体问题具体分析,只是作为参考
1.用jadx将apk打开,之后定位到登录逻辑的Activity包中登录的点击事件onClick:
[Asm] 纯文本查看 复制代码 @Override // android.view.View.OnClickListener
public void onClick(View v) {
if (((ActivityLoginBinding) getBinding()).btnLoginLogin.equals(v)) {
if (NetWorkUtils.isConnected(getApplicationContext())) {
String studentId = ((ActivityLoginBinding) getBinding()).etStudentId.getText().toString().trim();
String password = ((ActivityLoginBinding) getBinding()).etPassword.getText().toString().trim();
if (studentId.length() > 10 && password.length() > 0) {
getPresenter().login(studentId, password);
return;
} else {
ToastUtil.show("请将学号或密码填写完整");
return;
}
}
ToastUtil.show("请连接网络");
} else if (((ActivityLoginBinding) getBinding()).tvLoginGetHelp.equals(v)) {
OtherWebActivity.setName("帮助");
OtherWebActivity.setUrl(WustApi.GET_HELP_LOGIN_URL);
Intent privacy = OtherWebActivity.getInstance(this);
startActivity(privacy);
} else if (((ActivityLoginBinding) getBinding()).tvVolunteer.equals(v)) {
OtherWebActivity.setName("工时系统");
OtherWebActivity.setUrl(WustApi.VOLUNTEER_URL);
Intent volunteer = OtherWebActivity.getInstance(this);
startActivity(volunteer);
}
}
2.转到login方法:
[Asm] 纯文本查看 复制代码 public void login(String studentId, String password, DisposeDataListener listener) {
NewApiHelper.loginUndergraduateV2(studentId, password, listener);
}
3.顺着调用链一层层转接,最终看到在CommonOkHttpClient包中有一行设置
我们知道,这行代码就是bp抓不到包的原因
除此之外,我们还定位到该请求包自定义了sslSocketFactory。其中实现了HttpsUtils.initSSLSocketFactory(), HttpsUtils.initTrustManager(),皆为空实现;即登录时app走的自定义的okhttp并没有ssl pinning,暂且不提。
解决方法
firda语法:
可参考文章
https://bbs.huaweicloud.com/blogs/386133
编写hook脚本:
[Asm] 纯文本查看 复制代码 var PROXY_HOST = ""; // TODO: 改成电脑的局域网 IP
var PROXY_PORT = 1234; // TODO: 改成代理端口
Java.perform(function () {
var Proxy = Java.use("java.net.Proxy");
var ProxyType = Java.use("java.net.Proxy$Type");
var InetSockAddr = Java.use("java.net.InetSocketAddress");
function buildProxy() {
var addr = InetSockAddr.$new(PROXY_HOST, PROXY_PORT);
return Proxy.$new(ProxyType.HTTP.value, addr);
}
// ============ 方案 A: Hook Builder.proxy() ============
try {
var Builder = Java.use("okhttp3.OkHttpClient$Builder");
Builder.proxy.overload("java.net.Proxy").implementation = function (p) {
console.log("[proxy] Builder.proxy() 原值=" + p + " → 替换为 " + PROXY_HOST + ":" + PROXY_PORT);
return this.proxy(buildProxy());
};
console.log("[✅] Builder.proxy Hook 成功");
} catch (e) {
console.log("[❌] Builder.proxy Hook 失败: " + e);
}
// ============ 方案 B: 兜底单例重建 ============
try {
var COHC = Java.use("com.example.wusthelper.request.okhttp.CommonOkHttpClient");
var patched = null;
COHC.getOkHttpClient.implementation = function () {
var current = this.getOkHttpClient();
if (patched === null) {
patched = current.newBuilder().proxy(buildProxy()).build();
console.log("[proxy] CommonOkHttpClient 单例已重建并注入代理");
}
return patched;
};
console.log("[✅] CommonOkHttpClient 单例 Hook 成功");
} catch (e) {
console.log("[⚠️] CommonOkHttpClient Hook 失败(spawn 模式可忽略): " + e);
}
console.log("[🚀] 脚本加载完成,代理指向 " + PROXY_HOST + ":" + PROXY_PORT);
});
frida注入:
抓包成功:
|