Frida 原理及简单使用

Frida简介

Frida是一款基于Python + JavaScript 的hook框架,本质是一种动态插桩技术。可以用于Android、Windows、iOS等各大平台,其执行脚本基于Python或者Node.js写成,而注入代码用JavaScript写成,所以有必要了解一些这些语言的语法。本文主要讲述了Android上Frida框架的使用。

image

原理

frida使用的是动态二进制插桩技术DBI)。

插桩技术是指将额外的代码注入程序中以收集运行时的信息,可分为两种:

  1. 源代码插桩[Source Code Instrumentation(SCI)]:顾名思义,在程序源代码的基础上增加(注入)额外的代码,从而达到预期目的或者功能;
  2. 二进制插桩(Binary Instrumentation):额外代码注入到二进制可执行文件中,通过修改汇编地址,改变程序运行内容,运行后再返回到原来程序运行出处,从而实现程序的额外功能。
    ●静态二进制插桩[Static Binary Instrumentation(SBI)]:在程序执行前插入额外的代码和数据,生成一个永久改变的可执行文件。
    ●动态二进制插桩[Dynamic Binary Instrumentation(DBI)]:在程序运行时实时地插入额外代码和数据,对可执行文件没有任何永久改变。

DBI能做什么?

(1)访问进程的内存
(2)在应用程序运行时覆盖一些功能
(3)从导入的类中调用函数
(4)在堆上查找对象实例并使用这些对象实例
(5)Hook,跟踪和拦截函数等等

环境搭建

conda 安装python 环境

# 创建环境
conda create -n frida_ python=3.7

# 进入环境
# conda activate frida

安装frida 包

pip install frida -i https://pypi.mirrors.ustc.edu.cn/simple/ 
pip install frida-tools -i https://pypi.mirrors.ustc.edu.cn/simple/ 

vscode 配置代码提示

首先安装Node.js (nodejs.org),新建一个文件夹,在目录下执行下面这条命令。

npm i @types/frida-gum

image
g)

配置成功,可以在当前目录下编写js代码了。

Server环境配置

Releases · frida/frida (github.com)

下载Frida的Server端->frida-server-15.1.4-android-arm64.xz【这里版本要与hook程序架构适配】

然后push到手机的data/local/tmp目录下,和IDA的动态调试有点类似

adb devices  # 查看端口
adb.exe connect 127.0.0.1:62026

adb push .\frida-server-16.0.11-android-x86_64
/data/local/tmp/frida

adb shell
su
cd /data/local/tmp/frida

# 然后修改权限

chmod 777 frida-server-16.0.11-android-x86_64

# 直接运行frida服务

./frida-server-16.0.11-android-x86_64

# 开启端口转发,转发android TCP端口到本地

adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

如果能显示进程列表说明环境搭建完成

# PC端输入

frida-ps -R

image

Frida Hook

执行HOOK

首先来说一下如何执行hook代码

启动时hook,CMD输入

# 将 xxxxxx 换成你手机里安装好的任意apk包名

frida -U -f com.test.apk -l test.js --no-pause

启动apk后 hook

frida -U -f com.test.apk --no-pause
%load test.js

Java层hook

Frida的Java层重要函数

使用java平台—>Java.perform(function () {}
获取Java类 —>Java.use(className)
当我们获取到Java类之后,我们直接通过 <wrapper>.<method>.implementations =function() {}的方式来hook wrapper类的method方法,不管是实例方法还是静态方法都可以。

Hook普通方法

被hook的代码如下;

package com.example.xxx;


public class Student {
    static public int Add(int a,int b)
    {
        return a+b;
    }

}

接着编写Hook代码

function main()
{
     //使用java平台
     Java.perform(
        function() {
            //获取java类
            var student=Java.use("com.example.xxx.Student");
            //hook Add方法(重写Add方法) 
            student.Add.implementation=function(a,b)
            {
                //修改参数
                a=123;
                b=456;
                //调用原来的函数
                var res = this.Add(a,b);
                //输出结果
                console.log(a,b,res);
                return res;
            }
        }

     );

}
setImmediate(main)

Hook 执行so 函数

hook有导出函数

通过导出函数名称找到函数地址即可进行hook

// # com.xfast.hgr:bg


function main()
{
    Java.perform(function () {

        var JavaString = Java.use("java.lang.String");
       var adk_addr = Module.findExportByName("libnativelib.so","Java_com_faster_nativelib_NativeLib_adk");
       console.log("[*] 目标hook函数的内存地址是: " + adk_addr);
    //    var aes_128 = new NativeFunction(aes_addr , 'pointer', ['pointer', 'pointer']); // 返回值,参数

    Interceptor.attach(adk_addr,{
        //在hook函数之前执行的语句
        onEnter: function(args) 
        {
            console.log("[*] Success Hook So!");
        },	
        //在hook函数之后执行的语句
        onLeave:function(retval)
        {      
            console.log("[*] 原始的So层函数返回值是:"+ Java.vm.getEnv().getStringUtfChars(retval,null).readCString());
            // var change=1;
            // retval.replace(change);
            // console.log("[*] 篡改的So层函数返回值是:"+retval);
        }	
    });

    });
}
        // frida print String 类型返回值
        // //方式一
        // var element = Java.cast(obj,Java.use("java.lang.String"));
        // //方式二
        // var element = Java.vm.getEnv().getStringUtfChars(obj,null).readCString();
 
setImmediate(main)

执行

// 配置好环境
frida -UF com.xfast.hgr  -l test.js

或者
frida -UF com.xfast.hgr
%load test.js

成功hook 函数返回值。

image

# sdk() ret= faaf332a
# return outline.outline20("vs3ad", new NativeLib().adk(), "abb");

key = "vs3adfaaf332aabb"

hook无导出函数

.so 文件被去符号,无法找到对应函数名称,通过偏移地址调用函数。

function hookTest9()
{
    //so名称
    var so_name="libnative-lib.so";
    //要Hook的函数偏移
    var fun_off=0x7078;

   //加载到内存后,函数地址=so地址+函数偏移
   var so_add=Module.findBaseAddress(so_name);
   var add_func=parseInt(so_add,16)+fun_off;
   var ptr_fun=new NativePointer(add_func);
   
    Interceptor.attach(ptr_fun,{
        //在hook函数之前执行
        onEnter:function(args)
        {
            console.log("hook enter");
        },
        //在hook函数之后执行
        onLeave:function(retval)
        {
            console.log("hook leaver");
        }

    });     
}

案例 vnctf babyanti

image

posted @ 2023-04-06 22:59  Only-xiaoxiao  阅读(4562)  评论(0编辑  收藏  举报