常用命令
执行命令
# 快捷执行命令
adb shell su -c "/data/local/tmp/./frida14.2"
# 注入脚本 -U通过usb -F前台进程
frida -FU -l XXX.js
# spwan app, -f是spwan
frida -U -f com.rt.app -l hook.js --no-pause
# 指定输出路径traffix.txt
frida -U -f com.rt.app -l hook.js --no-pause -o traffix.txt
# 指定ID
frida -U -f [APP_ID] -l hook.js --no-pause
# 加上等待, -w 2: 等待两秒
python r0capture.py -U -f com.rt.app -v -w 2
反抓包及解决方案
vpn检测与证书校验区别
- vpn检测 在抓包软件看不到请求,请求发不出去,已经被扼杀在摇篮里了
-
证书校验 在抓包软件里会看到请求,但通常都会提示证书校验不通过
解决SSLPining问题
-
可以替换app中的https请求为http,然后http的请求就解决了证书校验的问题
-
之后在charles map remote中建立映射规则,在中间人这把http映射为https,这样既能抓到包。服务器还不会轻易知道
在charles中找到
这样设置
对抗抓包解决方案
vpn
检测
采用hook_vpn.js
sslpining client
校验server
client
校验server
DroidSSLUnpining.js
multi_unpinning.js
just_trust_me.js
server
校验client
tracer-keystore.js
keystore_dump.js
r0capture.js
网络框架
未混淆okhttp
hook_okhttp3.js
遇到的情况少
混淆okhttp
just_trust_me_okhttp_hook_finder.js
OkHttpLogger-Frida
hook
系统底层
hook_all.js
附录
// hook vpn
function hook_vpn(){
Java.perform(function (){
var String = Java.use("java.lang.String");
var NetworkInterface = Java.use("java.net.NetworkInterface");
NetworkInterface.getName.implementation = function (){
var result = this.getName();
console.log("find getName:", result);
if (result && (result.indexOf("ppp0") > -1 || result.indexOf("tun0") > -1)){
result = String.$new("rmnet_data0");
}
return result;
}
var ConnectivityManager = Java.use("android.net.ConnectivityManager");
ConnectivityManager.getNetworkCapabilities.implementation = function (arg){
var result = this.getNetworkCapabilities(arg);
console.log("find getNetworkCapabilities:", result);
return null;
}
Java.use("android.net.NetworkCapabilities").hasTransport.implementation = function(v){
console.log(v)
var res = this.hasTransport(v)
console.log("res hasTransport ==> ", res)
return false;
}
})
}
setImmediate(hook_vpn);
function tryGetClass(className) {
var clz = undefined;
try {
clz = Java.use(className);
} catch(e) {}
return clz;
}
function newMethodBeat(text, executor) {
var threadClz = Java.use("java.lang.Thread");
var androidLogClz = Java.use("android.util.Log");
var exceptionClz = Java.use("java.lang.Exception");
var currentThread = threadClz.currentThread();
var beat = new Object();
beat.invokeId = Math.random().toString(36).slice( - 8);
beat.executor = executor;
beat.threadId = currentThread.getId();
beat.threadName = currentThread.getName();
beat.text = text;
beat.startTime = new Date().getTime();
beat.stackInfo = androidLogClz.getStackTraceString(exceptionClz.$new()).substring(20);
return beat;
};
function printBeat(beat) {
var str = ("------------startFlag:" + beat.invokeId + ",objectHash:" + beat.executor + ",thread(id:" + beat.threadId + ",name:" + beat.threadName + "),timestamp:" + beat.startTime + "---------------\n");
str += beat.text + "\n";
str += beat.stackInfo;
str += ("------------endFlag:" + beat.invokeId + ",usedtime:" + (new Date().getTime() - beat.startTime) + "---------------\n");
console.log(str);
};
var containRegExps = new Array()
var notContainRegExps = new Array(RegExp(/\.jpg/), RegExp(/\.png/))
function check(str) {
str = str.toString();
if (! (str && str.match)) {
return false;
}
for (var i = 0; i < containRegExps.length; i++) {
if (!str.match(containRegExps[i])) {
return false;
}
}
for (var i = 0; i < notContainRegExps.length; i++) {
if (str.match(notContainRegExps[i])) {
return false;
}
}
return true;
}
Java.perform(function() {
var uriParseClz = Java.use('java.net.URI');
var uriParseClzConstruct = uriParseClz.$init.overload("java.lang.String");
uriParseClzConstruct.implementation = function(url) {
var result = uriParseClzConstruct.call(this, url);
var executor = this.hashCode();
var beatText = "url:" + url + "\npublic java.net.URI(String)";
var beat = newMethodBeat(beatText, executor);
if (check(url)) {
printBeat(beat);
}
return result;
};
// URL
var URLClz = Java.use('java.net.URL');
var androidLogClz = Java.use("android.util.Log");
var exceptionClz = Java.use("java.lang.Exception");
var urlConstruct = URLClz.$init.overload("java.lang.String");
urlConstruct.implementation = function(url) {
// url = url.replace("https", "http");
var result = urlConstruct.call(this, url);
var executor = this.hashCode();
var beatText = "url:" + url + "\npublic java.net.URL(String)";
var beat = newMethodBeat(beatText, executor);
if (check(url)) {
printBeat(beat);
}
return result;
};
//ok系统原生支持
var sysBuilderClz = tryGetClass('com.android.okhttp.Request$Builder');
if (sysBuilderClz) {
sysBuilderClz.build.implementation = function() {
var okRequestResult = this.build();
var httpUrl = okRequestResult.url();
var url = httpUrl.toString();
var executor = this.hashCode();
var beatText = "url:" + url + "\ncom.android.okhttp.Request.Builder.build()";
var beat = newMethodBeat(beatText, executor);
if (check(url)) {
printBeat(beat);
}
return okRequestResult
};
}
//ok本地依赖
var builderClz = tryGetClass('okhttp3.Request$Builder');
if (builderClz) {
var buildFunc = builderClz.build.overload();
buildFunc.implementation = function() {
var okRequestResult = buildFunc.call(this);
var httpUrl = okRequestResult.url();
var url = httpUrl.toString();
var executor = this.hashCode();
var beatText = "url:" + url + "\nokhttp3.Request.Builder.build()";
var beat = newMethodBeat(beatText, executor);
if (check(url)) {
printBeat(beat);
}
return okRequestResult
};
}
var android_net_Uri_clz = Java.use('android.net.Uri');
var android_net_Uri_clz_method_parse_u5rj = android_net_Uri_clz.parse.overload('java.lang.String');
android_net_Uri_clz_method_parse_u5rj.implementation = function(url) {
var executor = 'Class';
var beatText = url + '\npublic static android.net.Uri android.net.Uri.parse(java.lang.String)';
var beat = newMethodBeat(beatText, executor);
var ret = android_net_Uri_clz_method_parse_u5rj.call(android_net_Uri_clz, url);
if (check(url)) {
printBeat(beat);
}
return ret;
};
});