白帽子之逆向Crackme2.apk - 反调试(一)

Crackme反调试思路

  1. native注册函数
  2. 双进程启动
  3. native重启,java层无法hook

启动后会出现两个进程

别hook错了

复制代码
PS C:\Users\HiMaq> adb shell "ps -A | grep igio90"
u0_a78       10757   678 2232368  43924 SyS_epoll_wait 7a996441d4 S com.igio90.crackme2:main
u0_a78       10780   678 2228224  41632 futex_wait_queue_me 7a995f8630 S com.igio90.crackme2:launcher

此处launcher 直接来个nativeInit 事情不简单

IDA 查看导出函数

修复下变量名

基本可以得知是一个反射函数

盲猜是MainActivity的 init 函数 刚好也是一个静态函数

这个init其实就是重启它自己,这样做的好处是什么呢?

  1. java层hook会导致native崩溃

    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'java_vm_ext.cc:504] JNI DETECTED ERROR IN APPLICATION: java_class == null'

  2. 重启自己自然就会让IDA 无法动态调试,一箭双雕!
    我们试试 拦截它

    PS C:\Users\HiMaq> adb shell am force-stop com.igio90.crackme2

    PS C:\Users\HiMaq> adb shell am start -D -n com.igio90.crackme2/.Launcher
    Starting: Intent { cmp=com.igio90.crackme2/.Launcher }
    PS C:\Users\HiMaq> adb jdwp
    4144
    4720
    4177
    2155
    4766
    919
    5224
    4119
    5250
    2543
    4260
    4625
    4471
    2145
    4418
    5945
    10757
    10780
    PS C:\Users\HiMaq> adb shell "ps -A | grep igio90"
    u0_a78 10757 678 2232368 43924 SyS_epoll_wait 7a996441d4 S com.igio90.crackme2:main
    u0_a78 10780 678 2228224 41632 futex_wait_queue_me 7a995f8630 S com.igio90.crackme2:launcher
    PS C:\Users\HiMaq> adb forward tcp:31280 jdwp:10780
    PS C:\Users\HiMaq> jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=31280
    设置未捕获的java.lang.Throwable
    设置延迟的未捕获的java.lang.Throwable
    正在初始化jdb...

    resume
    已恢复所有线程。

这里jdb 启动app后 ,立即使用frida hook,最后再connect 31280 和resume 顺序不要错

复制代码
PS C:\Users\HiMaq> adb root
restarting adbd as root
PS C:\Users\HiMaq> adb shell setenforce 0
PS C:\Users\HiMaq> adb shell
angler:/ # su
angler:/ # ./data/lo
local/       lost+found/
angler:/ # ./data/local/tmp/frida-server-17.9.8-android-arm64 &

firda 端口转发

复制代码
PS C:\Users\HiMaq> adb forward tcp:27042 tcp:27042
27042

hook_jni.js

复制代码
 Java.perform(function () {
        console.log("[*] 正在挂钩目标类: com.igio90.crackme2.MainActivity");

        // Hook MainActivity 中的 init 方法
        var MainActivity = Java.use("com.igio90.crackme2.MainActivity");

        MainActivity.init.implementation = function () {
            console.log("[+] 成功拦截到 init() 方法!");
            console.log("[+] 正在屏蔽自毁逻辑 (System.exit(0))...");

            try {
                // 这里我们只执行跳转逻辑,但不执行 postDelayed 里的退出
                var application = this.getApplicationUsingReflection();
                var Intent = Java.use("android.content.Intent");

                var intent = Intent.$new(application, Java.use("com.igio90.crackme2.MainActivity").class);
                intent.addFlags(268435456);
                application.startActivity(intent);

                console.log("[+] 页面已成功启动,已跳过自毁计时器。");
            } catch (e) {
                console.log("[-] 错误: " + e);
            }
        };
    });

(frida_env) PS D:\FridaWorkSpace> uv run frida -U -p 10780 -l hook_jni.js
     ____
    / _  |   Frida 17.9.8 - 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 AOSP on angler (id=8XV7N16125004864)
                                                                                
[AOSP on angler::PID::10780 ]-> [*] 正在挂钩目标类: com.igio90.crackme2.MainActivity
[+] 成功拦截到 init() 方法!
[+] 正在屏蔽自毁逻辑 (System.exit(0))...
[+] 页面已成功启动,已跳过自毁计时器。

当我们点击按钮就不会重启自己了!!!

接下来我们干啥呢?

当然还是IDA动态调试了

bash 复制代码
5|angler:/ # ./data/local/tmp/as64
IDA Android 64-bit remote debug server(ST) v9.2.31. Hex-Rays (c) 2004-2025
2026-06-05 11:51:43 Listening on :::23946...
2026-06-05 11:52:13 [1] Accepting connection from ::ffff:127.0.0.1...
PS C:\Users\HiMaq> adb forward tcp:23946 tcp:23946
23946

