云计算、AI、云原生、大数据等一站式技术学习平台

网站首页 > 教程文章 正文

frida环境搭建及hook入门

jxf315 2024-12-07 13:38:20 教程文章 42 ℃

frida是什么

frida环境搭建

frida为CS架构,需要安装客户端和服务端

  1. 安装客户端
    需要提前准备好python3环境,执行pip install frida-tools命令即可完成frida客户端的安装(可以通过-i参数指定国内镜像源,加快安装过程,如阿里镜像源地址为https://mirrors.aliyun.com/pypi/simple/),客户端安装完成后将支持frida、frida-ps、frida-trace、frida-discover、frida-ls-devices、frida-kill等一系列命令。
  2. 安装服务端
    server端需要安装在要hook的主机上,server端的安装版本必须与客户端版本一致,且server端的安装包文件必须和主机的CPU架构匹配。这里以mumu android模拟器12为例,首先使用adb shell getprop ro.product.cpu.abi查看CPU架构,如下结果为x86_64,则下载frida-server-16.1.3-android-x86_64.xz,解压后上传到/data/local/tmp目录下,并赋权777。
PS C:\Users\xxx> adb shell getprop ro.product.cpu.abi
x86_64

执行adb shell "/data/local/tmp/frida-server-16.1.3-android-x86_64 &"启动服务端
server端下载链接:https://github.com/frida/frida/releases

  1. 检查安装是否成功
    在客户端执行frida-ps -U,如果能返回手机端运行的进程则说明frida环境搭建成功
PS C:\Users\xxx> frida-ps -U
 PID  Name
----  ------------------------------------------------
1450  adbd
1568  android.ext.services
...
2437  应用中心
2666  抖音
2008  设置
  1. 端口转发
    后续执行frida注入可能会提示找不到设备,这时尝试添加端口转发,27042是默认客户端和服务端通信端口,不确定27043是不是必须的,网上搜索的结果都是两个端口都加入了转发。
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

hook入门

frida环境搭建只是第一步,怎么使用frida才是真正的挑战,因为掌握它需要软件开发技能、软件逆向技能、操作系统等各种能力,能力越强越能发挥出它的威力,这里仅给出简单的入门示例,因为我也是新手。

  1. 开发一个简单的android app
    因为我不熟悉android开发,为了让自己对android app结构有个初步的认识,我参考网上的教程开发了一个简单的app,这个app就是求两个数的和。如果你已经很熟悉android app开发请直接忽略这一步。

布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="a:">
        </TextView>
        <EditText
            android:id="@+id/a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck"
            android:ems="10">
        </EditText>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="b:">
        </TextView>
        <EditText
            android:id="@+id/b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck"
            android:ems="10">
        </EditText>
    </LinearLayout>

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sum">
    </Button>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="a+b = ">
        </TextView>
        <TextView
            android:id="@+id/c"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:textColor="#0aaaaa"
            android:text=""
            android:ems="10">
        </TextView>
    </LinearLayout>

</LinearLayout>

MainActivity.java,调用了com.example.hookdemo.HookDemo的Add方法

package com.example.appdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.hookdemo.HookDemo;

public class MainActivity extends AppCompatActivity {
    private TextView tvc;
    private EditText edta, edtb;
    private Button btn;
    private int numC;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button)this.findViewById(R.id.btn);
        edta = (EditText)this.findViewById(R.id.a);
        edtb = (EditText)this.findViewById(R.id.b);
        tvc = (TextView)this.findViewById(R.id.c);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String inputA = edta.getText().toString();
                String inputB = edtb.getText().toString();
                int numA = Integer.valueOf(inputA).intValue();
                int numB = Integer.valueOf(inputB).intValue();
                numC = HookDemo.Add(numA, numB);
                tvc.setText(String.valueOf(numC));
            }
        });
    }
}

HookDemo.java

package com.example.hookdemo;

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

接下来我们就hook这个求和的Add方法,注入我们自己的代码实现直接修改求和的入参。

  1. 运行python代码进行注入
    frida的脚本是通过python来编写的,但是真正的注入代码是使用JavaScript来写,下面的示例python代码将注入js代码写在jscode变量中,这里需要特别注意的是frida官网给出的示例frida.get_usb_device().attach方式传入的是包名,但是实际测试发现报错frida.ProcessNotFoundError: unable to find process with name 'com.example.appdemo',提示找不到这个进程。解决的办法是通过adb shell ps命令找到对应的pid,直接传入pid可以正常运行。
import frida, sys

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

jscode = """
// 确保当前线程附件到虚拟机并调用其中的方法
Java.perform(() => {
    // hook的包名
    var hookdemo = Java.use('com.example.hookdemo.HookDemo');
    // 注入hook方法的代码
    hookdemo.Add.implementation = function (a, b) {
        // 直接修改入参a、b为固定值
        a = 12;
        b = 13;
        var res = this.Add(a, b);
        console.log(a, b, res);
        // 向frida客户端发送消息
        send(JSON.stringify({
            "a": a,
            "b": b,
            "c":res
        }));
        return res;
    }
});
"""
# 通过adb shell ps找到注入app对应的pid
# process = frida.get_usb_device().attach("com.example.appdemo")
process = frida.get_usb_device().attach(2620)
script = process.create_script(jscode)
# 当收到message时调用on_message
script.on("message", on_message)
script.load()
sys.stdin.read()

运行python脚本,然后在mumu模拟器输入两个数并点击求和按钮就会触发调用Add方法,这时控制台会打印message消息以及console.log的打印信息,而app显示的求和结果也被改变了,说明我们的代码成功注入app并实现了改变原有方法的行为。

  1. 命令行形式进行注入
    除了运行python脚本的方式进行注入之外,也可以在客户端输入命令方式进行代码注入,直接将js代码单独保存为hook.js文件
// 确保当前线程附件到虚拟机并调用其中的方法
Java.perform(() => {
    // hook的包名
    var hookdemo = Java.use('com.example.hookdemo.HookDemo');
    // 注入hook方法的代码
    hookdemo.Add.implementation = function (a, b) {
        // 直接修改入参a、b为固定值
        a = 12;
        b = 13;
        var res = this.Add(a, b);
        console.log(a, b, res);
        // 向frida客户端发送消息
        send(JSON.stringify({
            "a": a,
            "b": b,
            "c":res
        }));
        return res;
    }
});

frida-ps -U列出运行的进程id和进程名,找到需要注入的app名称,示例为appDemo

PS C:\Users\xxx> frida-ps -U
 PID  Name
----  ------------------------------------------------
2228  abb
1302  adbd
...
2620  appDemo
1041  audioserver
1064  cameraserver

执行frida -U 进程名 -l xx.js即可进行注入测试,注入成功会显示如下打印信息

C:\Users\xxx>frida -U hello_world -l hook1.js
     ____
    / _  |   Frida 16.1.3 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to PGAM10 (id=127.0.0.1:16384)
Attaching...
start
<class: com.example.hookdemo.Student>
[PGAM10::hello_world ]->

然后在mumu模拟器输入两个数并点击求和按钮触发调用Add方法,求和结果始终为25,因为注入的代码将a、b改为了固定的值。控制台也会打印相应的信息,说明我们注入的代码已经工作了。

最近发表
标签列表