Frida Hook 代码片段

反编译工具

抓包或者逆向使用到的反编译工具:

  • IDA,需要找破解版
  • JEB,需要找破解版
  • GDA,这是免费版的,不需要破解,一般功能可以够用了,也有收费的版本,官网

启动Frida客户端

#spwan模式,会重启app
frida -U -f com.piaoyou.piaoxingqiu -l d:/hook/objection_hooking_watch_class.txt -o d:/hook/hook.log
#attach模式,不会重启app
frida -U com.piaoyou.piaoxingqiu -l d:/hook/objection_hooking_watch_class.txt -o d:/hook/hook.log

参数-o,指定Frida的输出日志到文件

延迟执行

//立即执行
setImmediate(function() {
    //延迟1秒执行test方法
    setTimeout(test, 1000);
});

jnitrace 工具

jnitrace是一个Frida模块,跟踪Android应用程序中JNIAPI的使用情况

jnitrace -l libc.so com.piao.piaoxing

打印调用栈

//java打印堆栈
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
//SO打印堆栈,objection 的import命令,导入脚本,脚本中使用此语句打印调用栈,直接用frida执行脚本,会报错
console.log(' called from:\n' +Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join('\n') + '\n');

证书校验Hook

方式一checkServerTrusted

Java.perform(function() {
    var ClassName = "com.android.org.conscrypt.Platform";
    var Platform = Java.use(ClassName);
    var targetMethod = "checkServerTrusted";
    var len = Platform[targetMethod].overloads.length;
    console.log(len);
    for(var i = 0; i < len; ++i) {
        Platform[targetMethod].overloads[i].implementation = function () {
            console.log("class:", ClassName, "target:", targetMethod, " i:", i, arguments);
            //printStack(ClassName + "." + targetMethod);
        }
    }
});

方法二 objection

使用objection工具的下面这个命令,直接将SSL pinningdisable

android sslpinning disable

方法三 DroidSSLUnpinning

使用DroidSSLUnpinning项目,这是github上开源项目,项目地址

方法四 frida-interception-and-unpinning

同样是github上开源项目,项目地址
项目下载下来之后,执行以下命令:

frida -U -l ./config.js -l ./native-connect-hook.js -l ./android/android-proxy-override.js -l ./android/android-system-certificate-injection.js -l ./android/android-certificate-unpinning.js -l ./android/android-certificate-unpinning-fallback.js -f com.piao.piaoxing

枚举所有类

Java.perform(function(){
    var classz = Java.enumerateLoadedClassesSync();
    for(var i=0;i<classz.length;i++){
        if (classz[i].indexOf("com.xiaojianbang.app") != -1){
            console.log(classz[i])
        }
    }
})

枚举一个类的所有方法

var MainActivity = Java.use("com.xiaojianbang.app.MainActivity");
var methods = MainActivity.class.getDeclaredMethods();
for(var i=0;i<methods.length;i++){
    console.log(methods[i].getName())
}

hook重载方法

var Utils = Java.use("com.xiaojianbang.app.Utils");
var overloads  = Utils["test"].overloads;
for (var i=0;i< overloads.length;i++){
    overloads[i].implementation = function () {
       var params = "";
       for(var j=0;j<arguments.length;j++){
        params = params +arguments[j]+" "
       }
       console.log("params",params)
        
        return this.test.apply(this,arguments);
    };
}

hook所有方法

把想Hook的类的完整包名,卸载distClassArr数组中

