• frida入门总结


        Frida是一款轻量级HOOK框架,可用于多平台上,例如android、windows、ios等。
        frida分为两部分,服务端运行在目标机上,通过注入进程的方式来实现劫持应用函数,另一部分运行在系统机器上。
        frida上层接口支持js、python、c等。
        Frida官方github地址为:frida官方github地址

        PS:虽然百度一下会发现frida教程有不少,但是涉及到native层的教程基本很少,然后对每一句Hook代码解释一下的更是少之又少,所以我还是厚着脸皮从自己的角度写了这一篇!!!


    0|1二、Frida安装


        1 、安装python3.7并配置好环境变量(官方推荐python3以上版本至少为3.7),python安装包官方下载地址:https://www.python.org/downloads/

        2 、安装frida模块,命令为pip install frida(配置了多个python版本环境的可以使用命令python -m pip install frida防止用pip install frida命令报错)。

    1.png

        3、安装frida-tools模块,命令同上,pip install frida-tools或者python -m pip install frida-tools

    2.png

        4、下载运行在目标机上的frida-sever端,官方下载地址:https://github.com/frida/frida/releases,下载时要选择对应的版本下载,例如我的机器为arm32为架构,就选择frida-server-12.8.14-android-arm.xz下载。(可以在adb使用命令cat /proc/cpuinfo查询)

    3.png

    4.png

        5、将第四步下载好的文件解压,然后通过命令adb push 你的电脑是存放位置 /data/local/tmp将文件传输到手机中,然后通过adb shell进入手机端,给文件赋权777,并于root权限启动。

    5.png

    6.png

        6、做完以上几步后,新开一个命令行输入命令frida-ps -U查看手机进程,如果出现以下结果,则frida安装成功。

    7.png


    0|1三、Frida Hook Java层


        1、编写一个小demo用来hook,该demo关键部分代码如下:

    8.png

        2、现在我们将该apk安装好,运行看一下未Hook前的显示字符串!!!

    9.png

        3、现在来编写Hook的Python脚本,脚本代码如下:

    import frida #导入frida模块 import sys #导入sys模块 jscode = """ #从此处开始定义用来Hook的javascript代码 Java.perform(function(){ var MainActivity = Java.use('com.example.testfrida.MainActivity'); //获得MainActivity类 MainActivity.testFrida.implementation = function(){ //Hook testFrida函数,用js自己实现 send('Statr! Hook!'); //发送信息,用于回调python中的函数 return 'Change String!' //劫持返回值,修改为我们想要返回的字符串 } }); """ def on_message(message,data): #js中执行send函数后要回调的函数 print(message) process = frida.get_remote_device().attach('com.example.testfrida') #得到设备并劫持进程com.example.testfrida(该开始用get_usb_device函数用来获取设备,但是一直报错找不到设备,改用get_remote_device函数即可解决这个问题) script = process.create_script(jscode) #创建js脚本 script.on('message',on_message) #加载回调函数,也就是js中执行send函数规定要执行的python函数 script.load() #加载脚本 sys.stdin.read()

        4、现在python脚本编写完毕,我们来执行该脚本,首先手机端执行frida,然后通过命令adb forward tcp:27043 tcp:27043adb forward tcp:27042 tcp:27042来转发这两个端口,接着在手机上运行该应用程序,在命令行中执行脚本,最后点击应用的按钮,即可看到字符串已经被替换成我们要替换的了!!!

    6.png

    10.png

    11.png

    12.png


    0|1四、Frida Hook Native层


      4.1、Hook native层返回值为int类型的demo

        1、还是先写一个小demo,下面贴一下关键代码(很简单c语言代码就不再解释了,至于native层函数怎么编写,由于本篇主要不是讲怎么编写so函数,就不过多叙述了,实在不会的可以看一下我的一篇博客,我觉得写得还是挺详细的,博客编写native层函数链接:https://www.cnblogs.com/aWxvdmVseXc0/p/11564809.html)和未Hook前截图:

    23.png

    代码:

    /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_fridaso_FridaSoDefine */ #ifndef _Included_com_example_fridaso_FridaSoDefine #define _Included_com_example_fridaso_FridaSoDefine #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_fridaso_FridaSoDefine * Method: FridaSo * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_fridaso_FridaSoDefine_FridaSo(JNIEnv *env, jclass obj, jint a, jint b) { int c; c = a + b; return c; } #ifdef __cplusplus } #endif #endif

    13.png

    14.png

        2、接下来我们来写python hook脚本,我们需要hook native层这个函数,达到返回值修改为0的效果。写到这里需要说明一下关于so文件当中的函数,分为导出函数和未导出函数两种,导出函数打开IDA后能够在导出表中找到的函数就是导出函数,未导出函数则在导出表中寻找不到,一般来说静态编写的native函数都能在导出表中寻找到,而动态加载的则无法在导出表中发现!!!

    15.png

    代码如下:(跟上面hook java层重复的代码不在注释详讲了!!!)

    import frida import sys jscode = """ Java.perform(function(){ //下面这一句代码是指定要Hook的so文件名和要Hook的函数名,函数名就是上面IDA导出表中显示的那个函数名 Interceptor.attach(Module.findExportByName("libfridaso.so","Java_com_example_fridaso_FridaSoDefine_FridaSo"),{ //onEnter: function(args)顾名思义就是进入该函数前要执行的代码,其中args是传入的参数,一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始才是我们java层传入的参数 onEnter: function(args) { send("Hook start"); send("args[2]=" + args[2]); //打印我们java层第一个传入的参数 send("args[3]=" + args[3]); //打印我们java层传入的第二个参数 }, onLeave: function(retval){ //onLeave: function(retval)是该函数执行结束要执行的代码,其中retval参数即是返回值 send("return:"+retval); //打印返回值 retval.replace(0); //替换返回值为0 } }); }); """ def printMessage(message,data): if message['type'] == 'send': print('[*] {0}'.format(message['payload'])) else: print(message) process = frida.get_remote_device().attach('com.example.fridaso') script = process.create_script(jscode) script.on('message',printMessage) script.load() sys.stdin.read()

        3、最后在手机端执行frida-server,转发端口,开启应用,执行脚本,点击按钮,即可看到返回值已经被修改成了0,效果图如下:

    16.png

    17.png

      4.2、Hook native层返回值为String类型的demo

        1、上面已经写了怎么Hook修改native层函数返回值为int类型的情况,使用replace()函数直接修改即可,但是返回情况为字符串则不一样,在c语言中,返回值为字符串其实是返回了一个char *(字符串指针),所以简单的替换是无法取效果的,具体怎么修改返回值,接着看下面,下面还是贴上demo的关键代码和未Hook前截图:

    22.png

    代码如下:

    /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_fridasostring_fridaSoString */ /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_fridasostring_fridaSoString */ #ifndef _Included_com_example_fridasostring_fridaSoString #define _Included_com_example_fridasostring_fridaSoString #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_fridasostring_fridaSoString * Method: FridaSo * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_fridasostring_fridaSoString_FridaSo(JNIEnv *env, jclass obj, jstring str) { return str; } #ifdef __cplusplus } #endif #endif

    未Hook前运行截图:

    18.png

        2、接下来是python Hook脚本(只解释与上面有差异的代码),Hook的函数具体函数名还是使用IDA去寻找

    19.png

    python代码:

    import frida import sys jscode = """ Java.perform(function(){ Interceptor.attach(Module.findExportByName("libfridaso.so","Java_com_example_fridasostring_fridaSoString_FridaSo"),{ onEnter: function(args) { send("Hook start"); send("args[2]=" + args[2]); }, onLeave: function(retval){ send("return:"+retval); var env = Java.vm.getEnv(); //获取env对象,也就是native函数的第一个参数 var jstrings = env.newStringUtf("tamper"); //因为返回的是字符串指针,使用我们需要构造一个newStringUtf对象,用来代替这个指针 retval.replace(jstrings); //替换返回值 } }); }); """ def printMessage(message,data): if message['type'] == 'send': print('[*] {0}'.format(message['payload'])) else: print(message) process = frida.get_remote_device().attach('com.example.fridasostring') script = process.create_script(jscode) script.on('message',printMessage) script.load() sys.stdin.read()

        3、运行脚本后,点击按钮,我们可以看到字符串已经被替换成了tamper,如下所示:

    20.png

    21.png

        4、关于为导出函数的Hook,大体上差不多,差别在于需要通过ida找到偏移值计算地址,而不是像导出函数这么方便罢了,但原理都是差不多的,就不在细说了!!!

    转载请注明出处
  • 相关阅读:
    团队项目-第一阶段冲刺7
    团队项目-第一阶段冲刺6
    Spring Boot 揭秘与实战(七) 实用技术篇
    Spring Boot 揭秘与实战(七) 实用技术篇
    Spring Boot 揭秘与实战(六) 消息队列篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(四) 配置文件篇
  • 原文地址:https://www.cnblogs.com/ssw6/p/15016789.html
Copyright © 2020-2023  润新知