[SWPU 2019]easyapp——手把手frida环境配置与初步使用以及so文件动态调试教程
字数 1728 2025-08-24 20:49:22

Frida环境配置与Android SO文件动态调试教程

前言

本教程将详细介绍如何配置Frida环境以及进行Android SO文件的动态调试,以解决[SWPU 2019]easyapp题目为例。教程包含Java层分析、native层分析、动态调试SO文件和使用Frida hook函数两种解法。

环境准备

硬件与软件要求

  1. 设备选择

    • 雷电模拟器(推荐使用安卓5及以下版本)
    • 或安卓5及以下的真机(高版本可能导致程序崩溃)
  2. 必要工具

    • JEB 4.20.0(或其他反编译工具)
    • IDA Pro 8.3
    • ADB工具
    • Anaconda(Python环境管理)
  3. 目标APK

    • 未加固的APK文件(com.example.ndktest2)

程序分析

Java层分析

使用JEB反编译APK后,查看MainActivity:

package com.example.ndktest2;

import android.os.Bundle;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private EditText password;
    
    static {
        System.loadLibrary("native-lib");
    }
    
    public native String Encrypt();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(0x7F09001C); // layout:activity_main
        EditText password = (EditText)this.findViewById(0x7F07005B); // id:password
        
        ((Button)this.findViewById(0x7F07004E)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (password.getText().toString().equals(MainActivity.this.Encrypt())) {
                    Toast.makeText(MainActivity.this, "登录成功", 1).show();
                    return;
                }
                Toast.makeText(MainActivity.this, "登录失败", 0).show();
            }
        });
    }
}

关键点:

  • 加载了native库"native-lib"
  • 调用了native方法Encrypt()
  • 用户输入与Encrypt()返回值比较决定登录成功与否

Native层分析

  1. 使用IDA打开libnative-lib.so文件
  2. 搜索Encrypt函数,发现可能被混淆
  3. 真正的加密函数实际上是"test"函数
  4. 通过JNI_OnLoad函数分析注册过程:
int __cdecl JNI_OnLoad(_JavaVM *a1) {
    void *v3; // [esp+24h] [ebp-18h] BYREF
    if (_JavaVM::GetEnv(a1, &v3, 65542))
        return -1;
    if (sub_A570(v3))
        return 65542;
    return -1;
}

_BOOL4 __cdecl sub_A570(_JNIEnv *a1) {
    return sub_A5F0(a1, "com/example/ndktest2/MainActivity", off_38008, 1) != 0;
}

_BOOL4 __cdecl sub_A5F0(_JNIEnv *a1, char *a2, int a3, int a4) {
    int Class; // [esp+24h] [ebp-18h]
    Class = _JNIEnv::FindClass(a1, a2);
    return Class && _JNIEnv::RegisterNatives(a1, Class, a3, a4) >= 0;
}

关键点:

  • 使用RegisterNatives注册了native方法
  • JNINativeMethod结构体包含方法名、签名和实际函数指针
  • 真正的加密函数是test而非Encrypt

解法一:动态调试SO文件

准备工作

  1. 启动模拟器并安装APK
  2. 检查设备连接:adb devices
  3. 查看设备架构:adb shell getprop ro.product.cpu.abi(应为x86)

搭建调试环境

  1. 将IDA的android_x86_server推送到设备:

    adb push android_x86_server /data/local/tmp/
    adb shell chmod 755 /data/local/tmp/android_x86_server
    adb shell /data/local/tmp/android_x86_server
    
  2. 端口转发:

    adb forward tcp:23946 tcp:23946
    

启动调试

  1. 检查调试权限(AndroidManifest.xml中android:debuggable="true")
  2. 以调试模式启动应用:
    adb shell am start -D -n com.example.ndktest2/.MainActivity
    
  3. 使用JEB附加进程进行调试

IDA动态调试

  1. 在IDA中打开libnative-lib.so
  2. 在加密函数(test)处下断点
  3. 选择Remote Linux debugger
  4. 设置调试选项:
    • Hostname: localhost
    • Port: 23946
  5. 附加到目标进程
  6. 在模拟器中输入任意内容并点击登录
  7. IDA将在断点处暂停,可查看寄存器中的flag值

关键点:

  • 断点应下在真正的加密函数test而非Encrypt
  • 查看寄存器v1可获取flag:"YouaretheB3ST"

解法二:使用Frida hook函数

Python环境配置

  1. 安装Anaconda管理Python环境
  2. 创建Python 3.7环境:
    conda create -n python37 python=3.7
    conda activate python37
    

安装Frida

  1. 安装Frida核心:
    pip install frida==12.8.0
    
  2. 安装Frida-tools:
    pip install frida-tools==5.4.0
    
  3. 安装objection:
    pip install objection==1.8.4
    