setTimeout(function(){
    Java.perform(function () {
        try {
            var distClassArr = ["com.efs.sdk.base.core.b.a$a","com.efs.sdk.base.core.b.a","com.efs.sdk.base.core.a.d","com.efs.sdk.base.core.a.c","com.efs.sdk.base.core.a.b$a","com.efs.sdk.base.core.a.b","com.efs.sdk.base.core.a.a$a","com.efs.sdk.base.core.a.a"]
            var classz = Java.enumerateLoadedClassesSync();
            for (var i = 0; i < classz.length; i++) {
                try {
                    var class_name = classz[i];
                    if (class_name.indexOf("android") != -1 
                        || class_name.indexOf("androidx") != -1 || class_name.indexOf("sun.") != -1
                       || class_name.indexOf("java") != -1 || class_name.indexOf("javax") != -1 || class_name.indexOf("kotlin") != -1
                       || class_name.indexOf("okhttp") != -1 || class_name.indexOf("int") != -1
                       || class_name.indexOf("org.") != -1 || class_name.indexOf("retrofit2") != -1
                       || class_name.indexOf("libcore") != -1 || class_name.indexOf("dalvik") != -1
                       || class_name.indexOf("char") != -1
                       || class_name.indexOf("double") != -1|| class_name.indexOf("float") != -1
                       || class_name.indexOf("long") != -1 || class_name.indexOf("short") != -1
                       || class_name.indexOf("void") != -1 || class_name.indexOf("boolean") != -1
                       || class_name.indexOf("byte") != -1 || class_name.indexOf("r2.") != -1
                       || class_name.indexOf("okio.") != -1 || class_name.indexOf("junit.") != -1
                       || class_name.indexOf("[") != -1 || class_name.indexOf("io.") != -1
                       ) {
                        continue;
                    }
                    if (class_name.indexOf("com") != -1 && class_name.indexOf("piaoxingqiu") === -1) {
                        continue;
                    }
                    if (class_name.indexOf("com") != -1 && class_name.indexOf("juqi") === -1) {
                        continue;
                    }
                    if(distClassArr.indexOf(class_name) === -1){
                        continue;
                    }
                    console.log("Java.use:",class_name)
                    var cz = Java.use(class_name);
                    if(!cz){
                        continue;
                    }
                    //获取该类的所有公共方法(包含父类的),得到的是一个数组
                    //var methods = cz.class.getMethods();
                    //获取该类所有的私有方法(不包含父类),得到的是一个数组
                    var methods = cz.class.getDeclaredMethods();
                    console.log("all methods",class_name,methods)
                    for (var i1 = 0; i1 < methods.length-1; i1++) {
                        var classz_method_name = methods[i1].getName();
                        if(classz_method_name.indexOf("hashCode") != -1){
                            continue;
                        }
                        try {
                            var overloadAyy = cz[classz_method_name].overloads;
                            if (overloadAyy && overloadAyy.length>0){
                                for (var i2 = 0; i2 < overloadAyy.length; i2++) {
                                    console.log("will be hook overload impl method: ",class_name,overloadAyy[i2])
                                    overloadAyy[i2].implementation = function () {
                                        console.log("call overload method ", class_name, classz_method_name)
                                        console.log("this[classz_method_name]", this[classz_method_name])
                                        if (arguments.length);
                                        for (var j = 0; j < arguments.length; j++) {
                                            console.log("param[" + j + "]: " + arguments[j]);
                                        }
                                        if(!this[classz_method_name] || this[classz_method_name] === 'undefined'){
                                            console.log("method null..",classz_method_name)
                                        }
                                        try {
                                            var retval = this[classz_method_name].apply(this, arguments);
                                            console.log("retval=",retval)
                                            return retval
                                        } catch (error) {
                                            console.log(error)
                                            console.log("-----1-----", class_name, classz_method_name)
                                        }
                                    };
                                }
                            }else{
                                console.log("hook impl method: ",cz[classz_method_name])
                                cz[classz_method_name].implementation = function () {
                                    if (arguments.length) console.log();
                                    for (var j = 0; j < arguments.length; j++) {
                                        console.log("param[" + j + "]: " + arguments[j]);
                                    }
                                    console.log("call method params", class_name, classz_method_name)
                                    console.log("cz[classz_method_name]", cz[classz_method_name])
                                    try {
                                        var retval = cz[classz_method_name].apply(this, arguments);
                                        console.log("retval=",retval)
                                        return retval
                                    } catch (error) {
                                        console.log(error)
                                        console.log("-----2-----", class_name, classz_method_name)
                                    }
                                };
                            }
                        } catch (error) {
                            console.log(error)
                            console.log("-----3-----", class_name, classz_method_name)
                        }
                    }
                }catch (error) {
                    console.log(error)
                    console.log("-----4-----", class_name)
                }
            }
        } catch (error) {
            console.log(error)
            console.log("33333")
        }
        
    });
},10000);

hook 所有Http请求

下面不一定全

