(frida小记)native层Hook

native层Hook

写到这里需要说明一下关于so文件当中的函数,分为导出函数和未导出函数两种,导出函数打开IDA后能够在导出表中找到的函数就是导出函数,未导出函数则在导出表中寻找不到,一般来说静态编写的native函数都能在导出表中寻找到,而动态加载的则无法在导出表中发现!!!
(frida小记)native层Hook_第1张图片

Hook的目标依然是01里面编译出的APK

python frida native:
# coding:utf-8
import frida
import sys

jscode = """
Java.perform(function(){
    //下面这一句代码是指定要Hook的so文件名和要Hook的函数名,函数名就是上面IDA导出表中显示的那个函数名
    Interceptor.attach(Module.findExportByName("libnative-lib.so","Java_com_alex_nativehooktarget_MainActivity_intFromJNI"),{
        //onEnter: function(args)顾名思义就是进入该函数前要执行的代码,其中args是传入的参数,一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始才是我们java层传入的参数
        onEnter: function(args) {
            send("Hook start");
            send("args[0]=" + args[0]); //打印我们java层第一个传入的参数
            send("args[1]=" + args[1]); //打印我们java层传入的第二个参数
        },
        onLeave: function(retval){ //onLeave: function(retval)是该函数执行结束要执行的代码,其中retval参数即是返回值
            send("return:"+retval); //打印返回值
            retval.replace(10086); //替换返回值为0
        }
    });

    //当Native返回的字符串时,在C中字符串是字符数组的指针表示的,所以不能直接replace,要用env.newStringUtf
    Interceptor.attach(Module.findExportByName("libnative-lib.so","Java_com_alex_nativehooktarget_MainActivity_stringFromJNI"),{
        onEnter: function(args) {
            send("Hook start");
            send("args[0]=" + args[0]); //打印我们java层第一个传入的参数
            send("args[1]=" + args[1]); //打印我们java层传入的第二个参数
        },
        onLeave: function(retval){
            send("return:"+retval);
            var env = Java.vm.getEnv(); //获取env对象,也就是native函数的第一个参数
            var jstrings = env.newStringUtf("tamper"); //因为返回的是字符串指针,使用我们需要构造一个newStringUtf对象,用来代替这个指针
            retval.replace(jstrings); //替换返回值
        }
    });
    

    //照例一圈,没有找到直接替换jboolean或者JNI_TRUE的办法,JNI_TRUE是个C的宏,在这当然用不了。。。jboolean需要有个从js的布尔类型到它的转换方式才能用。。。
    //转念一想,既然上面打印出来的return都是个内存中的十六进制数,那么只需要返回非0x0的值不就是true了。。。
    Interceptor.attach(Module.findExportByName("libnative-lib.so","Java_com_alex_nativehooktarget_MainActivity_boolFromJNI"),{
        onEnter: function(args) {
            send("Hook start");
            send("args[0]=" + args[0]); //打印我们java层第一个传入的参数
            send("args[1]=" + args[1]); //打印我们java层传入的第二个参数
        },
        onLeave: function(retval){
            send("return:"+retval);
            //var myBoolean=new Boolean(true);
            retval.replace(0x1);
        }
    });

});
"""
def printMessage(message,data):
    if message['type'] == 'send':
        print(' {0}'.format(message['payload']))
    else:
        print(message)

process = frida.get_remote_device().attach('com.alex.nativehooktarget')
script = process.create_script(jscode)
script.on('message',printMessage)
script.load()
sys.stdin.read()

附一个Native层对象也就是C的对象在js中的表示方法:

def export_onClick(self):
    jobfile = QFileDialog.getSaveFileName(self, 'export', '', 'json file(*.json)')
    if isinstance(jobfile, tuple):
        jobfile = jobfile[0]
    if not jobfile:
        return
    f = open(jobfile, 'w')
    export = {}
    export['match_regex'] = self.app.match_regex_list
    export['black_regex'] = self.app.black_regex_list
    tree = {}
    for tid in self.app.thread_map:
        tree[self.app.thread_map[tid]['list'][0].text()] = gen_tree(self.app.thread_map[tid]['list'][0])
    export['tree'] = tree
    f.write(json.dumps(export))
    f.close()

再附一个,js怎么去new一个java对象并赋值的:

var czRequest = Java.use("com.bytedance.im.core.proto.Request");
如果Request的构造函数没有参数的话直接new
var objRequest = czRequest.$new();

接下来就是对objRequest 赋值了,具体要看 Request 类的定义

你可能感兴趣的:(reverse,android)