安装Frida-server

  1. 下载与Frida版本匹配的frida-server(12.8.0)
  2. 根据设备架构选择正确版本(x86)
  3. 推送并运行:
    adb push frida-server /data/local/tmp/
    adb shell chmod 755 /data/local/tmp/frida-server
    adb shell /data/local/tmp/frida-server
    

Hook函数

  1. 启动objection注入:
    objection -g com.example.ndktest2 explore
    
  2. Hook Encrypt方法:
    android hooking watch class_method com.example.ndktest2.MainActivity.Encrypt --dump-args --dump-backtrace --dump-return
    
  3. 在APP中输入任意内容并点击登录
  4. objection将显示hook到的返回值:"YouaretheB3ST"

关键点:

  • Frida和frida-server版本必须一致
  • 确保frida-server持续运行
  • 可直接获取加密函数的返回值

总结

通过本教程,我们学习了:

  1. APK的Java层和native层分析方法
  2. JNI函数注册机制和混淆识别技巧
  3. 两种获取加密flag的方法:
    • IDA动态调试SO文件
    • Frida hook技术

最终flag为:flag{YouaretheB3ST}

常见问题解决

  1. 程序崩溃:确保使用安卓5及以下版本
  2. 断点不生效:确认下在真正的加密函数(test)而非Encrypt
  3. Frida连接失败:检查版本匹配和frida-server是否运行
  4. IDA无法附加:确认端口转发和调试权限设置正确

扩展学习

  1. JNI函数注册机制
  2. Frida高级hook技巧
  3. IDA动态调试其他架构SO文件
  4. 对抗反调试技术
Frida环境配置与Android SO文件动态调试教程 前言 本教程将详细介绍如何配置Frida环境以及进行Android SO文件的动态调试,以解决[ SWPU 2019 ]easyapp题目为例。教程包含Java层分析、native层分析、动态调试SO文件和使用Frida hook函数两种解法。 环境准备 硬件与软件要求 设备选择 : 雷电模拟器(推荐使用安卓5及以下版本) 或安卓5及以下的真机(高版本可能导致程序崩溃) 必要工具 : JEB 4.20.0(或其他反编译工具) IDA Pro 8.3 ADB工具 Anaconda(Python环境管理) 目标APK : 未加固的APK文件(com.example.ndktest2) 程序分析 Java层分析 使用JEB反编译APK后,查看MainActivity: 关键点: 加载了native库"native-lib" 调用了native方法Encrypt() 用户输入与Encrypt()返回值比较决定登录成功与否 Native层分析 使用IDA打开libnative-lib.so文件 搜索Encrypt函数,发现可能被混淆 真正的加密函数实际上是"test"函数 通过JNI_ OnLoad函数分析注册过程: 关键点: 使用RegisterNatives注册了native方法 JNINativeMethod结构体包含方法名、签名和实际函数指针 真正的加密函数是test而非Encrypt 解法一:动态调试SO文件 准备工作 启动模拟器并安装APK 检查设备连接: adb devices 查看设备架构: adb shell getprop ro.product.cpu.abi (应为x86) 搭建调试环境 将IDA的android_ x86_ server推送到设备: 端口转发: 启动调试 检查调试权限(AndroidManifest.xml中android:debuggable="true") 以调试模式启动应用: 使用JEB附加进程进行调试 IDA动态调试 在IDA中打开libnative-lib.so 在加密函数(test)处下断点 选择Remote Linux debugger 设置调试选项: Hostname: localhost Port: 23946 附加到目标进程 在模拟器中输入任意内容并点击登录 IDA将在断点处暂停,可查看寄存器中的flag值 关键点: 断点应下在真正的加密函数test而非Encrypt 查看寄存器v1可获取flag:"YouaretheB3ST" 解法二:使用Frida hook函数 Python环境配置 安装Anaconda管理Python环境 创建Python 3.7环境: 安装Frida 安装Frida核心: 安装Frida-tools: 安装objection: 安装Frida-server 下载与Frida版本匹配的frida-server(12.8.0) 根据设备架构选择正确版本(x86) 推送并运行: Hook函数 启动objection注入: Hook Encrypt方法: 在APP中输入任意内容并点击登录 objection将显示hook到的返回值:"YouaretheB3ST" 关键点: Frida和frida-server版本必须一致 确保frida-server持续运行 可直接获取加密函数的返回值 总结 通过本教程,我们学习了: APK的Java层和native层分析方法 JNI函数注册机制和混淆识别技巧 两种获取加密flag的方法: IDA动态调试SO文件 Frida hook技术 最终flag为: flag{YouaretheB3ST} 常见问题解决 程序崩溃 :确保使用安卓5及以下版本 断点不生效 :确认下在真正的加密函数(test)而非Encrypt Frida连接失败 :检查版本匹配和frida-server是否运行 IDA无法附加 :确认端口转发和调试权限设置正确 扩展学习 JNI函数注册机制 Frida高级hook技巧 IDA动态调试其他架构SO文件 对抗反调试技术