当前位置:首页>学习笔记>Unidbg学习笔记(十七):Hook 框架选型与实战

Unidbg学习笔记(十七):Hook 框架选型与实战

  • 2026-04-29 10:29:55
Unidbg学习笔记(十七):Hook 框架选型与实战

Hook 是 Unidbg 里最容易过度设计的一环。拿到框架表看一眼,你会本能地选最强大的那个 —— 但结果常常是“一个锤子敲碎了整个桌子”。这一篇把 Unidbg 内置的六种 Hook 框架拆开,讲清楚哪种场景用哪种,以及不该用哪种


上一篇把你留在了哪里

第十六篇我们讲了 Console Debugger,这是一把手术刀 —— 精确,但只能在你亲自操刀时生效。断点回调算是半自动化,但仍然是“点对点”的。

但有些场景,手术刀不够用:

  • 想拦截 getrusage 这类 libc 函数 —— 调用点分散在 SO 里十几处,你没法一个一个下断点。
  • 想把 malloc 换成自己的实现 —— 你需要的是“替换”,不是“观察”。
  • 想让 free(ptr) 变成空操作 —— 断点改 PC 能做到,但每次都手动太累。

这时候需要的是Hook 框架 —— 一次注册,全局生效,代码简洁。

Unidbg 内置了不止一个 Hook 框架,而是六个。它们不是并列关系,而是从高到低五个不同的抽象层次。用错层次,代码会翻倍;用对层次,一行就搞定。


Hook 的本质

在讨论框架之前,先澄清一个概念:Hook 的本质就是“在函数调用前后插入自己的代码,而不修改原始二进制”

实现 Hook 有三种底层技术:

技术
原理
代表
GOT/PLT Hook
替换动态链接表里的函数地址
xHook
Inline Hook
在函数开头写一条跳转指令
HookZz / Whale
Engine-level Hook
在 CPU 模拟器层拦截指令执行
CodeHook / BlockHook
三种 Hook 底层技术对比

不归在这三类里的两个特殊 HookSystemPropertyHook 用的是 HookListener 链(在 dlsym 解析符号时把目标函数重定向到 SVC handler,比 PLT 更早一层);FunctionCallListener 是 Debugger 内部基于 BL/BLR 指令钩子实现的——两者都属于"unidbg 内部 instrumentation",不是真机上能复现的传统 hook 技术。后面框架介绍里会单独讲清楚。

在真机上做 Hook,你得先考虑 SELinux 权限、cache 刷新、线程安全、同一函数不能被多个 Hook 重复注册..。一堆工程问题。

在 Unidbg 里,这些问题全部消失。因为 Unidbg 就是执行引擎本身 —— 它随时知道每条指令在哪里执行、每个函数在哪里被调用。Hook 只是“在合适的时机通知你一声”,没有 cache 一致性问题,没有权限问题,没有竞争问题。

这就是为什么 Unidbg 里可以同时内置六种不同层级的 Hook 框架,各司其职。


六种 Hook 框架的抽象层次

从高到低:

六种 Hook 框架的抽象层次

记住这个层次感比记命令重要:

  • 越往上,声明式 越强,代码越少,适用场景越窄
  • 越往下,命令式 越强,灵活性越大,但代码量和出错概率也变大

选型的金科玉律从上往下选,找到能完成任务的最高层级。不要直接上 CodeHook,也不要一上来就写 Inline Hook.


框架 1: FunctionCallListener - 只观察,不改变

定位:监控 JNI 函数被调用的时机和参数。

适用场景:"我只想知道这个 SO 里谁调用了 CallObjectMethodV,调用的是 Java 的哪个方法,传了什么参数"。纯观察,不打算改。