Java.perform(function() {
    var URL = Java.use("java.net.URL");
    var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");
    var HttpURLConnection = Java.use("java.net.HttpURLConnection");
    var OutputStreamWriter = Java.use("java.io.OutputStreamWriter");
    var BufferedReader = Java.use("java.io.BufferedReader");
    var InputStreamReader = Java.use("java.io.InputStreamReader");
 
    var urloverloads  = URL["$init"].overloads;
    for (var i=0;i< urloverloads.length;i++){
        urloverloads[i].implementation = function () {
           var params = "";
           for(var j=0;j<arguments.length;j++){
            params = params +arguments[j]+" "
           }
           console.log("params",params)
           return this.$init.apply(this,arguments);
        };
    }
 
    HttpsURLConnection.setDoOutput.implementation = function(value) {
        console.log("[*] setDoOutput:", value);
        return this.setDoOutput(value);
    };
 
    HttpsURLConnection.setRequestProperty.implementation = function(key, value) {
        console.log("[*] setRequestProperty:", key, value);
        return this.setRequestProperty(key, value);
    };
 
    HttpsURLConnection.getOutputStream.implementation = function() {
        console.log("[*] getOutputStream");
        return this.getOutputStream();
    };
 
    HttpURLConnection.setRequestProperty.implementation = function(key, value) {
        console.log("[*] setRequestProperty:", key, value);
        return this.setRequestProperty(key, value);
    };
 
    HttpURLConnection.setDoOutput.implementation = function(value) {
        console.log("[*] setDoOutput:", value);
        return this.setDoOutput(value);
    };
 
    HttpURLConnection.getOutputStream.implementation = function() {
        console.log("[*] getOutputStream");
        return this.getOutputStream();
    };

    var writeoverloads  = OutputStreamWriter["write"].overloads;
    for (var i=0;i< writeoverloads.length;i++){
        writeoverloads[i].implementation = function () {
           var params = "";
           for(var j=0;j<arguments.length;j++){
            params = params +arguments[j]+" "
           }
           console.log("params",params)
            
            return this.write.apply(this,arguments);
        };
    }
    var readLineoverloads  = BufferedReader["readLine"].overloads;
    for (var i=0;i< readLineoverloads.length;i++){
        readLineoverloads[i].implementation = function () {
           var params = "";
           for(var j=0;j<arguments.length;j++){
            params = params +arguments[j]+" "
           }
           console.log("params",params)
            
            return this.readLine.apply(this,arguments);
        };
    }

InputStreamReader.$init.overload('java.io.InputStream').implementation = function(stream) {
        console.log("[*] InputStreamReader.init:", stream);
        return this.$init(stream);
    };
});

hook 所有Socket请求

摘自《android抓包学习的整理和归纳

function print_bytes(bytes) {
    var buf  = Memory.alloc(bytes.length);
    Memory.writeByteArray(buf, byte_to_ArrayBuffer(bytes));
    console.log(hexdump(buf, {offset: 0, length: bytes.length, header: false, ansi: true}));
}
function byte_to_ArrayBuffer(bytes) {
    var size=bytes.length;
    var tmparray = [];
    for (var i = 0; i < size; i++) {
        var val = bytes[i];
        if(val < 0){
            val += 256;
        }
        tmparray[i] = val
    }
    return tmparray;
}
function hook_tcp(){
    var socketClass= Java.use("java.net.Socket");
    socketClass.$init.overload('java.net.InetAddress', 'int').implementation=function(ip,port){
        console.log("socket$init ",ip,":",port);
        return this.$init(ip,port);
    };
    var outputClass=Java.use("java.net.SocketOutputStream");
    outputClass.socketWrite0.implementation=function(fd,buff,off,len){
        console.log("tcp write fd:",fd);
        print_bytes(buff);
        return this.socketWrite0(fd,buff,off,len);
    };

    var inputClass=Java.use("java.net.SocketInputStream");
    inputClass.socketRead0.implementation=function(fd,buff,off,len,timeout){
        var res=this.socketRead0(fd,buff,off,len,timeout);
        console.log("tcp read fd:",fd)
        print_bytes(buff);
        return res;
    };
}
//SSL_write(long sslNativePointer, FileDescriptor fd,
//             SSLHandshakeCallbacks shc, byte[] b, int off, int len, int writeTimeoutMillis)
//SSL_read(long sslNativePointer, FileDescriptor fd, SSLHandshakeCallbacks shc,
//             byte[] b, int off, int len, int readTimeoutMillis)
function getSocketData(fd){
    console.log("fd:",fd);
    var socketType=Socket.type(fd)
    if(socketType!=null){
        var res="type:"+socketType+",loadAddress:"+JSON.stringify(Socket.localAddress(fd))+",peerAddress"+JSON.stringify(Socket.peerAddress(fd));
        return res;
    }else{
        return "type:"+socketType;
    }
}
function getSocketData2(stream){
    var data0=stream.this$0.value;
    var sockdata=data0.socket.value;
    return sockdata;
}
function hook_ssl(){
    var NativeCryptoClass= Java.use("com.android.org.conscrypt.NativeCrypto");
    NativeCryptoClass.SSL_write.implementation=function(sslPtr,nativeSsl,fd,shc,b,off,len,timeout){
        console.log("enter SSL_write");
        print_bytes(b);
        return this.SSL_write(sslPtr,nativeSsl,fd,shc,b,off,len,timeout);
    };
    NativeCryptoClass.SSL_read.implementation=function(sslPtr,nativeSsl,fd,shc,b,off,len,timeout){
        console.log("enter SSL_read");
        var res=this.SSL_read(sslPtr,nativeSsl,fd,shc,b,off,len,timeout);
        print_bytes(b);
        return res;
    };
}


