Crackme反调试思路
- native注册函数
- 双进程启动
- 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其实就是重启它自己,这样做的好处是什么呢?
-
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' -
重启自己自然就会让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
输入密码 如愿以尝~ 成功夺旗!

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