SystemInformer DLL注入实现位置、原理与验证完整指南
【免费下载链接】systeminformerA free, powerful, multi-purpose tool that helps you monitor system resources, debug software and detect malware. Brought to you by Winsider Seminars & Solutions, Inc. @ https://windows-internals.com项目地址: https://gitcode.com/GitHub_Trending/sy/systeminformer
升级后右键菜单里找不到的那个"注入"入口,其实还在,只是不再叫这个名字。来自 Process Hacker 时代的 SystemInformer 把 DLL注入这类操作拆进了四层代码:内核驱动、内核消息层、用户态封装层和界面插件。这份指南直接给出每层的文件位置、请求如何跨边界传递,以及一套可执行的验证流程,帮你在十五分钟内确认注入链路是否完整。
快速定位
先看结论:四个模块、一条通道,职责边界如下。
| 功能入口 | 所在文件/模块 | 一句话职责 |
|---|---|---|
| 注入相关消息类型定义 | kphlib/include/kphmsg.h | 枚举内核通道支持的消息,如KphMsgReadVirtualMemory |
| 内核驱动消息处理 | KSystemInformer/ | 内核侧收消息、执行跨进程内存读写与线程相关操作 |
| 用户态通道收发 | phlib/kphcomms.c | 校验消息头后经 minifilter 端口(用户态与内核的命名通信端口)收发 |
| 用户态 API 封装 | phlib/kph.c | 提供KphReadVirtualMemory等 NTSTATUS 风格接口 |
| 界面菜单注册 | plugins/ExtendedTools/main.c | 向主程序菜单插入"工具 → System"子菜单,用户可见入口 |
分层拆解
内核通信层:一条消息如何被定义
kphlib 是内核与用户态共用的消息定义库,同一份代码分别编进驱动和主程序,保证两端对消息布局的理解一致。消息类型的枚举在kphlib/include/kphmsg.h中,跨进程内存操作和线程生命周期钩子都在这里:
// kphlib/include/kphmsg.h KphMsgReadVirtualMemory, ... KphMsgHandlePreCreateThread, KphMsgHandlePostCreateThread,驱动侧的入口清单同样可查。KSystemInformer/ksidll.def列出 ksi.dll 的导出符号,包括KsiInitialize、KsiQueueWorkItem、KsiSystemProcess等。值得注意的是,这里没有独立的"注入"导出——内核侧只暴露基础设施,具体动作全部走消息,这比按动作逐个导出的老式设计更容易审计。
用户态封装层:谁负责把消息送进内核
答案在 phlib 的两个文件里。phlib/kphcomms.c的KphCommsSendMessage是唯一的发送点,先做消息头校验,再交给PhFilterSendMessage:
// phlib/kphcomms.c if (!KphpCommsFltPortHandle) return STATUS_FLT_NOT_INITIALIZED; if (!NT_SUCCESS(status = KphMsgValidate(Message))) return status; status = PhFilterSendMessage( KphpCommsFltPortHandle, Message, ...上层应用则面向phlib/kph.c里的函数编程,如KphReadVirtualMemory、KphOpenProcess,它们把消息构造和端口调用都藏起来。这条路线替代了早期的用户态组合:在SystemInformer/heapinfo.c中还能看到被整体注释掉的CreateRemoteThread调用(目标进程里起远程线程、以RtlDestroyHeap为入口),这正是旧做法的遗迹。用户态远程线程依赖目标进程状态良好,且行为模式容易被现代防护软件识别,迁到内核通道后由驱动统一执行,行为特征也更收敛。
// SystemInformer/heapinfo.c(已注释的历史实现) // if (!(threadHandle = CreateRemoteThread( // processHandle, // NULL, // 0, // PhGetModuleProcAddress(L"ntdll.dll", "RtlDestroyHeap"), // HeapHandle,插件层:用户在界面上摸到的入口
ExtendedTools 插件在plugins/ExtendedTools/main.c中注册了四个菜单回调,其中ProcessMenuInitializingCallback负责进程右键菜单,MainMenuInitializingCallback则向主菜单的"工具"页插入"System"子菜单。当前版本没有独立的"注入 DLL"菜单项,能力以"远程内存读写 + 线程操作消息"的零件形式存在,界面层的动作由插件按需组合。
动手验证
按下面四步走一遍,链路是否完好就清楚了。
- 用 Windows 驱动签名流程构建并加载内核驱动(签名清单见
KSystemInformer/KSystemInformer.inf)。 - 启动 SystemInformer,确认顶部"工具"菜单下出现"System"子菜单——这是 ExtendedTools 插件加载成功的直接证据。
- 在进程列表选中目标进程,右键打开进程菜单,确认内存相关的查询与编辑项可用。
- 调用远程内存读取接口读目标进程一个已知模块的头部,比对返回内容与磁盘 PE 一致。
预期结果:第 4 步返回的字节序列与本地文件比对无差异,说明消息从用户态经 minifilter 端口进入驱动、再原路返回的闭环是通的。
失败情形:若任意接口返回STATUS_FLT_NOT_INITIALIZED,说明KphpCommsFltPortHandle为空,即驱动未加载或端口未建立。先检查驱动服务状态,再看phlib/kphcomms.c中KphCommsStart的返回码;端口建立成功后用KphCommsIsConnected复测。
常见问题
为什么右键菜单里找不到"注入 DLL"?这一版本没有该独立菜单项,能力被拆成内存读写和线程操作两类消息,界面入口是工具菜单下由 ExtendedTools 插件注册的 System 子菜单。
ksidll.def 里为什么没有 KsiSendMessage 之类的导出?导出的Ksi符号只是内核基础设施(APC、DPC、工作项等)。真正的"用户态→驱动"请求不走这些导出,而是由KphCommsSendMessage经 minifilter 端口发送,两者是不同通道。
CreateRemoteThread 的实现彻底删了吗?没有,SystemInformer/heapinfo.c保留了整段注释代码作为历史痕迹,但当前构建不再执行。相关逻辑已迁移到内核通道,由驱动侧统一完成。
如何确认通信通道已建立?调用KphCommsIsConnected(phlib/kphcomms.c),返回 TRUE 即端口就绪;返回 FALSE 时按"动手验证"一节排查驱动服务。
远程内存读取的接口签名在哪看?KphReadVirtualMemory的实现在phlib/kph.c,对应的消息布局在kphlib/include/kphmsg.h的KPHM_READ_VIRTUAL_MEMORY联合体中,两处对照阅读最清楚。
延伸阅读
- KSystemInformer/:内核驱动源码与签名清单
- kphlib/:内核/用户态共用消息定义库
- phlib/:用户态支持库,含通道收发与 API 封装
- plugins/ExtendedTools/:提供工具菜单界面的插件
- HACKING.md:构建与开发环境说明
- CONTRIBUTING.md:贡献流程与规范
【免费下载链接】systeminformerA free, powerful, multi-purpose tool that helps you monitor system resources, debug software and detect malware. Brought to you by Winsider Seminars & Solutions, Inc. @ https://windows-internals.com项目地址: https://gitcode.com/GitHub_Trending/sy/systeminformer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考