我们开始附加pid,注意是下面这个10780

再使用frida hook MainActivity

bash 复制代码
adb shell am start  com.igio90.crackme2/.MainActivity
adb shell am start -D -n com.igio90.crackme2/.MainActivity

拦截main进程 unlock 函数

private native void unlock(int arg1) { }

bash 复制代码
function doHook() {
    Java.perform(function () {
        var MainActivity = Java.use("com.igio90.crackme2.MainActivity");

        MainActivity.unlock.implementation = function (pin) {
            console.log("[+] 捕获到 unlock 调用,PIN: " + pin);

            // 【关键点】:完全注释掉 return this.unlock(pin);
            // 如果程序不依赖 unlock 的返回值(即该方法只是为了校验),
            // 那么不调用原逻辑可能直接绕过崩溃!

            console.log("[+] 已拦截执行流,尝试跳过 Native 校验...");
        };
    });
}

setImmediate(doHook);

执行

bash 复制代码
(frida_env) PS D:\FridaWorkSpace> uv run frida -U -p 8429 -l hook_jni2.js
     ____
    / _  |   Frida 17.9.8 - 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 AOSP on angler (id=8XV7N16125004864)
                                                                                
[AOSP on angler::PID::8429 ]-> [+] 捕获到 unlock 调用,PIN: 1234
[+] 已拦截执行流,尝试跳过 Native 校验...
[+] 捕获到 unlock 调用,PIN: 1234
[+] 已拦截执行流,尝试跳过 Native 校验...
[+] 捕获到 unlock 调用,PIN: 1234
[+] 已拦截执行流,尝试跳过 Native 校验...
[+] 捕获到 unlock 调用,PIN: 1234
[+] 已拦截执行流,尝试跳过 Native 校验...
[+] 捕获到 unlock 调用,PIN: 1234
[+] 已拦截执行流,尝试跳过 Native 校验...

好的 我们注释掉hook代码 接下来使用 ida 来动态调试一波

attach 就直接崩了~

回到静态分析 hook_jni2.js

以下是CC给我出的答案

bash 复制代码
Java.perform(function () {
    var moduleName = "libigio.so";
    var mod = Process.findModuleByName(moduleName);
    if (!mod) {
        console.log("[-] 模块未找到,等待中...");
        setTimeout(doHook, 1000);
        return;
    }

    console.log("[+] 基址: " + mod.base);

    // 在校验比较处打印v81的实际内容
    Interceptor.attach(mod.base.add(0xC30), {
        onEnter: function (args) {
            this.pass = args[2].toInt32();
        }
    });

    // 暴力枚举
    for (var i = 1000; i <= 9999; i++) {
        var s = i.toString();
        var v49 = 0x43 ^ s.charCodeAt(0);
        var v46 = s.charCodeAt(1);
        var v47 = s.charCodeAt(2);
        var v48 = s.charCodeAt(3);

        if (v49 == 0x71
            && (v46 ^ v49) == 0x45
            && (v47 ^ v46 ^ v49) == 0x74
            && (v48 ^ v47 ^ v46 ^ v49) == 0x44) {
            console.log("[!!!] 找到答案: " + i);
        }
    }
});
bash 复制代码
(frida_env) PS D:\FridaWorkSpace> uv run frida -U -p 4866 -l hook_jni2.js
     ____
    / _  |   Frida 17.9.8 - 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 AOSP on angler (id=8XV7N16125004864)
Attaching...                                                            
[*] PID: 4866
[+] 基址: 0x793b8e1000
[!!!] 找到答案: 2410

输入密码 如愿以尝~ 成功夺旗!

我们来回顾下 这段静态分析的代码

白帽子之逆向Crackme2.apk - 反调试(二)

相关推荐
himobrinehacken1 天前
C/C++中字符编码与指针应用全解析
c语言·逆向
shandianchengzi2 天前
【记录】Ghidra|Ubuntu 26.04 下 Ghidra 界面缩放完整指南
linux·ubuntu·逆向·ghidra
酿情师3 天前
逆向exe文件:CRT 初始化流程详细分析
android·软件构建·逆向·re·crt‘
遇事不決洛必達8 天前
【爬虫随笔】常见加密算法特征总结
javascript·爬虫·逆向·加密算法
阿昭L9 天前
Windows用户态hook技术总结
windows·逆向·hook
遇事不決洛必達10 天前
【爬虫随笔】常见js混淆原理和特征
javascript·爬虫·逆向·js加密
浩浩测试一下14 天前
汇编 16位32位64位通用寄存器(逆向分析)
汇编·windows·stm32·单片机·嵌入式硬件·逆向·二进制
Lang-121014 天前
Frida + Android Hook 完整指南
android·逆向·hook·frida
浩浩测试一下15 天前
汇编 标志位寄存器 (逆向分析 )
c语言·汇编·逆向·windows编程·标志寄存器