资讯动态

NtCall64源码解析(一):如何用6字节模式匹配在ntoskrnl中定位KiServiceTable——Windows x64系统调用模糊测试器入门

发布时间:2026/8/25 17:38:30 来源:尧图企业网站定制
NtCall64源码解析一如何用6字节模式匹配在ntoskrnl中定位KiServiceTable——Windows x64系统调用模糊测试器入门【免费下载链接】NtCall64Windows NT x64 syscall fuzzer项目地址: https://gitcode.com/gh_mirrors/nt/NtCall64NtCall64 是一个 Windows NT x64 系统调用syscall模糊测试器fuzzer它的任务是用海量随机参数暴力调用系统服务表中的每一个入口点从而挖出内核漏洞。而这一切的起点是在只读的 ntoskrnl.exe 镜像里找到KiServiceTable——这篇文章带你读懂 NtCall64 如何用短短 6 字节的字节码模式匹配完成这个寻宝过程。为什么服务表是整个工具的命门模糊测试 syscall 需要三样东西需要用途服务表地址KiServiceTable第 N 个 syscall 的函数入口就在这里条目总数KiServiceLimit知道要 fuzz 多少个系统调用栈参数表KiSystemCallStackArgumentTable判断每个 syscall 需要推几个参数这三个值在ntoskrnl中是私有符号——没有导出表可以直接GetProcAddress。NtCall64 因此走了一条经典的内核逆向路线特征码扫描 相对跳转解引用。核心实现位于Source/NtCall64/sup.c中的supFindKiServiceTable函数约 1279 行起。前置步骤以只读不可执行方式映射内核镜像定位服务表之前main.c的FuzzInitPhase2函数约 136 行起先通过supMapImageNoExecute把%SystemRoot%\system32\ntoskrnl.exe映射进自己的用户态进程用NtCreateSectionSEC_IMAGE_NO_EXECUTE创建节对象用NtMapViewOfSection以PAGE_READONLY映射 这一步很关键映射是只读且不可执行的NtCall64 只是读内核镜像来解析结构绝不会执行内核代码这是它能在用户态安全运行的前提。6字节魔数KiSystemService 的指纹sup.c中定义了这样一个模式约 1290 行const BYTE KiSystemServiceStartPattern[] { 0x45, 0x33, 0xC9, 0x44, 0x8B, 0x05 };拆开看这两条指令正是 64 位KiSystemService的开头微软编译器生成的固定序言字节反汇编含义45 33 C9xor ebp, ebp函数序言第一条指令44 8B 05mov r8, QWORD PTR [ripdisp32]RIP 相对寻址取 64 位常量选择它的理由很朴素足够短——6 字节扫描快误报概率低足够稳——xor ebp,ebp是现代 MSVC x64 函数几乎必然的开头且紧跟一条ripdisp32取指指令在KiSystemService入口处是长期稳定的结构。扫描前还要先锁定代码段注意 NtCall64 并不扫描整个镜像而是先遍历 PE 节表sup.c约 1301 行寻找名为PAGELK的节——ntoskrnl 的可执行代码节。找到后用RtlCompareMemory逐字节滑动比对这 6 个字节约 1325 行命中即得KiSystemService在节内的偏移。连续三跳从入口点解析出三张关键表找到入口点只是第一步。KiSystemService的开头紧接着三条 7 字节的 RIP 相对跳转指令分别指向三张表。supFindKiServiceTable约 1338 行起用同一套算术连跳三次目标地址 disp32 7 当前指令地址 7 该跳转指令自身长度每次解出地址后指针前进 7 字节处理下一条第几跳解析出的符号存入结构体1KiServiceLimitCountOfEntries2KiSystemCallStackArgumentTableStackArgumentTable3KiServiceTableServiceTable解析结果写入global.h约 58 行定义的RAW_SERVICE_TABLE结构体main.c在supFindKiServiceTable成功后就带着这张表进入FuzzRun开始正式 fuzz。对照组win32k 根本不需要模式匹配 用-win32k参数时NtCall64 改为 fuzz 图形子系统的影子 SSDT。有趣的是supFindW32pServiceTablesup.c约 1359 行完全不用特征码——win32k.sys 直接导出了W32pServiceLimit、W32pArgumentTable、W32pServiceTable三个符号通过supGetProcAddressEx在导出一节里二分查找一步到位即可。这个对比恰好说明设计取舍ntoskrnl 把服务表藏起来win32k 却大方导出所以同一工具对两套表用了两种定位策略。服务表如何驱动 fuzzing拿到表之后fuzz.c约 375 行起StackArgumentTable[sid] / 8得出该 syscall 的栈参数个数64 位下每参数 8 字节用fuzz_data.h中精心设计的参数值句柄模式、边界值、随机可识别值等填充循环syscall指令逐个轰击Source/badcalls.ini则用于拉黑会关机/挂起系统的危险调用如NtShutdownSystem本篇小结NtCall64 定位 KiServiceTable 的完整链路可以记为一句话只读映射 ntoskrnl.exe → 锁定 PAGELK 代码节 → 6 字节模式匹配 KiSystemService → 三连跳解析 Limit / 参数表 / 服务表。涉及的源码文件清单服务表定位核心Source/NtCall64/sup.csupFindKiServiceTable / supMapImageNoExecute初始化与调度Source/NtCall64/main.cFuzzInitPhase2数据结构定义Source/NtCall64/global.hRAW_SERVICE_TABLEfuzz 主循环Source/NtCall64/fuzz.c参数素材库Source/NtCall64/fuzz_data.h危险调用黑名单Source/badcalls.ini⚠️ 安全提示NtCall64 专为受控的实验室环境设计可能导致系统崩溃或数据丢失请勿在存有重要数据的生产机器上运行。下一篇将深入 fuzz 参数构造-h启发式模式与参数矩阵是怎么生成的。【免费下载链接】NtCall64Windows NT x64 syscall fuzzer项目地址: https://gitcode.com/gh_mirrors/nt/NtCall64创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价