1.教程 Demo 2.IDEA 3.IDA
系统调用(Syscall)补环境是 Unidbg 模拟执行中一个基础且高级的环节。当原生库(. So 文件)为了性能、对抗或功能需要,绕过标准库(libc)函数,通过 SVC 等底层指令直接向操作系统内核发起请求时,Unidbg 必须能够拦截并模拟这些内核级别的行为。由于 Unidbg 并非一个完整的操作系统,其对内核的模拟是不完备的。如果 so 文件请求了一个 Unidbg 未实现或模拟不完善的系统调用(通过系统调用号 NR 区分),通常会导致模拟流程出错、返回无效数据(如 fstat 对目录返回全零),或进入非预期的逻辑分支,最终使模拟失败或结果失真。因此,系统调用补环境的目的就是识别并接管这些对内核的底层请求,通过自定义 SyscallHandler 提供一个符合目标 so 逻辑预期的模拟行为或返回值,从而“欺骗”so 文件,使其相信自己正与一个真实的 Linux/Android 内核交互。
当 unidbg 遇到一个它无法处理的软中断(SVC)时,通常会打印出如下格式的 WARN 日志:
这个日志包含了定位问题的关键信息:
并且,JNI 调用失败通常会紧跟着抛出 UnsupportedOperationException,并带有清晰的 JNI 方法签名。
解决系统调用问题的通用范式是创建一个继承自 unidbg 原生 SyscallHandler 的子类,并重写或补充其中的方法。 首先,你需要定义一个自己的 SyscallHandler。以 ARM 64 为例:
然后,在构建 Emulator 时,通过 AndroidEmulatorBuilder 将其替换掉默认的处理器。
这是最常见的情况,unidbg 对某个 NR 完全没有实现,直接在 handleInterrupt 处抛出警告。案例 1:getcpu (NR=168)
在我们的 MySyscallHandler 中,重写 handleUnknownSyscall 方法,捕获未被处理的 NR。
案例 2:statx (NR=291) statx 是 Linux 中一个现代化的、用于获取文件元数据(metadata)的系统调用 。它是 stat, fstat, lstat 的继任者和升级版。
文件的元数据,就是描述文件属性的信息,例如:
statx 相对于旧版 stat 的主要优势: 1.更丰富的信息 :statx 可以获取旧版 stat 无法提供的信息,最典型的就是文件的创建时间(birth time, btime) 。 2.更高精度的时间戳 :旧版 stat 的时间戳只精确到秒。而 statx 可以提供**纳秒(nanosecond)级别的精度,这对于现代文件系统和应用至关重要。 3.更高的效率和灵活性 (Mask 机制) :调用旧版 stat 时,内核会把所有元数据一次性全返回给你,即使你只关心文件大小。statx 引入了一个 mask(掩码)参数,允许调用者明确告诉内核:“我只对文件大小和修改时间感兴趣”。内核就会只获取并返回这些信息,避免了不必要的工作,提高了效率 4.更好的扩展性 :它的结构体设计考虑了未来,留有备用字段,方便以后添加新的文件属性而不需要再次设计新的系统调用。如何填充statx结构:
接下来就是把上面的结构发给 AI 来伪造
Unidbg 实现了该系统调用,但存在缺陷。
案例 1:clock_gettime (NR=113, ARM 64) clock_gettime(clockid_t clk_id, struct timespec *tp) 用于获取特定时钟的时间。Unidbg 实现了对 CLOCK_REALTIME (clk_id=0) 的处理,但没有实现 CLOCK_PROCESS_CPUTIME_ID (clk_id=2),导致传入 2 时抛出异常。解决方案 :重写 clock_gettime 方法。
案例 2: sched_getaffinity (NR=123)
有时候,我们会发现某个系统调用的实现在 Unidbg 的父类 ARM64SyscallHandler 中,但该实现方法被声明为 final,导致我们无法像 clock_gettime 那样直接 @Override 它。此外,有些系统调用是在一个巨大的 switch 语句(如 handleSyscall 方法)中处理的,我们只想修改其中一个 case 的行为,同样无法直接重写。
在这种情况下,我们需要在更早的阶段介入。系统调用的最顶层入口是 hook() 方法,它负责接收所有 SVC 中断,解析出系统调用号(NR),然后再分发给具体的处理方法。通过重写 hook(),我们可以在 Unidbg 分发之前“截胡”我们关心的系统调用,实现自定义逻辑。
sched_getaffinity 用于检测当前进程可以运行在哪些 CPU 核心上,这常被用于环境检测或设备指纹生成。解决方案: 在 hook() 方法中,抢先处理目标 NR,然后“屏蔽”它,避免父类重复执行。
案例 3:fstat (NR=80)
fstat 和 statx 的核心目标都是获取文件元数据,但它们在设计、功能和使用方式上存在显著差异。简单来说,statx 是 fstat 的现代、功能更全面的“超级升级版” 。
对照着实现,并伪造一些模拟数据
有些库函数(如 popen)的实现依赖一整套复杂的系统调用(vfork, pipe2, dup2 / dup3, execve, wait4 等),这些都和进程创建、IPC(进程间通信)相关,是 unidbg 的弱项。尝试逐个修复这些系统调用会陷入泥潭。 因此,我们采用一种更高级、更高效的“组合拳”策略:在高层 Hook 函数意图,在底层伪造结果 。
案例:修复 popen popen 函数会执行一个 shell 命令,并创建一个管道,返回一个文件流指针,后续代码可以通过 fread 等函数从这个文件流中读取命令的输出结果。
**第一步:使用 xHook 拦截 popen 调用意图
使用 unidbg 的 Hook 功能(如 xhook),通过 xHook 拦截对 popen 的调用,主要目的不是替换它,而是获取它将要执行的命令字符串 ,并将其存入 Unidbg 的上下文中,供后续的底层 SyscallHandler 使用。
第二步:在 SyscallHandler 中伪造关键系统调用的结果 当原始的 popen 函数执行时,它会触发一系列系统调用。我们不需要全部实现它们,只需要伪造其中最关键的几个,形成一个逻辑闭环即可。1. 伪造 pipe2 (NR=59) - 创建通信管道 popen 首先会调用 pipe2 来创建一个管道,这个管道包含一个“读”端和一个“写”端。这是我们注入伪造结果的最佳时机。
2. 伪造 fork - 创建子进程
popen 接着会调用 fork 来创建子进程。在 Unidbg 中,我们无需真的创建一个进程。fork 系统调用的特点是:在父进程中返回子进程的 PID(一个正整数),在子进程中返回 0。由于 popen 的后续流程在父进程中,我们只需要让它以为子进程创建成功了 即可。
通过以上组合拳,popen 的执行流程被我们完美地“欺骗”了: 1.它调用 pipe2,得到了两个文件描述符。 2.它调用 fork,得到了一个看似成功的子进程 PID。 3.接下来,父进程会关闭管道的写端,然后从读端 read_fd 读取数据。 4.当它读取 read_fd 时,实际上读取的是我们预设在 ByteArrayFileIO 中的 stdout 字符串。 最终,so 获取到了我们想让它获取的任何结果,而我们完全没有涉及复杂的多进程模拟。
案例 2:补 gettid gettid 函数详解 在 Linux 内核中,每个线程都有一个唯一的标识符,即线程 ID(TID)。gettid 函数是应用程序获取这个底层 ID 最直接的方式。1. 它是做什么的? gettid 是一个 Linux 特有的 C 函数,原型如下:
2. 为什么它在补环境中如此重要? gettid 是风控和反调试检测的“常客”,因为它能揭示程序运行的线程环境,而 Unidbg 的线程模型与真实设备有本质区别。检测点通常包括:
如果不修补 gettid,Unidbg 环境下的返回值很可能无法通过上述校验,导致 so 认为自己运行在异常线程或模拟器中,从而改变执行路径或直接退出。
3. 修补方法 对于 gettid,最直接有效的修补方式就是使用 Dobby 进行 Inline Hook,强制它返回一个我们期望的值。通常,我们会让它返回当前的进程 ID(PID),以完美模拟“主线程”的行为。
小结: 深入探讨了 Unidbg 中三种高级 Hook 技术以应对复杂的模拟挑战。首先,介绍了针对不同场景(如 final 方法)的系统调用 Hook 策略,通过重写顶层 hook() 方法实现精准拦截。演示了通过高层函数 Hook(xHook popen)与底层 Syscall 伪造(pipe2, fork)相结合的“组合拳”策略,高效模拟复杂调用链。最后,展示了如何应用 Dobby 直接修补 C 库函数(gettid)以绕过环境一致性检测。
放点gemini-2.5-pro的key给表哥们玩玩
完整代码:ChallengeTenThree:
MySyscallHandler:
百度云 阿里云 哔哩哔哩 教程开源地址 PS: 解压密码都是 52 pj,阿里云由于不能分享压缩包,所以下载 exe 文件,双击自解压
白龙unidbg教程
[00:46:49 186] WARN [com.github.unidbg.linux.ARM64SyscallHandler] (ARM64SyscallHandler:399) - handleInterrupt intno=2, NR=165, svcNumber=0x0, PC=RX@0x401ba3d4[libc.so]0x6a3d4, LR=RX@0x40000770[libdemo.so]0x770, syscall=null
[00:46:49 186] WARN [com.github.unidbg.linux.ARM64SyscallHandler] (ARM64SyscallHandler:399) - handleInterrupt intno=2, NR=165, svcNumber=0x0, PC=RX@0x401ba3d4[libc.so]0x6a3d4, LR=RX@0x40000770[libdemo.so]0x770, syscall=null
[01:00:43 681] WARN [com.github.unidbg.linux.ARM64SyscallHandler] ... svcNumber=0x16f ...
java.lang.UnsupportedOperationException: com/aliyun/TigerTally/A->ct()Landroid/content/Context;
[01:00:43 681] WARN [com.github.unidbg.linux.ARM64SyscallHandler] ... svcNumber=0x16f ...
java.lang.UnsupportedOperationException: com/aliyun/TigerTally/A->ct()Landroid/content/Context;
import com.github.unidbg.Emulator;
import com.github.unidbg.linux.ARM64SyscallHandler;
import com.github.unidbg.memory.SvcMemory;
public class MySyscallHandler extends ARM64SyscallHandler {
public MySyscallHandler(SvcMemory svcMemory) {
super(svcMemory);
setVerbose(true);
}
}
import com.github.unidbg.Emulator;
import com.github.unidbg.linux.ARM64SyscallHandler;
import com.github.unidbg.memory.SvcMemory;
public class MySyscallHandler extends ARM64SyscallHandler {
public MySyscallHandler(SvcMemory svcMemory) {
super(svcMemory);
setVerbose(true);
}
}
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.android.AndroidARM64Emulator;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.unix.UnixSyscallHandler;
AndroidEmulatorBuilder builder = new AndroidEmulatorBuilder(true) {
[url=home.php?mod=space&uid=1892347]@Override[/url]
public AndroidEmulator build() {
return new AndroidARM64Emulator(processName, rootDir, backendFactories) {
@Override
protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {
return new MySyscallHandler(svcMemory);
}
};
}
};
builder.setProcessName("com.zj.wuaipojie");
emulator = builder.build();
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.android.AndroidARM64Emulator;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.unix.UnixSyscallHandler;
AndroidEmulatorBuilder builder = new AndroidEmulatorBuilder(true) {
[url=home.php?mod=space&uid=1892347]@Override[/url]
public AndroidEmulator build() {
return new AndroidARM64Emulator(processName, rootDir, backendFactories) {
@Override
protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {
return new MySyscallHandler(svcMemory);
}
};
}
};
builder.setProcessName("com.zj.wuaipojie");
emulator = builder.build();
import com.github.unidbg.Emulator;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.pointer.UnidbgPointer;
import com.sun.jna.Pointer;
import unicorn.Arm64Const;
@Override
protected boolean handleUnknownSyscall(Emulator<?> emulator, int NR) {
System.err.println(">>> MySyscallHandler is processing syscall NR = " + NR);
Backend backend = emulator.getBackend();
switch (NR) {
/** getcpu (NR=168): x0=cpu*, x1=node* */
case 168: {
Pointer cpuPtr = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X0);
Pointer nodePtr = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
int currentCpu = rng.nextInt(8);
if (cpuPtr != null) {
cpuPtr.setInt(0, currentCpu);
}
if (nodePtr != null) {
}
return true;
}
}
return super.handleUnknownSyscall(emulator, NR);
}
import com.github.unidbg.Emulator;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.pointer.UnidbgPointer;
import com.sun.jna.Pointer;
import unicorn.Arm64Const;
@Override
protected boolean handleUnknownSyscall(Emulator<?> emulator, int NR) {
System.err.println(">>> MySyscallHandler is processing syscall NR = " + NR);
Backend backend = emulator.getBackend();
switch (NR) {
/** getcpu (NR=168): x0=cpu*, x1=node* */
case 168: {
Pointer cpuPtr = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X0);
Pointer nodePtr = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
int currentCpu = rng.nextInt(8);
if (cpuPtr != null) {
cpuPtr.setInt(0, currentCpu);
}
if (nodePtr != null) {
}
return true;
}
}
return super.handleUnknownSyscall(emulator, NR);
}
struct statx {
__u32 stx_mask;
__u32 stx_blksize;
__u64 stx_attributes;
__u32 stx_nlink;
__u32 stx_uid;
__u32 stx_gid;
__u16 stx_mode;
__u16 __spare0[1];
__u64 stx_ino;
__u64 stx_size;
__u64 stx_blocks;
__u64 stx_attributes_mask;
struct statx_timestamp stx_atime;
struct statx_timestamp stx_btime;
struct statx_timestamp stx_ctime;
struct statx_timestamp stx_mtime;
};
struct statx_timestamp {
__s64 tv_sec;
__u32 tv_nsec;
__s32 __spare;
};
struct statx {
__u32 stx_mask;
__u32 stx_blksize;
__u64 stx_attributes;
__u32 stx_nlink;
__u32 stx_uid;
__u32 stx_gid;
__u16 stx_mode;
__u16 __spare0[1];
__u64 stx_ino;
__u64 stx_size;
__u64 stx_blocks;
__u64 stx_attributes_mask;
struct statx_timestamp stx_atime;
struct statx_timestamp stx_btime;
struct statx_timestamp stx_ctime;
struct statx_timestamp stx_mtime;
};
struct statx_timestamp {
__s64 tv_sec;
__u32 tv_nsec;
__s32 __spare;
};
/** statx (NR=291): x1=path, x4=statx* */
case 291: {
Pointer pathPtr = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
Pointer stx = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X4);
String path = pathPtr != null ? pathPtr.getString(0) : null;
if (stx != null) {
ByteBuffer bb = ByteBuffer.allocate(0x100).order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(0x000007ff);
bb.putInt(4096);
bb.putLong(0);
bb.putInt(1);
bb.putInt(1000);
bb.putInt(1000);
int S_IFDIR = 0x4000, S_IFREG = 0x8000;
int mode = (path != null && path.endsWith("/")) ? (S_IFDIR | 0755) : (S_IFREG | 0644);
bb.putShort((short) mode);
while (bb.position() < 0x20) bb.put((byte) 0);
bb.putLong(123456789L);
bb.putLong(4096L);
bb.putLong(8L);
while (bb.position() < 0x58) bb.put((byte) 0);
long now = 1710000000L;
putStatxTs(bb, now);
putStatxTs(bb, now);
putStatxTs(bb, now);
putStatxTs(bb, now);
stx.write(0, bb.array(), 0, bb.limit());
}
writeX(backend, Arm64Const.UC_ARM64_REG_X0, 0);
return true;
}
/** statx (NR=291): x1=path, x4=statx* */
case 291: {
Pointer pathPtr = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
Pointer stx = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X4);
String path = pathPtr != null ? pathPtr.getString(0) : null;
if (stx != null) {
ByteBuffer bb = ByteBuffer.allocate(0x100).order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(0x000007ff);
bb.putInt(4096);
bb.putLong(0);
bb.putInt(1);
bb.putInt(1000);
bb.putInt(1000);
int S_IFDIR = 0x4000, S_IFREG = 0x8000;
int mode = (path != null && path.endsWith("/")) ? (S_IFDIR | 0755) : (S_IFREG | 0644);
bb.putShort((short) mode);
while (bb.position() < 0x20) bb.put((byte) 0);
bb.putLong(123456789L);
bb.putLong(4096L);
bb.putLong(8L);
while (bb.position() < 0x58) bb.put((byte) 0);
long now = 1710000000L;
putStatxTs(bb, now);
putStatxTs(bb, now);
putStatxTs(bb, now);
putStatxTs(bb, now);
stx.write(0, bb.array(), 0, bb.limit());
}
writeX(backend, Arm64Const.UC_ARM64_REG_X0, 0);
return true;
}
@Override
protected int clock_gettime(Emulator<?> emulator) {
Backend backend = emulator.getBackend();
long clkId = readX(backend, Arm64Const.UC_ARM64_REG_X0);
Pointer tp = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
if (tp == null) {
return -14;
}
long nowMs = System.currentTimeMillis();
long nowNs = System.nanoTime();
long sec, nsec;
switch ((int) clkId) {
case 0:
case 8:
sec = nowMs / 1000L;
nsec = (nowMs % 1000L) * 1_000_000L;
break;
case 1:
case 4:
case 7:
case 9:
sec = nowNs / 1_000_000_000L;
nsec = nowNs % 1_000_000_000L;
break;
case 2:
case 3:
sec = 0L;
nsec = (nowNs % 50_000_000L) + 10_000L;
default:
sec = nowMs / 1000L;
nsec = (nowMs % 1000L) * 1_000_000L;
break;
}
tp.setLong(0, sec);
tp.setLong(8, nsec);
return 0;
}
@Override
protected int clock_gettime(Emulator<?> emulator) {
Backend backend = emulator.getBackend();
long clkId = readX(backend, Arm64Const.UC_ARM64_REG_X0);
Pointer tp = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
if (tp == null) {
return -14;
}
long nowMs = System.currentTimeMillis();
long nowNs = System.nanoTime();
long sec, nsec;
switch ((int) clkId) {
case 0:
case 8:
sec = nowMs / 1000L;
nsec = (nowMs % 1000L) * 1_000_000L;
break;
case 1:
case 4:
case 7:
case 9:
sec = nowNs / 1_000_000_000L;
nsec = nowNs % 1_000_000_000L;
break;
case 2:
case 3:
sec = 0L;
nsec = (nowNs % 50_000_000L) + 10_000L;
default:
sec = nowMs / 1000L;
nsec = (nowMs % 1000L) * 1_000_000L;
break;
}
tp.setLong(0, sec);
tp.setLong(8, nsec);
return 0;
}
@Override
public void hook(Backend backend, int intno, int swi, Object user) {
int nr = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X8)).intValue();
if (nr == 123) {
long cpusetsize = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X1)).longValue();
long maskAddr = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X2)).longValue();
if (maskAddr != 0 && cpusetsize > 0) {
final int cores = 8;
final int size = (int) cpusetsize;
byte[] buf = new byte[size];
int maxBits = size * 8;
int bitsToSet = Math.min(cores, maxBits);
for (int cpu = 0; cpu < bitsToSet; cpu++) {
int bi = cpu / 8;
int bit = cpu % 8;
buf[bi] |= (1 << bit);
}
backend.mem_write(maskAddr, buf);
}
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, cpusetsize);
backend.reg_write(Arm64Const.UC_ARM64_REG_X8, -1);
}
super.hook(backend, intno, swi, user);
}
@Override
public void hook(Backend backend, int intno, int swi, Object user) {
int nr = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X8)).intValue();
if (nr == 123) {
long cpusetsize = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X1)).longValue();
long maskAddr = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X2)).longValue();
if (maskAddr != 0 && cpusetsize > 0) {
final int cores = 8;
final int size = (int) cpusetsize;
byte[] buf = new byte[size];
int maxBits = size * 8;
int bitsToSet = Math.min(cores, maxBits);
for (int cpu = 0; cpu < bitsToSet; cpu++) {
int bi = cpu / 8;
int bit = cpu % 8;
buf[bi] |= (1 << bit);
}
backend.mem_write(maskAddr, buf);
}
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, cpusetsize);
backend.reg_write(Arm64Const.UC_ARM64_REG_X8, -1);
}
super.hook(backend, intno, swi, user);
}
特性 / 方面
fstat (旧版)
statx (现代版)
操作对象
只能 作用于一个已经打开的文件描述符 (fd) 。
更灵活 ,既可以作用于文件描述符 ,也可以直接作用于文件路径 。
信息丰富度
返回 struct stat 结构体,信息相对基础。
返回 struct statx 结构体,信息更丰富,可以提供文件创建时间 (btime) 等。
时间戳精度
传统上只精确到秒 。
精确到纳秒 (nanosecond) ,更能满足现代高精度需求。
执行效率
All-or-Nothing (全量获取) 。每次调用,内核都会填充所有字段,不管你是否需要。
On-Demand (按需获取) 。可以通过 mask 参数精确指定需要哪些信息,内核按需返回,效率更高。
扩展性
struct stat 结构体已非常拥挤,难以扩展。
struct statx 设计上留有余地,方便未来添加新属性。
@Override
public int fstat(Emulator<?> emulator, StatStructure stat) {
stat.st_mode = IO.S_IFDIR;
stat.st_dev = 0;
stat.st_size = 0;
stat.st_blksize = 0;
stat.st_ino = 0;
stat.pack();
return 0;
}
@Override
public int fstat(Emulator<?> emulator, StatStructure stat) {
stat.st_mode = IO.S_IFDIR;
stat.st_dev = 0;
stat.st_size = 0;
stat.st_blksize = 0;
stat.st_ino = 0;
stat.pack();
return 0;
}
if (nr == 80) {
int fd = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X0)).intValue();
UnidbgPointer statbuf = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
if (this.fdMap.get(fd) instanceof DirectoryFileIO) {
System.out.println("Hooked fstat(80) for directory fd=" + fd);
StatStructure stat = new Stat64(statbuf);
stat.st_mode = S_IFDIR | 0755;
stat.st_dev = 1;
stat.st_size = 4096;
stat.st_blksize = 4096;
stat.st_ino = 12345;
stat.setSt_atim(1668267277L, 999999999L);
stat.pack();
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, 0);
backend.reg_write(Arm64Const.UC_ARM64_REG_X8, -1);
}
if (nr == 80) {
int fd = ((Number) backend.reg_read(Arm64Const.UC_ARM64_REG_X0)).intValue();
UnidbgPointer statbuf = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1);
if (this.fdMap.get(fd) instanceof DirectoryFileIO) {
System.out.println("Hooked fstat(80) for directory fd=" + fd);
StatStructure stat = new Stat64(statbuf);
stat.st_mode = S_IFDIR | 0755;
stat.st_dev = 1;
stat.st_size = 4096;
stat.st_blksize = 4096;
stat.st_ino = 12345;
stat.setSt_atim(1668267277L, 999999999L);
stat.pack();
backend.reg_write(Arm64Const.UC_ARM64_REG_X0, 0);
backend.reg_write(Arm64Const.UC_ARM64_REG_X8, -1);
}
private void hook_popen() {
IxHook xHook = XHookImpl.getInstance(emulator);
xHook.register("libszstone.so", "popen", new ReplaceCallback() {
@Override
public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
RegisterContext registerContext = emulator.getContext();
String command = registerContext.getPointerArg(0).getString(0);
emulator.set("command", command);
System.out.println("command:"+command);
return HookStatus.RET(emulator, originFunction);
}
}, true);
xHook.refresh();
}
challenge.hook_popen();
private void hook_popen() {
IxHook xHook = XHookImpl.getInstance(emulator);
xHook.register("libszstone.so", "popen", new ReplaceCallback() {
@Override
public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
RegisterContext registerContext = emulator.getContext();
String command = registerContext.getPointerArg(0).getString(0);
emulator.set("command", command);
System.out.println("command:"+command);
return HookStatus.RET(emulator, originFunction);
}
}, true);
xHook.refresh();
}
challenge.hook_popen();
@Override
protected int pipe2(Emulator<?> emulator) {
UnidbgPointer pipefd = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X0);
int write_fd = getMinFd();
int read_fd = getMinFd();
this.fdMap.put(write_fd, new DumpFileIO(write_fd));
String cmd = (String) emulator.get("command");
if (cmd == null) cmd = "stat /data";
String stdout = "\n";
if ("stat /data".equals(cmd)) {
stdout =
" File: /data\n" +
" Size: 4096 Blocks: 16 IO Blocks: 512 directory\n" +
"Device: 10305h/66309d Inode: 2 Links: 53\n" +
"Access: (0771/drwxrwx--x) Uid: ( 1000/ system) Gid: ( 1000/ system)\n" +
"Access: 2022-04-22 16:08:42.656423789 +0800\n" +
"Modify: 1970-02-05 00:02:38.459999996 +0800\n" +
"Change: 1971-12-21 21:33:28.769999994 +0800\n";
}
this.fdMap.put(read_fd, new ByteArrayFileIO(0, "pipe2_read_side", stdout.getBytes()));
pipefd.setInt(0, read_fd);
pipefd.setInt(4, write_fd);
return 0;
}
@Override
protected int pipe2(Emulator<?> emulator) {
UnidbgPointer pipefd = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X0);
int write_fd = getMinFd();
int read_fd = getMinFd();
this.fdMap.put(write_fd, new DumpFileIO(write_fd));
String cmd = (String) emulator.get("command");
if (cmd == null) cmd = "stat /data";
String stdout = "\n";
if ("stat /data".equals(cmd)) {
stdout =
" File: /data\n" +
" Size: 4096 Blocks: 16 IO Blocks: 512 directory\n" +
"Device: 10305h/66309d Inode: 2 Links: 53\n" +
"Access: (0771/drwxrwx--x) Uid: ( 1000/ system) Gid: ( 1000/ system)\n" +
"Access: 2022-04-22 16:08:42.656423789 +0800\n" +
"Modify: 1970-02-05 00:02:38.459999996 +0800\n" +
"Change: 1971-12-21 21:33:28.769999994 +0800\n";
}
this.fdMap.put(read_fd, new ByteArrayFileIO(0, "pipe2_read_side", stdout.getBytes()));
pipefd.setInt(0, read_fd);
pipefd.setInt(4, write_fd);
return 0;
}
private int fakePid = 4242;
@Override
protected long fork(Emulator<?> emulator) {
return ++fakePid;
}
private int fakePid = 4242;
@Override
protected long fork(Emulator<?> emulator) {
return ++fakePid;
}
#include <sys/types.h>
pid_t gettid(void);
#include <sys/types.h>
pid_t gettid(void);
private static void hookLibcGettidWithDobby(Emulator<?> emulator, int forcedTid) {
Module libc = emulator.getMemory().findModule("libc.so");
if (libc == null) {
throw new IllegalStateException("libc.so not found");
}
Symbol sym = libc.findSymbolByName("gettid", false);
if (sym == null) sym = libc.findSymbolByName("__gettid", false);
if (sym == null) {
throw new IllegalStateException("gettid/__gettid symbol not found in libc.so");
}
Dobby dobby = Dobby.getInstance(emulator);
dobby.replace(sym, new ReplaceCallback() {
@Override
public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
int fakeTid = forcedTid;
System.out.println("[HOOK] gettid(): Faking return value to -> " + fakeTid);
return HookStatus.LR(emulator, (long) (fakeTid & 0xffffffffL));
}
});
}
hookLibcGettidWithDobby(emulator, emulator.getPid());
private static void hookLibcGettidWithDobby(Emulator<?> emulator, int forcedTid) {
Module libc = emulator.getMemory().findModule("libc.so");
if (libc == null) {
throw new IllegalStateException("libc.so not found");
}
Symbol sym = libc.findSymbolByName("gettid", false);
if (sym == null) sym = libc.findSymbolByName("__gettid", false);
if (sym == null) {
throw new IllegalStateException("gettid/__gettid symbol not found in libc.so");
}
Dobby dobby = Dobby.getInstance(emulator);
dobby.replace(sym, new ReplaceCallback() {
@Override
public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
int fakeTid = forcedTid;
System.out.println("[HOOK] gettid(): Faking return value to -> " + fakeTid);
return HookStatus.LR(emulator, (long) (fakeTid & 0xffffffffL));
}
});
}
hookLibcGettidWithDobby(emulator, emulator.getPid());
AIzaSyDeYcYUxAN52DNrgZeFNcEfceVMoWJDjWk
AIzaSyDLMJARxMYqUt4Tl8ADjPPPB1m672tTVmY
AIzaSyAWY438PG4XacWuZU8nQtQ0popo9YAVB18
AIzaSyBouea_CZifzNGN_vC72TtyxYwQLR42tpM
AIzaSyBJtRKb0W0cg1f3Tv65yU1NaYAZ3Hiqn3g
AIzaSyBYPYP-SgvrqsdVrfgOFwvPSGsIFdRLlRs
AIzaSyDN1EtiR1ef6LG4xjtSiiDPNPkkJMh0auQ
AIzaSyCNbdDb9FsvXA8B2Gn_qzhQSxmuTHo_ifA
AIzaSyBJEAGhQB1Wou6yzHe1QCQPv2GaHgsdeTA
AIzaSyDgpkOpIGCuZif3BU9lcrrFOkY-onE263E
AIzaSyBmOVAdUB54vGOHroYOJ7OtC06YrFDOST0
AIzaSyAymb7h68s42zt6xY7jmJMBUjqPiMyU27M
AIzaSyCSHZuRBP1RPGcirYaCopJFi9FSM7le6Zc
AIzaSyBLlTKQaxeXm7DWa5Q1mmSIHBpHyWRdwMA
AIzaSyCxt7zx-cUzvkuroP1uaSp_m0SkoFU_j4A
AIzaSyBnOqAk-VfAjdFpbkveT2yJnNmFXv9-7Mw
AIzaSyDtsLIwVZgT5T8tqfYN2PIQKlflAk-90NI
AIzaSyCvXozHylyHSEFYAW-SZ1QXLyQeKJnt-ac
AIzaSyCy_5IaKck7-MrnJRYLjyV3n2FeCJ9FDGs
AIzaSyBTxaEzGGLVrskzx7UK374NgV4BXn-4nqs
AIzaSyCXSEStgw39a9znv6ATo8mRQZ0eRI5T-n0
AIzaSyA_tSR5vUDWRSIIXFdsOJtnSsueC496njQ
AIzaSyBl56gfbyjTY5qI1mzTP9-uK_Jg7c2ckaY
AIzaSyCQxdrjSaHUfAYikI64Co_mux09RRtYLe0
AIzaSyCl25sgM6WAbqYmY_QTqlMnYQCQxQEQQO8
AIzaSyBjuyyFRTJ5b4XOSAVosrfZShx1K-e6FyE
AIzaSyChOZyn4FgZm41gyg2VEValfDV47IIuw3Q
AIzaSyCg_axGIeK7mMj_XeYtozTQdj4iREPufSo
AIzaSyCmje3P-kGPwqE5hENYujKLKjIievNvmvM
AIzaSyDeQ2QYCW9bu32DX9nmuNrctgKC2oTyZW8
AIzaSyBySkCG5yLgtz4IANJySl5Y59Xxt9pdVWI
AIzaSyCrDCA1le2EY2tSMUu-JTXEusSnXFaXv6k
AIzaSyAevOZ8wu6LmrS6XQDH-S1prUb4Zs-WOqk
AIzaSyDwdVZuLn4W9Xz4YGNtqRcaKXFrl6HE3dA
AIzaSyDx5bncjiKOnbQ_1mz8j6kgwHlKGRWxQIo
AIzaSyDj14MIi4L7pCxXIxMfJVFTTaZ5h_stxdI
AIzaSyCxrE6u0KsbiAR6vLrBnC5PPqG05wl-bTA
AIzaSyDX3U9UEgus4Gdx7960ABTn7Ll3LYMxaF4
AIzaSyDEDxFwPbMXPv7GUb1sQduNLCgbpgvU8_I
AIzaSyCCGyjLLZNZnSm0OZOMtxQWe--ZOnsfe_4
AIzaSyDtDKmMytfIq9Ld5VUIOffIoOY7yXxWEv4
AIzaSyCuz7VK0DU7EtdmMHhNidccJfU36j6CADs
AIzaSyCV9dD4V90z7Sf_fWenXEb83ne0Iav5i3o
AIzaSyAqb4ZV4vCfhrfvinj_rGs3lZOP1--zyqc
AIzaSyCo1NhsZBJg5Yloi5HcrdeMnkNGrSloJ9E
AIzaSyCL9cN9Y3-qQbS5wmr9gxk3J9ZICWHsyiQ
AIzaSyDBacTP1FYjR61hHBUNLCEtLAyk5vqFPiI
AIzaSyCV077Q-1nwxMbPM_3f4Z1h1b7ZHjIBE78
AIzaSyDuExne7oG9NnfNZeaqDOSXVtxUdau7IBU
AIzaSyBHXLYc4hrlVFafKd3hsvqniK1Nytw6pDI
AIzaSyDRizynqIPgiZfgrMdqcosDOWxsTGNtwEM
AIzaSyCIjgG29HPVa7_db5NMrQL5O4oBgW18S5o
AIzaSyDa0wwQKBtfwVxP8wmZSTpq2hFxV0QeCY8
AIzaSyAT2aZC-EMqdjYaz2VgBWCtNFp8rE2If34
AIzaSyAvXG6KKI65N1jNOwIRwEQNoyWbXpdDcsg
AIzaSyAEWasCSVrPKoBXH8SEwFYMu6rbKjTFPcQ
AIzaSyAMWdJ5n3Ro5FdnQNJzw0wrUmNYBw0wzKU
AIzaSyDJnRYm3-t06ks4zrBFyEglV6qJyFvn8Qo
AIzaSyDfNTj4zJWiaXbzwvur812s9DPb5CE9y2w
AIzaSyBqopZ5Q_RKyzYYMI-LmcbSaJwONy16TzU
AIzaSyDR49YtJPhn0QJB8Jh6FZM4gSliW9W47xg
AIzaSyBMT1vW_L-VEqZdF_fMCowgtNbzIQduqMI
AIzaSyDsMf87ZAzDFUZHBnc1HQXmidOGDu8anhk
AIzaSyDweH2jQe7RLYDYUUfcJlAVxgcOmLkd3is
AIzaSyDzAOJND8nS3c7Mwzc0rU330eHucH9c-8E
AIzaSyBU-hzfR-sgVp_-OSb3YcPmUwbUOApUIPE
AIzaSyAXVwlY7urRPxPMlkE_T8Z-4hIc_dzgGE0
AIzaSyDRpJORsoLZMRG60l_68TEzH5b3jd6DGZ4
AIzaSyCBHcP4Seer76nBjvy9vOciNxHumZg7eFE
AIzaSyDqH5QxZxhb8SpQ-_LEmhTteXmzYmpSHgE
AIzaSyDHlry6Ma_CLUVyBGOH7ph0WZLKRG2ccbg
AIzaSyAq2b17eIBC4UJpyateDA3fwRgGe2uC6Ko
AIzaSyCfgPZn0kZZPmk5eaaVvlkR-SrGH2rXH4k
AIzaSyBoiXy-lnXJhOOF0YxMeFFbn7F4oOXtTIc
AIzaSyCHCrl4O31xv4msRwR9B52dpghDPmpKwKM
AIzaSyCQddEzfQidcNdtuDbq8SSlO6K3Ds-ayOc
AIzaSyADe2YtszUhEcTR546CNlc3UVssE7PStMU
AIzaSyCD8uwm3Ye7tBS6uFxOM6mao1sqssf_SHw
AIzaSyDlBv9Br45qcfbzGyr3AlcScyWQo3eSOPU
AIzaSyAu_PNVM03Pu1o380ZI_TKU61FSDeDV1Ks
AIzaSyCDz4gjhidaJvdzPjYHxdo1o0CAqiqll9k
AIzaSyDL12z-qYxT4uAv2v2hwjMHUe8iXcK0ETU
AIzaSyDtwjdZFSAW1pJSnAj1kURTN8kGeFWmATU
AIzaSyAUKqVhKd51nSHwZUxQrYTGqPsr31IdyCY
AIzaSyAUfL_KrYf9rY599fGi2v63IR2Z_PmMMcw
AIzaSyAxpV4OY_zVDst3jGaYNwnyHhFmZ0V4XJE
AIzaSyBoJIB7xIHrxVCw6dd8Zv_eJHSe67lmoQM
AIzaSyCaxTDfzcE5UqPCiZ5QmDEXsgQkdgLhp1w
AIzaSyDzQChJoC_jnb5xwn9UHkFyePD3qZYRaBU
AIzaSyCuZ0zCypYmrGT5GXopw3JPu3WGLzEMpGU
AIzaSyBMlGsH4vA9gcEimwnOyMTAFcPZ33J3akI
AIzaSyCXzlJRd3krr5e32pXTAS14mfS3a8dDsMA
AIzaSyAMgFD2kmgb7Cri49Z7-sOAFBejb37LWgQ
AIzaSyAQPkvdoV4_nzsaaYTZu-QqU__kV9988JI
AIzaSyASjNCk1oxREML4AFhcx5joggaSyvDVj9Q
AIzaSyBl5lM6Md8_YbDt7o-rmB2SiIyppPT32dU
AIzaSyDo3Y0qZ5HPmGGoTNGl_6xmxbOAE8q3cSY
AIzaSyBGFC9cnNJEC822NAKicHbX4PJsE1PGn4c
AIzaSyDUlDBDxfl7c33vb3ILKLayrQNROqHhUDg
AIzaSyDYlLPKXjcrvyTMl8ANYH_FgvKM1mrIdcM
AIzaSyCtJ4cwA90mL25n2f-aFUfnOP0t9zEgs7A
AIzaSyCX_TzqcMio44YuQnkFe0HAaUQNE5qa4n4
AIzaSyDQFUa1LGkonbd7152FK6roHyLs4FhMsVM
AIzaSyDNwmGY0aTaE0GFAndRe773JmZtoPBO8WU
AIzaSyBhITH3uj_6kHz4cIHQ5p7-M5cuOXvGwW0
AIzaSyBidS2L33bSz73nCywuv64Z-lxIx3IaifE
AIzaSyBe8kjRD-siRLDQh30xVRka5TmrsAZVwYc
AIzaSyDfO3oWskF7Pj99ua_72pZxEDQgfGEl8Fo
AIzaSyAFsWzfDNb-OE9DM7ucb4Nwx2rgr_5Horg
AIzaSyCNSdZWCnONcfrmjYI3STJAEO3TRGXxgbQ
AIzaSyCd5zymLO6nQPtaSBtDZJbIggZbQFeRCvc
AIzaSyAF5WnWgLOWJthnfD6_KpSuD7eI5FdAQBk
AIzaSyAj9qY_NbobH5D7wkF1QjWWJ0Wb-agLEgI
AIzaSyDRY5Iga1IYEZjK0MroKACshZYDSoDa5kQ
AIzaSyDQs4bJr4VHcO5XZMHM5Gg3GKVSi7hifoU
AIzaSyDnhCxgEgCMPtBgYi9evlCDm8NKWHrFbMc
AIzaSyDegIQZAzMZeiVajsStxrgWvGDMkfZ4GUg
AIzaSyAOIVHb7xcAMqx07D4kM45qwHNZeNu0Qas
AIzaSyChcczCZLpZbYlw7J_vcU5LE-pfKUFiS3o
AIzaSyBOUpORGxljVDusUs-fMVpLKfZNh02AnmU
AIzaSyCUfqhUXwgUzkw_t67wF3D4gsRCBgYm-50
AIzaSyAMZ7sJlD2ZlUyqObwLOZgJ9BGneYATG2o
AIzaSyBN5WVkfPSZ4EcqoTy06XfmaRjXrl0DbnU
AIzaSyBAn3hVZfgMUQYIm-o_-U0TaM1lGCCDItw
AIzaSyBhoK80uMGiY-885co3xqdnCOzXBjBC24k
AIzaSyAr8fG-NsCNjVe3QmnS_zMsu9Kaf6jVGa4
AIzaSyCLExLEYHiMK3Hyo3XoJBEug5wvfLdJ-p0
AIzaSyCLx3zZ7xGSMpuE0jc87gdJV7VNQ5DcSZM
AIzaSyCpoWTEbR9ggzR_74bkUUdjir_2Kw8ALm0
AIzaSyBeUkVJzv1yx9bVIQsveMma-dsAi8TcqME
AIzaSyCmS2TuyUXfXRREsiEEgmWeG8Plu__0SqA
AIzaSyDlwNcNuyR-HnUctFz8Bn2uS0ienqJz2zc
AIzaSyBaUKIYRqv4Bj2V-Kqx1C7IJ5zvlRwLO_E
AIzaSyDm4gztlWTcR2SUla8Y9bH3iXZbshuXD_4
AIzaSyDZ93djmNzYIRkFs8qxTJmRPWVaYf_fPxM
AIzaSyDo-2Ubl_SukYv1QoIHPREB0CYy-uFrHJc
AIzaSyCxdHELZeZykp4jGMNp8JGJKGFexRjc-i8
AIzaSyBJsFQon7QDK7QRslWWBGPxhbuUJBcWB0k
AIzaSyCF4NKD4O01ktWWoRPWluyx9fD2MaFg8iU
AIzaSyCKEpwjAEcy979dinuoTSsCD4eMB8JaHLA
AIzaSyBkunWP4l4SVzCSbaP_oVNHrXO9OI_R33k
AIzaSyCLiVBiLWYKH04qVhd8Dj45mmNaG-s8Bzc
AIzaSyBkm3UaXYRKLKwmXyFsjOfNQtG4slPAtMM
AIzaSyCXPk-S3qNYYU7f960YP1XIwKQMIUigWAE
AIzaSyDoYoM0xCbpbnkzmEOUzrOQKE2I3tGEiPw
AIzaSyCWDo6tT1HFlsXT50RPzFn3glMhzTXVHDg
AIzaSyDJzAJF422SyZ99Z6CGihnJqKIDlQn4CfM
AIzaSyCjH6NCAmwcrqxaWEhxeSaMqKc9A10Osec
AIzaSyBjTvXHlFStQbzCOg88jjbe1cAaxlaE9M8
AIzaSyBugkmHyJf32u7vlRtU3VviO3mE2RZGVQQ
AIzaSyALDOFJnoigN_k0lFRydMnnfJJjHJcDfiI
AIzaSyDCGHHwwKmlDYtLdXLiEnxzNfSKw6ewSbY
AIzaSyDNOtokPHTUm9WCJ1pOPaweUp_Rks9DhjI
AIzaSyCv4H5U4WJ7DDC4O-2N-sBSnH9GPMwurqk
AIzaSyBAKQdzi4bjkeHz_xnpVaUp0JbSgGB5mWc
AIzaSyCnTROIII2xrUW6rpzDn_WdRFhiLKuze5I
AIzaSyBE-m0-Np0mqdwHrGg1XNue4cz5qC3ecDA
AIzaSyBU41uwxx-G-Mkff20r0OzJWfOVI35rZwQ
AIzaSyDw79xgZTh2lYEPMF2JPs_RqUrteKz1eZU
AIzaSyBjatV-0puUSHYY-PYbUVyj3GuYJYV918g
AIzaSyAlrRP3TQWTaI_essPz0oaNQAhXeq8SaOw
AIzaSyBBdjoUVKVJZb1Ovv-6WbQD7XYIRg3BSKo
AIzaSyAcWQruU56ZLIvQQpMDoHBkRjBjnY4Ja2I
AIzaSyAduQyY6xC4Nma4uPvHwve2fxKNXIYe2dQ
AIzaSyBbhTEJfa9ArGgKKnjUOV3XL60UMpL_gd4
AIzaSyCqTYLyCG37Y2S8s_8NxY0RJD9zj-JgSGI
AIzaSyAAvmxbVy8qcLotR34MB36klygYgNGnS2g
AIzaSyDlyjDbO-HdJyLXVrpzd8R1zqd_KE8Mq4E
AIzaSyAzhXIpf500NeZdfl44Qjh5k7epNaa8WS8
AIzaSyAvuhTgURgvzTRIp51CzIggks-top10DRs
AIzaSyAUgrPIOR1Kokk1f29rvxhkIZom9mToA_o
AIzaSyBe6EkfS-eVWMOQalm2TpxL6ljGBC2z9dI
AIzaSyBIoS20jBYkfdUnMII-bfVMprmCpwWr9Lg
AIzaSyCW1nB9SIPs0BcAy_rUoR6oT0E1ePKaRuo
AIzaSyDu6pH5nfKPJzzanYwEp2yCsubvl495oyk
AIzaSyCEzmk05J35sn0ADAjbX3PPTrRjbl2Pqn0
AIzaSyANY9CZz7W7VRh8hObUhJMdAWTyLD3ngrk
AIzaSyALWlbXC2RpSrGqzSr7Ubjm_UwSY8W7IbY
AIzaSyCAVsYKBiAL0oXtZ5weAXXRbX7J6GOrJII
AIzaSyAN40P9Ad_3COVtCUTzxKzAmmw9D1vUrZM
AIzaSyDeYcYUxAN52DNrgZeFNcEfceVMoWJDjWk
AIzaSyDLMJARxMYqUt4Tl8ADjPPPB1m672tTVmY
AIzaSyAWY438PG4XacWuZU8nQtQ0popo9YAVB18
AIzaSyBouea_CZifzNGN_vC72TtyxYwQLR42tpM
AIzaSyBJtRKb0W0cg1f3Tv65yU1NaYAZ3Hiqn3g
AIzaSyBYPYP-SgvrqsdVrfgOFwvPSGsIFdRLlRs
AIzaSyDN1EtiR1ef6LG4xjtSiiDPNPkkJMh0auQ
AIzaSyCNbdDb9FsvXA8B2Gn_qzhQSxmuTHo_ifA
AIzaSyBJEAGhQB1Wou6yzHe1QCQPv2GaHgsdeTA
AIzaSyDgpkOpIGCuZif3BU9lcrrFOkY-onE263E
AIzaSyBmOVAdUB54vGOHroYOJ7OtC06YrFDOST0
AIzaSyAymb7h68s42zt6xY7jmJMBUjqPiMyU27M
AIzaSyCSHZuRBP1RPGcirYaCopJFi9FSM7le6Zc
AIzaSyBLlTKQaxeXm7DWa5Q1mmSIHBpHyWRdwMA
AIzaSyCxt7zx-cUzvkuroP1uaSp_m0SkoFU_j4A
AIzaSyBnOqAk-VfAjdFpbkveT2yJnNmFXv9-7Mw
AIzaSyDtsLIwVZgT5T8tqfYN2PIQKlflAk-90NI
AIzaSyCvXozHylyHSEFYAW-SZ1QXLyQeKJnt-ac
AIzaSyCy_5IaKck7-MrnJRYLjyV3n2FeCJ9FDGs
AIzaSyBTxaEzGGLVrskzx7UK374NgV4BXn-4nqs
AIzaSyCXSEStgw39a9znv6ATo8mRQZ0eRI5T-n0
AIzaSyA_tSR5vUDWRSIIXFdsOJtnSsueC496njQ
AIzaSyBl56gfbyjTY5qI1mzTP9-uK_Jg7c2ckaY
AIzaSyCQxdrjSaHUfAYikI64Co_mux09RRtYLe0
AIzaSyCl25sgM6WAbqYmY_QTqlMnYQCQxQEQQO8
AIzaSyBjuyyFRTJ5b4XOSAVosrfZShx1K-e6FyE
AIzaSyChOZyn4FgZm41gyg2VEValfDV47IIuw3Q
AIzaSyCg_axGIeK7mMj_XeYtozTQdj4iREPufSo
AIzaSyCmje3P-kGPwqE5hENYujKLKjIievNvmvM
AIzaSyDeQ2QYCW9bu32DX9nmuNrctgKC2oTyZW8
AIzaSyBySkCG5yLgtz4IANJySl5Y59Xxt9pdVWI
AIzaSyCrDCA1le2EY2tSMUu-JTXEusSnXFaXv6k
AIzaSyAevOZ8wu6LmrS6XQDH-S1prUb4Zs-WOqk
AIzaSyDwdVZuLn4W9Xz4YGNtqRcaKXFrl6HE3dA
AIzaSyDx5bncjiKOnbQ_1mz8j6kgwHlKGRWxQIo
AIzaSyDj14MIi4L7pCxXIxMfJVFTTaZ5h_stxdI
AIzaSyCxrE6u0KsbiAR6vLrBnC5PPqG05wl-bTA
AIzaSyDX3U9UEgus4Gdx7960ABTn7Ll3LYMxaF4
AIzaSyDEDxFwPbMXPv7GUb1sQduNLCgbpgvU8_I
AIzaSyCCGyjLLZNZnSm0OZOMtxQWe--ZOnsfe_4
AIzaSyDtDKmMytfIq9Ld5VUIOffIoOY7yXxWEv4
AIzaSyCuz7VK0DU7EtdmMHhNidccJfU36j6CADs
AIzaSyCV9dD4V90z7Sf_fWenXEb83ne0Iav5i3o
AIzaSyAqb4ZV4vCfhrfvinj_rGs3lZOP1--zyqc
AIzaSyCo1NhsZBJg5Yloi5HcrdeMnkNGrSloJ9E
AIzaSyCL9cN9Y3-qQbS5wmr9gxk3J9ZICWHsyiQ
AIzaSyDBacTP1FYjR61hHBUNLCEtLAyk5vqFPiI
AIzaSyCV077Q-1nwxMbPM_3f4Z1h1b7ZHjIBE78
AIzaSyDuExne7oG9NnfNZeaqDOSXVtxUdau7IBU
AIzaSyBHXLYc4hrlVFafKd3hsvqniK1Nytw6pDI
AIzaSyDRizynqIPgiZfgrMdqcosDOWxsTGNtwEM
AIzaSyCIjgG29HPVa7_db5NMrQL5O4oBgW18S5o
AIzaSyDa0wwQKBtfwVxP8wmZSTpq2hFxV0QeCY8
AIzaSyAT2aZC-EMqdjYaz2VgBWCtNFp8rE2If34
AIzaSyAvXG6KKI65N1jNOwIRwEQNoyWbXpdDcsg
AIzaSyAEWasCSVrPKoBXH8SEwFYMu6rbKjTFPcQ
AIzaSyAMWdJ5n3Ro5FdnQNJzw0wrUmNYBw0wzKU
AIzaSyDJnRYm3-t06ks4zrBFyEglV6qJyFvn8Qo
AIzaSyDfNTj4zJWiaXbzwvur812s9DPb5CE9y2w
AIzaSyBqopZ5Q_RKyzYYMI-LmcbSaJwONy16TzU
AIzaSyDR49YtJPhn0QJB8Jh6FZM4gSliW9W47xg
AIzaSyBMT1vW_L-VEqZdF_fMCowgtNbzIQduqMI
AIzaSyDsMf87ZAzDFUZHBnc1HQXmidOGDu8anhk
AIzaSyDweH2jQe7RLYDYUUfcJlAVxgcOmLkd3is
AIzaSyDzAOJND8nS3c7Mwzc0rU330eHucH9c-8E
AIzaSyBU-hzfR-sgVp_-OSb3YcPmUwbUOApUIPE
AIzaSyAXVwlY7urRPxPMlkE_T8Z-4hIc_dzgGE0
AIzaSyDRpJORsoLZMRG60l_68TEzH5b3jd6DGZ4
AIzaSyCBHcP4Seer76nBjvy9vOciNxHumZg7eFE
AIzaSyDqH5QxZxhb8SpQ-_LEmhTteXmzYmpSHgE
AIzaSyDHlry6Ma_CLUVyBGOH7ph0WZLKRG2ccbg
AIzaSyAq2b17eIBC4UJpyateDA3fwRgGe2uC6Ko
AIzaSyCfgPZn0kZZPmk5eaaVvlkR-SrGH2rXH4k
AIzaSyBoiXy-lnXJhOOF0YxMeFFbn7F4oOXtTIc
AIzaSyCHCrl4O31xv4msRwR9B52dpghDPmpKwKM
AIzaSyCQddEzfQidcNdtuDbq8SSlO6K3Ds-ayOc
AIzaSyADe2YtszUhEcTR546CNlc3UVssE7PStMU
AIzaSyCD8uwm3Ye7tBS6uFxOM6mao1sqssf_SHw
AIzaSyDlBv9Br45qcfbzGyr3AlcScyWQo3eSOPU
AIzaSyAu_PNVM03Pu1o380ZI_TKU61FSDeDV1Ks
AIzaSyCDz4gjhidaJvdzPjYHxdo1o0CAqiqll9k
AIzaSyDL12z-qYxT4uAv2v2hwjMHUe8iXcK0ETU
AIzaSyDtwjdZFSAW1pJSnAj1kURTN8kGeFWmATU
AIzaSyAUKqVhKd51nSHwZUxQrYTGqPsr31IdyCY
AIzaSyAUfL_KrYf9rY599fGi2v63IR2Z_PmMMcw
AIzaSyAxpV4OY_zVDst3jGaYNwnyHhFmZ0V4XJE
AIzaSyBoJIB7xIHrxVCw6dd8Zv_eJHSe67lmoQM
AIzaSyCaxTDfzcE5UqPCiZ5QmDEXsgQkdgLhp1w
AIzaSyDzQChJoC_jnb5xwn9UHkFyePD3qZYRaBU
AIzaSyCuZ0zCypYmrGT5GXopw3JPu3WGLzEMpGU
AIzaSyBMlGsH4vA9gcEimwnOyMTAFcPZ33J3akI
AIzaSyCXzlJRd3krr5e32pXTAS14mfS3a8dDsMA
AIzaSyAMgFD2kmgb7Cri49Z7-sOAFBejb37LWgQ
AIzaSyAQPkvdoV4_nzsaaYTZu-QqU__kV9988JI
AIzaSyASjNCk1oxREML4AFhcx5joggaSyvDVj9Q
AIzaSyBl5lM6Md8_YbDt7o-rmB2SiIyppPT32dU
AIzaSyDo3Y0qZ5HPmGGoTNGl_6xmxbOAE8q3cSY
AIzaSyBGFC9cnNJEC822NAKicHbX4PJsE1PGn4c
AIzaSyDUlDBDxfl7c33vb3ILKLayrQNROqHhUDg
AIzaSyDYlLPKXjcrvyTMl8ANYH_FgvKM1mrIdcM
AIzaSyCtJ4cwA90mL25n2f-aFUfnOP0t9zEgs7A
AIzaSyCX_TzqcMio44YuQnkFe0HAaUQNE5qa4n4
AIzaSyDQFUa1LGkonbd7152FK6roHyLs4FhMsVM
AIzaSyDNwmGY0aTaE0GFAndRe773JmZtoPBO8WU
AIzaSyBhITH3uj_6kHz4cIHQ5p7-M5cuOXvGwW0
AIzaSyBidS2L33bSz73nCywuv64Z-lxIx3IaifE
AIzaSyBe8kjRD-siRLDQh30xVRka5TmrsAZVwYc
AIzaSyDfO3oWskF7Pj99ua_72pZxEDQgfGEl8Fo
AIzaSyAFsWzfDNb-OE9DM7ucb4Nwx2rgr_5Horg
AIzaSyCNSdZWCnONcfrmjYI3STJAEO3TRGXxgbQ
AIzaSyCd5zymLO6nQPtaSBtDZJbIggZbQFeRCvc
AIzaSyAF5WnWgLOWJthnfD6_KpSuD7eI5FdAQBk
AIzaSyAj9qY_NbobH5D7wkF1QjWWJ0Wb-agLEgI
AIzaSyDRY5Iga1IYEZjK0MroKACshZYDSoDa5kQ
AIzaSyDQs4bJr4VHcO5XZMHM5Gg3GKVSi7hifoU
AIzaSyDnhCxgEgCMPtBgYi9evlCDm8NKWHrFbMc
AIzaSyDegIQZAzMZeiVajsStxrgWvGDMkfZ4GUg
AIzaSyAOIVHb7xcAMqx07D4kM45qwHNZeNu0Qas
AIzaSyChcczCZLpZbYlw7J_vcU5LE-pfKUFiS3o
AIzaSyBOUpORGxljVDusUs-fMVpLKfZNh02AnmU
AIzaSyCUfqhUXwgUzkw_t67wF3D4gsRCBgYm-50
AIzaSyAMZ7sJlD2ZlUyqObwLOZgJ9BGneYATG2o
AIzaSyBN5WVkfPSZ4EcqoTy06XfmaRjXrl0DbnU
AIzaSyBAn3hVZfgMUQYIm-o_-U0TaM1lGCCDItw
AIzaSyBhoK80uMGiY-885co3xqdnCOzXBjBC24k
AIzaSyAr8fG-NsCNjVe3QmnS_zMsu9Kaf6jVGa4
AIzaSyCLExLEYHiMK3Hyo3XoJBEug5wvfLdJ-p0
AIzaSyCLx3zZ7xGSMpuE0jc87gdJV7VNQ5DcSZM
AIzaSyCpoWTEbR9ggzR_74bkUUdjir_2Kw8ALm0
AIzaSyBeUkVJzv1yx9bVIQsveMma-dsAi8TcqME
AIzaSyCmS2TuyUXfXRREsiEEgmWeG8Plu__0SqA
AIzaSyDlwNcNuyR-HnUctFz8Bn2uS0ienqJz2zc
AIzaSyBaUKIYRqv4Bj2V-Kqx1C7IJ5zvlRwLO_E
AIzaSyDm4gztlWTcR2SUla8Y9bH3iXZbshuXD_4
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-10-9 10:55
被正己编辑
,原因: