Frida安装和使用(一)

劳昊明
2023-12-01

零、官方API

 JavaScript API

 

一、安装

(1).windows 安装frida

pip install frida
pip install frida-tool

安装完成后,直接在终端中输入frida-ps命令查看,如果能显示当前系统进程则证明安装成功

frida-ps
 PID  Name
----  ---------------------------------------------
 416  AirPlayUIAgent
 596  Android Studio
 551  AppleSpell.service
 529  CoreServicesUIAgent
 264  Dock
 266  Finder
 402  FolderActionsDispatcher
 553  Google Chrome
 505  LaterAgent
 517  QQ
 530  QQ jietu plugin

(2).android手机安装frida-server

 https://pypi.python.org/pypi/frida

  下载frida-server-12.8.11-android-arm64.xz

  • 下载后解压文件,并将文件重命名为: frida-server, 重命名完成后使用adb push命令推送到手机中
> adb push frida-server /data/local/tmp/

> adb shell
$ su
# cd /data/local/tmp/
# chmod 777 frida-server
# ./frida-server

 执行frida-ps -U查看手机端是否正常运行

frida-ps -U | find "frida"

使用frida-ps -R 也可以,但是需要进行转发。

> adb forward tcp:27042 tcp:27042
> frida-ps -R

二、基础使用

1.踪某个特定的函数 frida-trace -U -i [函数名] [程序包名]

跟踪手机中的app

frida-trace -U -i open com.peakx.stickfight.and

跟踪成功后,会在当前路径下创建以下JavaScript文件"C:\\Users\\admin.000\\Desktop\\test\\__handlers__\\libbase.so\\open.js",我们可以修改这个文件,增加一些自定义的功能。例如将open函数修改为:

onEnter: function (log, args, state) {
    log("open(" +
      "path=\"" + Memory.readUtf8String(args[0]) + "\"" +
      ", oflag=" + args[1] +
    ")");
  },

2.强制启动一个应用进程 frida -U --no-pause -f [应用包名]

frida -U --no-pause -f com.peakx.stickfight.and

当attach成功后,就可以开始Hook Java函数和对象了。
关于Friada框架中Java部分的API可以查看官方文档,下面总结几个常用的API。

//加载了 JVM也就是是否运行在Dalvik 或 ART环境中.
-> Java.available 

// 列出已加载的类
-> Java.perform(function(){ 
    Java.enumerateLoadedClasses(
    {
        "onMatch":function(className){ 
            console.log(className) 
        },
        "onComplete":function(){
            console.log("onComplete") 
        }
    }
    )
})

//Java.use(className) 根据className动态获取一个JavaScript wrapper,
//获取到后可以调用$new()方法来实例化一个对象,也可以调用$dispose()方法进行释放
-> Java.perform(function () {
    var Activity = Java.use("android.app.Activity");
    var Exception = Java.use("java.lang.Exception");
    Activity.onResume.implementation = function () {
        throw Exception.$new("Test!");
    };
});

 3.将上面的代码封装为Test.js,然后让frida执行这个文件

 frida -U/-R -l --no-pause -f <process_name/pid> 

-U, --usb             connect to USB device

-R, --remote          connect to remote frida-server

-l SCRIPT, --load=SCRIPT

                        load SCRIPT

--no-pause            automatically start main thread after startup

-p PID, --attach-pid=PID

> frida -U -l Test.js --no-pause -f com.peakx.stickfight.and

4.Frida有时候会有超时的提示,为防止这种情况,可以将脚本里面的代码包装在setImmediate函数中或导出为rpc

  • 例: 将Test.js中的代码修改一下,然后再次运行上面的命令重新部署一下即可。
setImmediate(function() {
    Java.perform(function () {
    var Activity = Java.use("android.app.Activity");
    var Exception = Java.use("java.lang.Exception");
    Activity.onResume.implementation = function () {
        throw Exception.$new("Test!");
    };
});
});

三、hook一个java方法

  1. 使用Java.use(className)命令获取 JavaScript wrapper
  2. 调用获取到的 JavaScript wrapper对象的方法[JavaScript wrapper对象].[要Hook的方法名].implementation=function(){...}

注1: 如果要Hook的方法有多个重载时,必须使用overload()方法调用,参数必须是完全匹配的,参数类型必须是全类名的也就是全引用名的。
注2: Hook方法中的参数,可以通过arguments数组访问,也可以在implementation函数中声明对应的形参

Android 代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.mBtnTest).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                helloAndroid();
                test1();
                test2(123);
                test3("str");
                test4("str", true);
            }
        });
    }
    
    private void helloAndroid() {
        System.out.println("helloAndroid()");
    }

    private void test() {
        System.out.println("test1()");
    }

    private void test(int i) {
        System.out.println("test2(int) " + i);
    }

    private void test(String s) {
        System.out.println("test3(String) " + s);
    }

    private void test(String s, boolean b) {
        System.out.println("test4(String, boolean) " + s + ", " + b);
    }
}

JavaScript Hook代码

Java.perform(function () {
    var MainActivity = Java.use("com.github.fridademo.MainActivity");
    MainActivity.helloAndroid.implementation = function () {
        console.log("helloAndroid()");
        this.private_func();
    };
    MainActivity.test.overload().implementation = function () {
        console.log("test1()");
        this.private_func();
    };
    MainActivity.test.overload("int").implementation = function (i) {
        console.log("test2(int): " + i);
        this.private_func(i);
    };
    MainActivity.test.overload("java.lang.String").implementation = function () {
        console.log("test3(String): " + arguments[0]);
        this.private_func(arguments[0]);
    };
    MainActivity.test.overload("java.lang.String", "boolean").implementation = function (s, b) {
        console.log("test4(String,boolean): " + s + ", " + b);
        this.private_func(s, b);
    };
});
> frida -U -l Test.js --no-pause -f com.peakx.stickfight.and

四、Hook一个Native函数

Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
    onEnter: function(args) {
        console.log(
              "open(" +
              "path=\"" + Memory.readUtf8String(args[0]) + "\"" +
              ", oflag=" + args[1] +
                ")"
        )
    },
    onLeave:function(retval){
    
    }
});
> frida -U -l Test.js --no-pause -f com.peakx.stickfight.and

> frida -R -l test.py -p 1001

五、利用python frida模块hook libc.so的open()函数

# hook chrome进程的libc.so中的函数open
import frida
import sys
import io

device = frida.get_usb_device()

pid = device.spawn(["com.android.chrome"])
session = device.attach(pid)
device.resume(pid)

scr = """
setImmediate(function() {
Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
    onEnter: function(args) {

        send("open called! args[0]:",Memory.readByteArray(args[0],256));
    },
    onLeave:function(retval){
    
    }
});

});
"""

def on_message(message ,data):
    file_object=open("d:\\log.txt",'ab+')
    file_object.write(message['payload'].encode())
    file_object.write(data.split(b'\x00')[0])
    file_object.write('\n'.encode())
    file_object.close()


script = session.create_script(scr)
script.on("message" , on_message)
script.load()
sys.stdin.read()

参考:

https://www.jianshu.com/p/7be526b77bd2

https://www.jianshu.com/p/d4a44f803f33

https://www.jianshu.com/p/b833fba1bffe

 类似资料: