3,frida进阶-so方法hook

非原创, 来自 https://www.52pojie.cn/thread-1128884-1-1.html

hook int类型, 并修改返回值

import frida
import sys

jscode = """
Java.perform(function(){
    var str_name_so = "libfridaso.so";    //需要hook的so名
    var n_addr_func_offset = 0x00000500;         //需要hook的函数的偏移, ida打开即可看到
    var n_addr_so = Module.findBaseAddress(str_name_so); //加载到内存后 函数地址 = so地址 + 函数偏移
    var n_addr_func = parseInt(n_addr_so, 16) + n_addr_func_offset;
    var ptr_func = new NativePointer(n_addr_func);
    // var ptr_func = Module.findExportByName("libfridaso.so","Java_com_example_fridaso_FridaSoDefine_FridaSo"); //对函数名hook

    Interceptor.attach(ptr_func,{ 
        //onEnter: 进入该函数前要执行的代码,其中args是传入的参数,一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始是我们java层传入的参数
        onEnter: function(args) {
            send("Hook start");
            send("args[2]=" + args[2]); //第一个传入的参数
            send("args[3]=" + args[3]); //第二个参数
        },
        onLeave: function(retval){ //onLeave: 该函数执行结束要执行的代码,其中retval参数即是返回值
            send("return:"+retval); //返回值
            retval.replace(100);
        }
    });
});
"""
def printMessage(message,data):
    if message['type'] == 'send':
        print('[*] {0}'.format(message['payload']))
    else:
        print(message)

process = frida.get_remote_device().attach('fridaso') #进程名
script = process.create_script(jscode)
script.on('message',printMessage)
script.load()
sys.stdin.read()

hookstring, 并修改返回值

import frida
import sys

jscode = """
Java.perform(function(){
    // var str_name_so = "libfridaso.so";    //需要hook的so名
    // var n_addr_func_offset = 0x0000051C;         //需要hook的函数的偏移
    // var n_addr_so = Module.findBaseAddress(str_name_so); //加载到内存后 函数地址 = so地址 + 函数偏移
    // var n_addr_func = parseInt(n_addr_so, 16) + n_addr_func_offset;
    // var ptr_func = new NativePointer(n_addr_func);
    var ptr_func = Module.findExportByName("libfridaso.so","Java_com_example_fridasostring_fridaSoString_FridaSo"); //对函数名hook

    Interceptor.attach(ptr_func,{ 
        //onEnter: 进入该函数前要执行的代码,其中args是传入的参数,一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始是我们java层传入的参数
        onEnter: function(args) {
            send("Hook start");
            send("args[2]=" + args[2]); //第一个传入的参数
        },
        onLeave: function(retval){ //onLeave: 该函数执行结束要执行的代码,其中retval参数即是返回值
            send("return:"+retval); //返回值
            // retval 返回的是指针, 我们需要看其值
            console.log(jstring2Str(retval));
            var env = Java.vm.getEnv();
            var jstrings = env.newStringUtf("tamper");
            retval.replace(jstrings);
        }
    });
});

function jstring2Str(jstring) { //从frida_common_funs.js中copy出来
   var ret;
   Java.perform(function() {
       var String = Java.use("java.lang.String");
       ret = Java.cast(jstring, String);//jstring->String
   });
   return ret;
}
"""
def printMessage(message,data):
    if message['type'] == 'send':
        print('[*] {0}'.format(message['payload']))
    else:
        print(message)

process = frida.get_remote_device().attach('fridasostring') #进程名
script = process.create_script(jscode)
script.on('message',printMessage)
script.load()
sys.stdin.read()