//SSLOutputStream  write(byte[] buf, int offset, int byteCount)
//SSLInputStream     read(byte[] buf, int offset, int byteCount)
function hook_ssl2(){
    var SSLOutputClass=Java.use("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLOutputStream");
    SSLOutputClass.write.overload('[B', 'int', 'int').implementation=function(buf,off,cnt){
        console.log(getSocketData2(this));
        print_bytes(buf);
        return this.write(buf,off,cnt);
    };
    var SSLInputClass=Java.use("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream");
    SSLInputClass.read.overload('[B', 'int', 'int').implementation=function(buf,off,cnt){
        var res=this.read(buf,off,cnt);
        console.log(getSocketData2(this));
        print_bytes(buf);
        return res;
    }
}
function hook_jni_ssl_enc(){
    var writePtr=Module.getExportByName("libc.so","write");
    var readPtr=Module.getExportByName("libc.so","read");
    console.log("write:",writePtr,",read:",readPtr);
    Interceptor.attach(writePtr,{
        onEnter:function(args){
            var fd=args[0];
            var buff=args[1];
            var size=args[2];
            var sockdata=getSocketData(fd.toInt32());
            if(sockdata.indexOf("tcp") != -1){
                console.log(sockdata);
                console.log(hexdump(buff,{length:size.toInt32()}));
            }
        },
        onLeave:function(retval){

        }
    });
    Interceptor.attach(readPtr,{
        onEnter:function(args){
            this.fd=args[0];
            this.buff=args[1];
            this.size=args[2];
        },
        onLeave:function(retval){
            var sockdata=getSocketData(this.fd.toInt32());
            if(sockdata.indexOf("tcp") != -1){
                console.log(sockdata);
                console.log(hexdump(this.buff,{length:this.size.toInt32()}));
            }
        }
    });
}
function hook_jni_ssl(){
    var sslWritePtr=Module.getExportByName("libssl.so","SSL_write");
    var sslReadPtr=Module.getExportByName("libssl.so","SSL_read");
    console.log("sslWrite:",sslWritePtr,",sslRead:",sslReadPtr);
    var sslGetFdPtr=Module.getExportByName("libssl.so","SSL_get_rfd");
    var sslGetFdFunc=new NativeFunction(sslGetFdPtr,'int',['pointer']);

    //int SSL_write(SSL *ssl, const void *buf, int num)
    Interceptor.attach(sslWritePtr,{
        onEnter:function(args){
            var sslPtr=args[0];
            var buff=args[1];
            var size=args[2];
            var fd=sslGetFdFunc(sslPtr);
            var sockdata=getSocketData(fd);
            console.log(sockdata);
            console.log(hexdump(buff,{length:size.toInt32()}));

        },
        onLeave:function(retval){

        }
    });
    //int SSL_read(SSL *ssl, void *buf, int num)
    Interceptor.attach(sslReadPtr,{
        onEnter:function(args){
            this.sslPtr=args[0];
            this.buff=args[1];
            this.size=args[2];
        },
        onLeave:function(retval){
            var fd=sslGetFdFunc(this.sslPtr);
            var sockdata=getSocketData(fd);
            console.log(sockdata);
            console.log(hexdump(this.buff,{length:this.size.toInt32()}));
        }
    });
}

function hook_jni_tcp(){
    var sendtoPtr=Module.getExportByName("libc.so","sendto");
    var recvfromPtr=Module.getExportByName("libc.so","recvfrom");
    console.log("sendto:",sendtoPtr,",recvfrom:",recvfromPtr);
    //sendto(int fd, const void *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len)
    Interceptor.attach(sendtoPtr,{
        onEnter:function(args){
            var fd=args[0];
            var buff=args[1];
            var size=args[2];
            var sockdata=getSocketData(fd.toInt32());
            console.log(sockdata);
            console.log(hexdump(buff,{length:size.toInt32()}));
        },
        onLeave:function(retval){

        }
    });
    //recvfrom(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *addr_len)
    Interceptor.attach(recvfromPtr,{
        onEnter:function(args){
            this.fd=args[0];
            this.buff=args[1];
            this.size=args[2];
        },
        onLeave:function(retval){
            var sockdata=getSocketData(this.fd.toInt32());
            console.log(sockdata);
            console.log(hexdump(this.buff,{length:this.size.toInt32()}));
        }
    });
}