vm.setJni(new AbstractJni() {// AbstractJni 的重写中...});// FunctionCallListener 不在 Emulator / SyscallHandler 上, 而在 Debugger 上// 拿 Debugger 的姿势是 emulator.attach()Debugger debugger = emulator.attach();// 两种范围:// - traceFunctionCall(listener)         全局, 所有 module 的 BL 都拦// - traceFunctionCall(module, listener) 限定在指定 module 范围内debugger.traceFunctionCall(new FunctionCallListener() {@OverridepublicvoidonCall(Emulator<?> emulator, long callerAddress, long functionAddress){        System.out.println("call from " + Long.toHexString(callerAddress)                + " -> " + Long.toHexString(functionAddress));    }@OverridepublicvoidpostCall(Emulator<?> emulator, long callerAddress, long functionAddress, Number[] args){// 可以在返回后看 x0 / args[0]    }});

注意:FunctionCallListener 是个“傍观者”,你不能修改任何行为。适合做日志面板,不适合做拦截器


框架 2: SystemPropertyHook - 专治系统属性

定位:专门拦截 __system_property_get / __system_property_find。这是 Android 里最常见的“设备指纹”来源之一。

适用场景:SO 里有这样的代码:

char buf[PROP_VALUE_MAX];__system_property_get("ro.build.fingerprint", buf);// 然后拿 buf 去对比黑名单

你想让 SO 认为自己在 "Pixel 5 / Android 13" 上。Unidbg 把这件事拆成了 SystemPropertyHook(注册成 HookListener 拦 __system_property_get / __system_property_find) + SystemPropertyProvider(你来决定每个 key 返回什么)两步:

SystemPropertyHook hook = new SystemPropertyHook(emulator);hook.setPropertyProvider(new SystemPropertyProvider() {@Overridepublic String getProperty(String key){switch (key) {case"ro.build.fingerprint":return"google/redfin/redfin:13/TQ3A.230705.001/...";case"ro.build.version.release":return"13";default:returnnull;  // 未命中的返回 null, 让 Unidbg 走默认逻辑        }    }});emulator.getMemory().addHookListener(hook);

构造器里强制传 Emulator 是因为 SystemPropertyHook 内部要拿 SvcMemory 注册 SVC 跳板;getProperty 是 SystemPropertyProvider 接口的方法,不是 SystemPropertyHook 自己的——这两个细节如果搞反了,IDE 直接报错。

相比用 xHook 或 HookZz 去 Hook __system_property_get 的好处:你不用自己解析 name、写结果、处理 buffer 长度。Unidbg 已经帮你做完了。

这是“业务粒度 Hook”的典型 —— 它抽象了属性读取这一个具体业务,让你只关心“返回什么值”。


框架 3: xHook (PLT Hook) - 拦截库函数调用

定位:拦截“某个 SO 调用 libc/其他 SO 的函数”。工作在 GOT/PLT 表这一层。

适用场景:SO 代码里调用了 getrusageioctlgettimeofday 这类 libc 函数,你想把它们的返回值改掉。

IxHook xHook = XHookImpl.getInstance(emulator);xHook.register("libtarget.so""getrusage",new ReplaceCallback() {@Overridepublic HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction){            RegisterContext ctx = emulator.getContext();int who = (int) ctx.getLongArg(0);            Pointer rusage = ctx.getPointerArg(1);// 构造假的 rusage 数据            rusage.setLong(0100);  // ru_utime.tv_secreturn HookStatus.LR(emulator, 0);  // 直接返回 0, 不调用原始函数        }    }, true);xHook.refresh();  // 必须调用, 才能真正生效

xHook 的三个关键点

  1. 粒度是“SO + 函数名”:你是在拦截“libtarget.so 调用 getrusage”,而不是全局拦截 getrusage。其他 SO 调用 getrusage 不受影响。这正是 PLT Hook 的本质。

  2. 第一参数是正则不是精确字符串:源码 IxHook.java:13 上明确叫 pathname_regex_str"libtarget.so" 因为是合法 regex 子串所以能精确匹配,但你也可以用 "lib.*\\.so" 一次拦多个 SO 的同一个函数,或者用 ".*" 做全局拦截。这是隐藏能力点,多数人不知道。

  3. xHook.refresh() 不能忘:xHook 的注册是批量应用的,必须调 refresh() 才会真正写入 GOT 表。我见过不止一个人 Hook 半天没生效,原因就是忘了 refresh.

忘记 refresh 的失败现场长什么样

这个坑我亲眼见过无数次,几乎每个刚上手的同事都会踩一遍,所以值得把“忘了 refresh” 的症状完整记录下来,下次你遇到就能秒识别。

假设你写了这样一段“看起来完全正确”的代码,想 hook getrusage:

IxHook xHook = XHookImpl.getInstance(emulator);xHook.register("libtarget.so""getrusage"new ReplaceCallback() {@Overridepublic HookStatus onCall(Emulator<?> emulator, HookContext ctx, long originFunction){        System.out.println("[hook] getrusage called!");return HookStatus.LR(emulator, 0);    }}, true);// 忘了调 xHook.refresh()DalvikModule dm = vm.loadLibrary(new File("libtarget.so"), true);dm.callJNI_OnLoad(emulator);

跑起来你会看到:

I/Hooks - Register getrusage success for libtarget.so[程序正常输出...](整个运行完都不会出现 "[hook] getrusage called!")

关键症状是“注册时 success,但回调从不触发”。日志里 Register xxx success 只说明 xHook 把你的回调登记到了内部表里,真正的 GOT 改写要等 refresh() 被调用时才发生。一旦你漏了这一步,SO 加载时走的是未经修改的 GOT,调用自然还是原始的 getrusage

补一行就好:

xHook.register("libtarget.so""getrusage", callback, true);xHook.refresh();  // 这一行!DalvikModule dm = vm.loadLibrary(...);

这个设计其实有它的道理——refresh 是一个昂贵的操作(要遍历 PLT/GOT 改写),如果每次 register 都自动 refresh,注册 10 个 hook 就要 refresh 10 次。把它做成显式调用,让用户一次性注册完再 refresh,性能好得多。但代价就是新手会漏。

社区的惯例是写一个 helper 函数把 register + refresh 封装起来,避免忘记:

publicstaticvoidregisterAndApply(IxHook xHook, String soName, String fn, ReplaceCallback cb){    xHook.register(soName, fn, cb, true);    xHook.refresh();}

看着冗余,但至少再也不会忘。

适用场景:所有对 libc / 其他第三方 SO 的函数拦截。几乎不适用于 SO 内部自己的函数。


框架 4: HookZz (Inline Hook) - 函数入口拦截

定位:在任意函数的入口处插入回调。既可以“观察参数”,也可以“替换整个函数”。

适用场景:你想 Hook SO 内部一个函数(比如 sub_1A34),在它被调用时看参数,根据参数决定“让它正常执行”还是“直接返回假值”。

IHookZz hookZz = HookZz.getInstance(emulator);hookZz.wrap(module.base + 0x1A34new WrapCallback<HookZzArm64RegisterContext>() {@OverridepublicvoidpreCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info){long arg0 = ctx.getXLong(0);        System.out.println("preCall x0 = " + arg0);// 可选: 在这里修改寄存器// ctx.setXLong(0, newValue);    }@OverridepublicvoidpostCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info){long retVal = ctx.getXLong(0);        System.out.println("postCall ret = " + retVal);// 可选: 在这里修改返回值// ctx.setXLong(0, 0);    }});

wrap vs replace 的区别

HookZz 提供两种模式:

  • wrap(addr, callback):在函数前后都插入回调,原始函数仍然执行。你可以观察 + 修改参数/返回值。
  • replace(addr, callback):你的回调完全替代原始函数。返回什么,函数就返回什么。原始代码一行都不执行。

用 wrap 调试和观察,用 replace 做替换。

HookZz wrap vs replace 调用流对比
hookZz.replace(module.base + 0x1A34new ReplaceCallback() {@Overridepublic HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction){// 不调用 originFunction, 直接返回 42return HookStatus.LR(emulator, 42);    }});

HookZz 和 xHook 的分界:如果你要 Hook 的是 SO 内部的函数,用 HookZz;如果是 调用其他 SO 的外部函数,用 xHook。两者管理不同层级的跳板。


框架 5: Whale (Inline Hook) - 暴力函数替换

定位:类似 HookZz 的 replace,但更直接,没有 preCall/postCall 的概念。

适用场景:你不需要观察原始参数,也不需要调用原始函数,就是想"从今天起 free 什么都不做"。

IWhale whale = Whale.getInstance(emulator);whale.inlineHookFunction(module.findSymbolByName("free"),new ReplaceCallback() {@Overridepublic HookStatus onCall(Emulator<?> emulator, long originFunction){// 直接返回, 不做任何事return HookStatus.LR(emulator, 0);        }    });

Whale 和 HookZz 怎么选

实话说,它们的能力几乎重叠。社区实践的经验:

  • 优先 HookZz,它更成熟,文档多,问题少。
  • Whale 作为后备:如果遇到 HookZz 在某个函数上工作异常(常见于函数开头有特殊指令),试试 Whale.

Tip:不要因为“我不需要观察参数”就选 Whale。 HookZz 的 replace 也能做到完全替换,代码量差不多,但稳定性更好。


框架 6: CodeHook / BlockHook - 指令级核武器

定位:在任意指令地址基本块边界插入回调。这是 Unidbg 最底层的 Hook,直接挂在 CPU 模拟器上。

适用场景:你想监控 SO 内部某条指令(不是函数)的执行,比如:

  • 在算法主循环的某条指令上,dump 当前寄存器状态
  • 在某个具体 PC 位置观察数据变化
  • 在函数的某个分支中间插入监控
// CodeHook: 每次执行某个地址范围的指令都触发emulator.getBackend().hook_add_new(new CodeHook() {@Overridepublicvoidhook(Backend backend, long address, int size, Object user){        System.out.println("executing instruction at 0x" + Long.toHexString(address));long x0 = backend.reg_read(Arm64Const.UC_ARM64_REG_X0).longValue();        System.out.println("  x0 = " + x0);    }}, module.base + 0x1B00module.base + 0x1B00null);  // 只对 0x1B00 这一条指令触发

CodeHook 的强大和代价

  • 强大:这是唯一能做到“指令粒度”拦截的 Hook。 Trace 本身就是用 CodeHook 实现的。
  • 代价:范围大一点性能就炸掉。每条指令都触发一次 JNI 回调,开销是巨大的。
  • 陷阱:CodeHook 仅在 Unicorn / Unicorn2 Backend 上可用;切到 Dynarmic 后**直接抛 UnsupportedOperationException**(见 DynarmicBackend.java 对 hook_add_new(CodeHook, ...) 的实现),不是"偶发不生效"而是完全不支持。要做指令级 hook 就只能用 Unicorn 系列。

使用纪律:

  1. 范围尽可能窄。不要做 “Hook 整个函数” 这种事,用 HookZz 代替。
  2. 回调里的代码尽量短。不要在里面打印大量内容,不要做 IO.
  3. 只在“非做不可”的时候用 —— 高层 Hook 全都不适用时。

选型决策表
Hook 框架选型决策树

把上面的内容压缩成一张表,贴在显示器旁边:

我想做什么
推荐框架
为什么
拦截 SO 对 libc.so 的某个函数调用
xHook
PLT Hook,粒度就是 libc 函数
拦截系统属性读取
SystemPropertyHook
业务抽象最好,代码最少
Hook SO 内部的函数,看参数 + 返回值
HookZz (wrap)
保留原始函数,前后观察
Hook SO 内部的函数,完全替换
HookZz (replace)
直接换,不执行原始代码
Hook 一个函数失败了,想换一个工具试试
Whale
HookZz 的备胎,换一个 Inline Hook 实现
观察 JNI 调用的时机和参数
FunctionCallListener
纯监控,不干预
在 SO 内部某条指令上做点事
CodeHook
唯一能做指令级拦截
监控整个函数的执行轨迹
不要用 CodeHook! 用 Trace
Trace 本身就是 CodeHook 封装,性能更好

三个常见的坑

坑 1:Hook 时机 —— 不同框架约束不一样

各框架的"必须在什么时候注册"不能一概而论,混淆会导致 Hook 不生效或生效不完整。一张对照表:

框架
时机约束
原因
xHook
必须在目标函数首次被调用之前注册 + refresh()
xHook 改写 PLT/GOT 表项,已经走过 PLT 的调用不会再查表
HookZz
同上:在目标函数首次被调用之前 patch
Inline hook 改函数入口字节,已经在执行的代码不会回头读改后的字节
Whale必须在 loadLibrary 之后
(要 findSymbolByName 找到目标) + 首次调用之前
同 HookZz,但额外需要目标 SO 已加载
CodeHook / SystemPropertyHook / FunctionCallListener
任意时机都行
直接挂在 backend / debugger / hook listener 链上,运行时动态匹配

实战中最常见的姿势

// 推荐姿势: loadLibrary 之前注册 xHook 的"基础消毒"xHook.register("libtarget.so""gettimeofday", fakeTimeCb, true);xHook.refresh();DalvikModule dm = vm.loadLibrary(new File("libtarget.so"), true);dm.callJNI_OnLoad(emulator);// 之后再做 Whale / HookZz 的 SO 内函数 hook (此时 module 已加载, 能 findSymbol)Whale.getInstance(emulator).inlineHookFunction(module.findSymbolByName("free"), freeCb);hookZz.replace(module.base + 0x1A34, envIntegrityCb);

常见误区:很多文章说"xHook 必须在 loadLibrary 之前",更准确的说法是"必须在目标函数被首次调用之前"。Unidbg 自带测试 JniDispatch64.java 里 xHook 是在 loadLibrary + callJNI_OnLoad 之后注册的,照样工作 —— 因为 OnLoad 期间没调那个 hook 目标函数。但实战里**JNI_OnLoad 经常会调 libc 函数**(如初始化时间戳、读 system property),所以保守做法是 xHook 放最前面。

Whale 反而必须在 loadLibrary 之后,因为要先 findSymbolByName 拿到目标函数符号 —— 这跟 xHook 时机相反,新手容易搞混。

坑 2:多个框架 Hook 同一函数的行为

假设你同时用 xHook 和 HookZz 去 Hook malloc,会发生什么?

答案:取决于谁后生效。通常后注册的覆盖前注册的。不要依赖这个行为,因为它在不同版本的 Unidbg 里可能变化。

为什么不要混用:两个框架在改不同的地方

设想一种常见的混用动机:一处用 xHook 做“统计所有 malloc 调用次数”(审计用途),另一处用 HookZz 做“拦截超过 1MB 的大 malloc,返回 NULL 模拟 OOM”(故障注入用途)。两个 hook 单独跑都对,一起跑就开始有奇怪问题——计数对不上、OOM 偶发触发、栈回溯偶尔崩。

根因在于两个框架改的不是同一个位置:

  • xHook 改的是 PLT/GOT:拦截的是“SO 内部调用 malloc 这个外部符号”的入口,被 hook 的对象是调用方那一侧
  • HookZz 改的是 malloc 函数头:在 libc 真实的 malloc 头部写跳转,被 hook 的对象是被调方那一侧

两边各自对“调用链”的假设不一样:xHook 的 trampoline 假设跳过去之后调用的是原始 malloc 头;HookZz 的 trampoline 假设进来时是从正常调用点过来的。一旦叠加,两个 trampoline 之间对寄存器保存(尤其是 lr)、对原始指令备份的假设就可能错位,组合行为变成不可预测。

这类问题不属于“哪个框架有 bug”,而是两个 hook 框架对“函数调用”的建模不一致:xHook 建模的是“谁在调”,HookZz 建模的是“谁被调”。同时生效就像在同一段路上同时铺两套红绿灯,结果取决于二者的安装顺序和触发顺序,没法稳定。

xHook 改 caller 侧 PLT;HookZz 改 callee 侧函数头

最佳实践一个函数只用一个 Hook 框架。如果需要多级 Hook(比如既要统计又要拦截),在同一个 Hook 回调内部自己组合逻辑:

// 坏示范: 两个框架各hook一个目的xHook.register("libtarget.so""malloc", countingCb, true);hookZz.wrap(mallocAddr, oomInjectionCb);// 好示范: 一个 Hook 同时做两件事hookZz.wrap(mallocAddr, new WrapCallback<...>() {@OverridepublicvoidpreCall(...){        counter.incrementAndGet();  // 统计long size = ctx.getXLong(0);if (size > 1024 * 1024) {            ctx.setXLong(00);     // OOM 注入// 或用 replace + HookStatus.LR 直接返回 NULL        }    }});

坑 3: Backend 限制

Hook 类型
Unicorn/Unicorn2
Dynarmic
FunctionCallListener
OK
OK
SystemPropertyHook
OK
OK
xHook
OK
OK
HookZz
OK
OK
Whale
OK
OK
CodeHook / BlockHook
OK
不支持

如果你用了 CodeHook,必须确保 Backend 是 Unicorn / Unicorn2. Dynarmic 虽然快,但没法在指令粒度上打断。


一个典型的选型走样案例

设想一个常见的反检测目标,要对付的样本有三个绕过点:

  • SO 会调用 gettimeofday 三次,然后对比时间差。模拟器上每次返回一样,直接被识别。
  • SO 会读 ro.build.fingerprint 并和黑名单匹配。
  • SO 里有个 check_env_integrity() 函数返回 1 表示“检测到异常”,希望让它固定返回 0.

第一版设计(新手陷阱):

按"我都不知道用啥就先上 CodeHook"的思路,在 SO 全段范围下一个 CodeHook,按 PC 分发到每个目标地址。代码很容易膨胀到 200~300 行,跑起来贼慢,每条指令都走一遍回调。

具体坏在哪里?第一版代码的骨架是这样:

// 反面教材: 用 CodeHook 处理所有事emulator.getBackend().hook_add_new(new CodeHook() {@Overridepublicvoidhook(Backend backend, long address, int size, Object user){long pc = address;// 针对每个敏感地址做判断if (pc == timeofdayCallSite1 || pc == timeofdayCallSite2 || pc == timeofdayCallSite3) {// 改 x0 把 gettimeofday 返回值做手脚            ...        } elseif (pc == fingerprintReadSite) {// 改 x0 指向伪造的字符串            ...        } elseif (pc == envIntegrityReturnSite) {// 改 x0 = 0 让 check_env_integrity 返回 0            backend.reg_write(Arm64Const.UC_ARM64_REG_X0, 0);        }// ... 还有其他 10 来个分支    }}, module.base, module.base + module.size, null);

问题很明显:

  1. 每条指令都进回调——在 module.base 到 module.base + module.size 的全量 hook,意味着 SO 里每一条指令都要进 Java 层检查 pc 是不是自己关心的那几个地址,这个 JNI 开销是灾难级的,慢 50-100 倍。
  2. 分支地狱——十几个 if/else 挤在一个回调里,加一个需求就得改这个函数,代码腐烂极快。
  3. 地址硬编码脆弱——SO 一旦升级,所有 pc == xxx 都要重新对,维护成本爆炸。
CodeHook 一锅端 vs 三种 Hook 分层

第二版设计(按层级选):

  • gettimeofday → xHook(libc 函数)—— 二十来行
  • ro.build.fingerprint → SystemPropertyHook(业务层抽象)—— 十来行
  • check_env_integrity() → HookZz.replace(SO 内部函数)—— 十来行

总量降到几十行,跑起来速度和没 Hook 一样,效果完全一致:

// 正面教材: 每种需求用最合适的框架// gettimeofday -> xHook (libc 层)xHook.register("libtarget.so""gettimeofday"new FakeTimeCallback(), true);xHook.refresh();// ro.build.fingerprint -> SystemPropertyHook (业务层)SystemPropertyHook propHook = new SystemPropertyHook(emulator);propHook.setPropertyProvider(new SystemPropertyProvider() {@Overridepublic String getProperty(String key){if ("ro.build.fingerprint".equals(key)) {return"google/redfin/redfin:13/TQ3A.230705.001/...";        }returnnull;    }});emulator.getMemory().addHookListener(propHook);// check_env_integrity -> HookZz.replace (SO 内部)hookZz.replace(module.base + 0x1A34new ReplaceCallback() {@Overridepublic HookStatus onCall(Emulator<?> emulator, long originFunction){return HookStatus.LR(emulator, 0);  // 直接让函数返回 0    }});

注意 ReplaceCallback 是抽象类不是函数式接口,不能用 lambda 写,必须用匿名内部类——这是新手在 IDE 里第二个最容易栽的坑。

代码量从几百行的 CodeHook 分支地狱压到几十行,运行速度回到“几乎无 hook”的水平,还附带一个隐性好处:可读性暴涨。新同事接手时看第二版,一眼就知道每个 hook 解决什么问题;看第一版则要读完整个分支地狱才能理解意图。

这就是层级选型的威力 —— 同样的功能,代码量差一个数量级,性能差几十倍,可维护性更是云泥之别。


HookZz ctx 范式:算法分步 hook 的工业级写法

层级选型告诉你用哪个 Hook 框架,但怎么用 HookZz 的 ctx 参数才是分析师每天打交道的细节。下面用抖音 TTEncrypt 算法的真实样本(AwemeTTEncrypt.java)说明一种"分步 hook + ctx push/pop 配对"的范式——一个完整的算法被拆成 4 个 Hook,每个 Hook 都有对称的 preCall / postCall

// 给 AES 函数 (libEncryptor.so:0x3640) 挂 hook, 同时 dump 入参和出参// 函数名按"hookSub<offset>"约定, 方便和 IDA 反汇编的偏移直接对照publicvoidhookSub3640(){    IHookZz hookZz = HookZz.getInstance(emulator);    hookZz.wrap(module.base + 0x3640 + 1new WrapCallback<HookZzArm32RegisterContext>() {@OverridepublicvoidpreCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info){// 入参: r0 = 输入指针, r1 = 输出指针            Pointer input1 = ctx.getPointerArg(0);            Inspector.inspect(input1.getByteArray(00x100), "AES 输入");            Pointer input2 = ctx.getPointerArg(1);            Inspector.inspect(input2.getByteArray(00x100), "AES 输出指针 (此时为空)");// 关键: 把指针 push 到 ctx 栈上, 等 postCall 再读            ctx.push(input2);            ctx.push(input1);        }@OverridepublicvoidpostCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info){// 关键: 弹出顺序和 push 相反 (LIFO)            Pointer output1 = ctx.pop();            Pointer output2 = ctx.pop();// 此时输出指针已经被 SO 填充, dump 出来就是 AES 加密结果            Inspector.inspect(output1.getByteArray(00x100), "AES 输入(再确认)");            Inspector.inspect(output2.getByteArray(00x100), "AES 输出(已填充)");        }    });}

整个 TTEncrypt 算法被拆成 4 个独立的 Hook,每个对应一个算法步骤:

Hook 函数
偏移
算法步骤
用途
hookSub3BB8+0x3BB8
主入口
dump 完整明文 + 看 SO 内部状态布局
hookSub3640+0x3640
AES 单块加密
每轮 AES 都触发, dump 密钥 + 输入 + 输出
hookSub8BAC+0x8BAC
SHA512
dump SHA512 输入 + 输出(用于推导 AES 密钥)
hookSub8214+0x8214
字节级 XOR
看异或链中间状态

ctx push/pop 的核心价值:HookZz 的 preCall 和 postCall 是两个独立的回调,它们之间默认不共享变量。如果你想在 postCall 里看 preCall 时拿到的指针(比如"输入参数指向的内存,函数返回后可能已经被填充了输出"),就必须用 ctx 栈传递。这是 HookZz 的线程安全设计——每个 Hook 实例自己维护一个 ctx 栈,避免你自己写 ConcurrentHashMap。

几个关键约束

  1. push 顺序 = 出栈顺序的反序(LIFO)。先 push 的最后 pop。
  2. preCall push 几次, postCall 必须 pop 几次——不配对会泄漏 ctx 栈,长时间跑会累积。
  3. +1 后缀module.base + 0x3640 + 1)—— ARM32 Thumb 模式标志,必须加;ARM64 不需要这个 +1。
  4. Inspector.inspect(bytes, label) 是 Unidbg 自带的工具,按 16 字节一行打印 hex+ASCII,比手写 bytesToHex 强得多。

为什么不用 replace 而用 wrap:分析阶段你想"观察"算法的中间状态,不想替换它的逻辑。等观察清楚了再用 Python 复刻整个算法。这是第十八章「算法还原」的工作流——wrap 是观察工具,replace 是替换工具,两者用途完全不同。


总结

问题
答案
Hook 的本质是什么
在不修改二进制的前提下,插入自己的逻辑
Unidbg 的 Hook 比真机强在哪
没有权限、cache、线程安全问题
选型的金科玉律
从高层往低层选,找到能完成任务的最高层级
xHook 和 HookZz 的分界
xHook 拦 SO 外的库函数,HookZz 拦 SO 内的函数
HookZz 和 Whale 怎么选
默认 HookZz,失败时换 Whale
CodeHook 什么时候用
高层全都不适用时,最后的核武器
最常见的坑
Hook 时机太晚 / 忘记 xHook.refresh() / 用 CodeHook 做大范围 Hook

一句话原则不要拿核武器解决小问题。每一个 Hook 需求,都应该先问自己:“我能用最高层的框架解决吗?” 答案是 yes 的话,就选那个。答案是 no,再往下走一层。能用 SystemPropertyHook 一行代码搞定的,绝不用 CodeHook 写一百行。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-30 03:03:27 HTTP/2.0 GET : https://67808.cn/a/484840.html
  2. 运行时间 : 0.099141s [ 吞吐率:10.09req/s ] 内存消耗:4,848.27kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=77895bfb850a3233693ea7d4e20cf6c5
  1. /yingpanguazai/ssd/ssd1/www/no.67808.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/no.67808.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/no.67808.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/no.67808.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/no.67808.cn/runtime/temp/6df755f970a38e704c5414acbc6e8bcd.php ( 12.06 KB )
  140. /yingpanguazai/ssd/ssd1/www/no.67808.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000567s ] mysql:host=127.0.0.1;port=3306;dbname=no_67808;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000967s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000353s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000285s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000734s ]
  6. SELECT * FROM `set` [ RunTime:0.000232s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000708s ]
  8. SELECT * FROM `article` WHERE `id` = 484840 LIMIT 1 [ RunTime:0.000615s ]
  9. UPDATE `article` SET `lasttime` = 1777489407 WHERE `id` = 484840 [ RunTime:0.018246s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 65 LIMIT 1 [ RunTime:0.000490s ]
  11. SELECT * FROM `article` WHERE `id` < 484840 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000709s ]
  12. SELECT * FROM `article` WHERE `id` > 484840 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000587s ]
  13. SELECT * FROM `article` WHERE `id` < 484840 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001064s ]
  14. SELECT * FROM `article` WHERE `id` < 484840 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.003455s ]
  15. SELECT * FROM `article` WHERE `id` < 484840 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001568s ]
0.100791s