Sahil Dhar Application Security and Exploitation all day everyday.

    Following are some of the frida snippets I have written in past to bypass some of the client-side checks in android apps.

    Decrypting SQLCipher Encrypted Databases

    
    /*
    Modifications: Change <app_name> accordingly
    */
    
    Java.perform(function () {
        var random_name = function (length) {
            var result = '';
            var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            var charactersLength = characters.length;
            for (var i = 0; i < length; i++) {
                result += characters.charAt(Math.floor(Math.random() * charactersLength));
            }
            return result;
        }
        Java.choose("net.sqlcipher.database.SQLiteDatabase", {
            onMatch: function (ins) {
                console.log(ins.getPath());
                console.log(ins.isOpen());
                var dbName = random_name(5);
                var sql1 = String.$new("ATTACH DATABASE '/data/user/0/<app_name>/databases/" + dbName + ".sql.plaintext' as " + dbName + " KEY '';");
                var sql2 = String.$new("SELECT sqlcipher_export('" + dbName + "');");
                var sql3 = String.$new("DETACH DATABASE " + dbName);
                ins.rawExecSQL(sql1);
                ins.rawExecSQL(sql2);
                ins.rawExecSQL(sql3);
                console.log("Found SqlCipherDatabaseProvider instance");
            },
            onComplete: function (ins) { }
        });
    })
    

    SSL pinning bypass implemented via okhttp3

    Java.perform(function(){
    
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');
        CertificatePinner.check$okhttp.overload('java.lang.String', 'kotlin.jvm.functions.Function0').implementation = function(x, y) {
            console.log("[+] OkHTTP 3 check$okhttp() bypassed.");
            
        };
    })
    

    Detect keystore access without authentication

    /*
    Modifications: <keystore class> : Change keystore class name accordingly
    Output: prints keys stored in keystore in a device's locked state 
    */
    
    function hookCipherInit(){
        var _cipher = Java.use("javax.crypto.Cipher")
        _cipher.init.overload("int", "java.security.Key", "java.security.spec.AlgorithmParameterSpec").implementation = function(mode, key){
            console.log(printModes(mode));
            hookGetkey();
            return this.init.overload("int", "java.security.Key", "java.security.spec.AlgorithmParameterSpec").apply(this, arguments);
        }
    }
    
    function printModes(mode){
        if (mode == 1){
            return "\nEncrypt Mode"
        } else if(mode == 2){  
            return "\nDecrypt Mode"
        }
    }
    
    function hookGetkey(){
        var secretStore = Java.use("<keystore class>")
        secretStore.getKey.implementation = function(keyName){
            console.log(keyName);
            return this.getKey.apply(this,arguments)
        }
    }
    
    function hookCipherDoFinal() {
        var _cipher = Java.use('javax.crypto.Cipher');
        _cipher.doFinal.overload("[B").implementation = function (byteArr) {
            var result = this.doFinal(byteArr);
            javaHexdump(result);
            return result;
        }
    }
    
    function javaHexdump(array) {
        var ptr = Memory.alloc(array.length);
        for(var i = 0; i < array.length; ++i)
            Memory.writeS8(ptr.add(i), array[i]);
        console.log(hexdump(ptr, { offset: 0, length: array.length, header: false, ansi: true}));
    }
    
    Java.perform(function(){
        hookCipherInit()
        hookCipherDoFinal();
    });
    

    SSL pinning bypass for CURL specific implementation

    /*
    - Steps:
    - Obtain the base address of example_so_lib
    - Obtain the binary offset from IDA pro
    - add the binary offset to lib base to obtain the function pointer for function curl_easy_setopt()
    - Based on the second argument / curl setting passed overwite the third argument passed to the function
    */
    function dump_address(addr) {
        var i = 0;
        var pc = ptr(addr)
        console.log("Dumping addr: " + addr);
        while (i < 20) {
            var instr = Instruction.parse(pc);
            var caddr = instr['address'];
            var cinstr = instr.toString();
            console.log(caddr + " " + cinstr);
            pc = ptr(instr['next'])
            i += 1;
        }
    }
    
    
    function disableSSLPinning() {
        var libProcess = Process.findModuleByName("example_so_lib.so");
        var curl_opt_offset = libProcess.base.add(0x1AFFFFF);
        console.log("libProcess module is loaded at " + libProcess.base.toString())
        var verifyPeerEnabled = libProcess.base.add(0x02BFFFFF);
        var verifyPeerDisabled = libProcess.base.add(0x03BFFFFF);
        var verifyHostEnabled = libProcess.base.add(0x04CFFFFF);
        var verifyHostDisabled = libProcess.base.add(0x05DFFFFF);
    
    
        Interceptor.attach(curl_opt_offset, {
            onEnter: function (args) {
                this.arg1 = args[1];
                this.arg2 = args[2];
    
            },
            onLeave: function (retval) {
                // CURLOPT_SSL_CIPHER_LIST = 0x2763
                if (this.arg1.toString() == "0x2763") {
                    console.log("[+] Patching curl_easy_setopt:CURLOPT_SSL_CIPHER_LIST");
                    console.log(ptr(this.arg2).readUtf8String())
                    console.log("[+] arg2 is referenced from: " + this.arg2);
                    console.log("[+] Previous Cipher suite value: " + ptr(this.arg2).readCString());
                    if (ptr(this.arg2).readCString() == "<cipher_name>") {
                        ptr(this.arg2).writeUtf8String("DEFAULT\x00");
                        console.log("[+] Replaced cipher suite to default");
                    }else{
                        console.log("[I] Priting second argument anyway");
                        console.log(ptr(this.arg2).readCString());
                    }
                }
    
                if (this.arg1 == 0x40) {
    
                    console.log("[+] Patching curl_easy_setopt:CURLOPT_SSL_VERIFYPEER");
                    Memory.protect(verifyPeerEnabled, 4, 'rwx');
                    var b_array = verifyPeerEnabled.readByteArray(4);
                    console.log(b_array);
                    verifyPeerEnabled.writeByteArray(verifyPeerDisabled.readByteArray(4));
                    console.log('[+] Patched state peer verification');
                    var b_array = verifyPeerEnabled.readByteArray(4);
                    console.log(b_array);
                    Memory.protect(verifyPeerEnabled, 4, 'r-x');
                }
                if (this.arg1 == 0x51) {
                    console.log("[+] Patching curl_easy_setopt:CURLOPT_SSL_VERIFYHOST");
                    Memory.protect(verifyHostEnabled, 4, 'rwx');
                    var b_array = verifyHostEnabled.readByteArray(4);
                    console.log(b_array);
                    verifyHostEnabled.writeByteArray(verifyHostDisabled.readByteArray(4));
                    console.log('[+] Patched state host verification');
                    var b_array = verifyHostEnabled.readByteArray(4);
                    console.log(b_array);
                    Memory.protect(verifyHostEnabled, 4, 'r-x');
                }
                return retval;
            }
        });
    }
    
    Java.perform(function () {
        const System = Java.use('java.lang.System');
        const Runtime = Java.use('java.lang.Runtime');
        const VMStack = Java.use('dalvik.system.VMStack');
    
        System.loadLibrary.implementation = function (library) {
            try {
                if (library == "<another_lib>") {
                    // Ensuring that example_so_lib.so is being loaded
                    disableSSLPinning()
                }
                const loaded = Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), library);
                return loaded;
            } catch (ex) {
                console.log(ex);
            }
        };
    });