function hook_java(){
    Java.perform(function(){
        // hook_tcp();
        // hook_ssl();//不打印socket IP地址
        // hook_ssl2();//打印socket IP地址
        
        // hook_jni_tcp();
        hook_jni_ssl_enc();//密文
        //hook_jni_ssl();//明文
    })
}
function getFullName(name){
    Java.perform(function(){
        Java.enumerateLoadedClassesSync().forEach(function(className){
            if(className.indexOf(name)!=-1){
                console.log(className);
            }
        })
    });
}

function main(){
    hook_java();
    // getFullName("SSLOutputStream")
}

setImmediate(main);

实现okhttp3.Interceptor

Java.perform(function () {
        var ByteString = Java.use("com.android.okhttp.okio.ByteString");
        var Buffer = Java.use("com.android.okhttp.okio.Buffer");
        var Interceptor = Java.use("okhttp3.Interceptor");
        var MyInterceptor = Java.registerClass({
            name: "okhttp3.MyInterceptor",
            implements: [Interceptor],
            methods: {
                intercept: function (chain) {
                    var request = chain.request();
                    try {
                        console.log("MyInterceptor.intercept onEnter:", request, "\nrequest headers:\n", request.headers());
                        var requestBody = request.body();
                        var contentLength = requestBody ? requestBody.contentLength() : 0;
                        if (contentLength > 0) {
                            var BufferObj = Buffer.$new();
                            requestBody.writeTo(BufferObj);
                            try {
                                console.log("\nrequest body String:\n", BufferObj.readString(), "\n");
                            } catch (error) {
                                try {
                                    console.log("\nrequest body ByteString:\n", ByteString.of(BufferObj.readByteArray()).hex(), "\n");
                                } catch (error) {
                                    console.log("error 1:", error);
                                }
                            }
                        }
                    } catch (error) {
                        console.log("error 2:", error);
                    }
                    var response = chain.proceed(request);
                    try {
                        console.log("MyInterceptor.intercept onLeave:", response, "\nresponse headers:\n", response.headers());
                        var responseBody = response.body();
                        var contentLength = responseBody ? responseBody.contentLength() : 0;
                        if (contentLength > 0) {
                            console.log("\nresponsecontentLength:", contentLength, "responseBody:", responseBody, "\n");
 
                            var ContentType = response.headers().get("Content-Type");
                            console.log("ContentType:", ContentType);
                            if (ContentType.indexOf("video") == -1) {
                                if (ContentType.indexOf("application") == 0) {
                                    var source = responseBody.source();
                                    if (ContentType.indexOf("application/zip") != 0) {
                                        try {
                                            console.log("\nresponse.body StringClass\n", source.readUtf8(), "\n");
                                        } catch (error) {
                                            try {
                                                console.log("\nresponse.body ByteString\n", source.readByteString().hex(), "\n");
                                            } catch (error) {
                                                console.log("error 4:", error);
                                            }
                                        }
                                    }
                                }
 
                            }
 
                        }
 
                    } catch (error) {
                        console.log("error 3:", error);
                    }
                    return response;
                }
            }
        });
        var ArrayList = Java.use("java.util.ArrayList");
        var OkHttpClient = Java.use("okhttp3.OkHttpClient");
        console.log(OkHttpClient);
        OkHttpClient.$init.overload('okhttp3.OkHttpClient$Builder').implementation = function (Builder) {
            console.log("OkHttpClient.$init:", this, Java.cast(Builder.interceptors(), ArrayList));
            this.$init(Builder);
        };
 
        var MyInterceptorObj = MyInterceptor.$new();
        var Builder = Java.use("okhttp3.OkHttpClient$Builder");
        console.log(Builder);
        Builder.build.implementation = function () {
            this.interceptors().clear();
            //var MyInterceptorObj = MyInterceptor.$new();
            this.interceptors().add(MyInterceptorObj);
            var result = this.build();
            return result;
        };
 
        Builder.addInterceptor.implementation = function (interceptor) {
            this.interceptors().clear();
            //var MyInterceptorObj = MyInterceptor.$new();
            this.interceptors().add(MyInterceptorObj);
            return this;
            //return this.addInterceptor(interceptor);
        };
 
        console.log("hook_okhttp3...");
    });
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值