android app抓包,会出现http包不走fiddler等代理的情况,譬如淘宝系、支付宝系app
etao app使用mtopsdk(https://help.aliyun.com/document_detail/69785.html),https://acs.m.taobao.com/下的请求都抓不到
本文分析了com.taobao.etao,最终可以通过fiddler、burp进行抓包
1、通过frida hook可以打印出所有请求及参数
//所有响应
var Response = Java.use('mtopsdk.network.domain.Response');
Response.$init.overload('mtopsdk.network.domain.Response$Builder').implementation = function(){
//PrintStack()
console.log("\nResponse "+arguments[0].body)
var ret = this.$init.apply(this, arguments);
//all request
console.log("\nResponse "+this.toString())
return ret
}
//所有请求
var RequestBuilder = Java.use('mtopsdk.network.domain.Request$Builder');
RequestBuilder.build.overload().implementation = function(){
//PrintStack()
var ret = this.build.apply(this, arguments);
//all request
console.log("\nRequestBuilder "+ret.toString())
return ret
}
//所有请求
var ANetworkCallImpl = Java.use('mtopsdk.network.impl.ANetworkCallImpl');
ANetworkCallImpl.$init.overload('mtopsdk.network.domain.Request', 'android.content.Context').implementation = function(){
//PrintStack()
console.log("\nANetworkCallImpl "+arguments[0])
var ret = this.$init.apply(this, arguments);
return ret
}
//所有请求url
var AbstractNetworkConverter = Java.use('mtopsdk.mtop.protocol.converter.impl.AbstractNetworkConverter');
AbstractNetworkConverter.buildBaseUrl.overload('mtopsdk.framework.domain.MtopContext','java.lang.String', 'java.lang.String').implementation = function(){
//console.log("buildBaseUrl "+arguments[1]+' '+arguments[2])
var ret = this.buildBaseUrl.apply(this, arguments);
//url
//console.log("buildBaseUrl "+ret)
return ret
}
2、进一步分析得知由于sdk使用spdy协议,导致无法抓包
通过hook 将是否使用spdy返回false
var SwitchConfig = Java.use('mtopsdk.mtop.global.SwitchConfig');
SwitchConfig.isGlobalSpdySwitchOpen.overload().implementation = function(){
var ret = this.isGlobalSpdySwitchOpen.apply(this, arguments);
console.log("\nisGlobalSpdySwitchOpenl "+ret)
return false
}
不同应用集成mtopsdk 混淆程度不一样,函数名可能会变
终于可以抓到包
虽然可以看到包,但请求有签名,无法直接改包,还需要针对具体业务进行hook修改参数,后续可以分析下签名机制
其他app可以通过设置no_proxy来bypass wifi代理
1、Socket(Proxy proxy)
2、openConnection (Proxy proxy)
3、OkHttpClient.Builder().proxy(proxy);
等等,需要具体进行hook
============支付宝APP使用mpaas-rpc框架======
参考https://juejin.im/post/5bc850caf265da0abf7d195d#heading-12
(请求通过socket连接发送http协议,暂时没法导入fiddler等代理)
通过frida hook可以打印出请求和响应
var Throwable = null;
Java.perform(function () {
Throwable = Java.use("java.lang.Throwable");
});
/*
* 输出当前调用堆栈
*/
function PrintStack() {
var stackElements = Throwable.$new().getStackTrace();
var body = "Stack: " + stackElements[0];//method//stackElements[0].getMethodName()
for (var i = 1; i < stackElements.length; i++) {
body += "\n at " + stackElements[i];
}
console.log(body);
};
Java.perform(function() {
//========android 7+
try{
var array_list = Java.use("java.util.ArrayList");
var ApiClient = Java.use('com.android.org.conscrypt.TrustManagerImpl');
ApiClient.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6) {
var k = array_list.$new();
return k;
}
}catch (e) {
//console.log('universal '+e);
}
var CoreHttpManager = Java.use('com.alipay.mobile.common.transport.http.inner.CoreHttpManager');
CoreHttpManager.a.overload('com.alipay.mobile.common.transport.http.HttpUrlRequest').implementation = function(){
//PrintStack()
//console.log("")
// console.log("CoreHttpManager "+arguments[0].getUrl()+' '+arguments[0].getTag('operationType'))
var ret = this.a.apply(this, arguments);
return ret
}
//请求,这个位置已经sign过无法更改参数
var HttpCaller = Java.use('com.alipay.mobile.common.rpc.transport.http.HttpCaller');
HttpCaller.sendRequest.overload('com.alipay.mobile.common.transport.http.HttpUrlRequest').implementation = function(){
var ret = this.sendRequest.apply(this, arguments);
var blacklist = ['com.alipayhk.imobilewallet.plugin.home.union.query', 'ant.abtest.configlite', 'alipay.mappconfig.queryAppInfo', 'alipay.mappconfig.queryStageInfo', 'alipay.livetradeprod.soundWave.getInitArgs.pb']
var opertype = arguments[0].getTag('operationType')
var url = arguments[0].getUrl()
var data = arguments[0].getReqData()
var header = arguments[0].getHeaders()
var Map = Java.use('java.util.HashMap')
var args_map = Java.cast(arguments[0].getTags(), Map)
var tags = args_map.toString()
var resdata = ret.getResData()
if (blacklist.indexOf(opertype) == -1 ){
// try{
// console.log("httpcaller ==request "+url+' '+opertype + ' =header: '+header+ ' =tags: '+tags+' =data: '+byteArr2str(data, true)+' \n======response '+byteArr2str(resdata,true))
// console.log("")
// }catch(e){
// //console.log('decode error '+opertype)
// console.log("httpcaller ==request "+url+' '+opertype + ' =header: '+header+ ' =tags: '+tags+' =data: '+byteArr2str(data, false)+' \n======response '+byteArr2str(resdata, false))
// console.log("")
// }
}
return ret
}
//es6支持默认参数
function byteArr2str(ba, w){
if(w){
var string = Java.use('java.lang.String')
return string.$new(ba)
}else{
var array = Java.use('java.util.Arrays')
return array.toString(ba)
}
}
//array2str
function arr(arr){
if (arr != null){
var ret = ''
for(var i = 0, len = arr.length; i < len; i++){
ret += String.fromCharCode(arr[i])
}
return ret
}
}
//参考https://juejin.im/post/5bc850caf265da0abf7d195d#heading-12
//Serializer数据格式protobuf和json两种
//在此位置更改参数
var RpcInvoker = Java.use('com.alipay.mobile.common.rpc.RpcInvoker');
RpcInvoker.singleCall.overload('java.lang.reflect.Method', '[Ljava.lang.Object;', 'java.lang.String', 'int', 'com.alipay.mobile.common.rpc.transport.InnerRpcInvokeContext', 'com.alipay.mobile.common.rpc.protocol.util.RPCProtoDesc').implementation = function(){
console.log("")
console.log('call '+arguments[2]+ ' =data: '+arguments[1])
var ret = this.singleCall.apply(this, arguments);
return ret
}
}, 0);
可以打印出所有请求