常用命令

执行命令

# 快捷执行命令
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;
    };
});

1.DroidSSLUnpinning:原项目链接
2.r0capture
3.Frida js断点调试

分类: app逆向

站点统计

  • 文章总数:315 篇
  • 分类总数:20 个
  • 标签总数:193 个
  • 运行天数:1126 天
  • 访问总数:10972 人次

浙公网安备33011302000604

辽ICP备20003309号