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
右键菜单里那个熟悉的"注入DLL"选项,升级之后找不到了?你不是一个人。SystemInformer 的 DLL注入能力一直在代码库里挪窝,翻旧教程只会越看越晕。这篇不讲故事,直接把整条链路拆成三层——入口、通信、内核——看完你在任何版本里都能顺着文件路径快速定位。
入口找不到了?先把链路拆开
先说结论:SystemInformer 的 DLL注入主体活在用户态,它只是把"把路径搬进对方内存、借对方的 LoadLibraryW 跑起来"这套活编排好;真正需要内核出手的,是操作受保护进程时的特权内存读写。把这件事按"谁动手"分成三层,你就不会迷路。📌
SystemInformer DLL注入三层架构全景
下面这张图是全文地图,后文按层展开,每个节点对应一个具体文件。
三层职责一句话讲清:入口层负责"发起注入",通信层负责"把普通 API 变成特权操作",内核驱动负责"替你在受保护进程里动内存"。三者是串联关系,不是并列。
逐层拆解注入链路
界面层——你点的那一下到底调了什么
入口就在 phlib/nativethread.c 的PhLoadDllProcess(远程线程版)和PhLoadDllProcessApcThread(APC 版)。你点的那一下,最终落到这两个函数。核心三步如下:
// 解析目标进程自己 kernel32 的 LoadLibraryW 地址 PhGetProcedureAddressRemote(ProcessHandle, &kernel32, "LoadLibraryW", &loadLibraryW, NULL); // 把 DLL 路径(宽字符)写进目标进程内存 PhWriteVirtualMemory(ProcessHandle, fileNameBaseAddress, FileName->Buffer, len, NULL); // 以 LoadLibraryW 为入口、路径为参数,远程拉起一个线程 PhCreateUserThread(ProcessHandle, NULL, THREAD_ALL_ACCESS, 0,0,0,0, loadLibraryW, fileNameBaseAddress, &threadHandle, NULL);说白了就是经典 LoadLibraryW 远程线程套路:地址、路径、线程一个不少;APC 版则把"拉线程"换成"往对方线程队列塞 APC",更不易被察觉。旧版CreateRemoteThread的痕迹还躺在 SystemInformer/heapinfo.c(已注释),仅供对照。界面层只负责把参数打包传下去,真正的活是下一层干的。
通信层——用户态和内核之间怎么传话
别被一堆 KPH 缩写吓到,这层其实就干一件事:把一次系统调用封装成结构体,走命名端口发给驱动。发送逻辑在 phlib/kph.c(KphSendMessage+KPH_PORT_NAME),报文结构在 kphlib/include/kphmsgdefs.h。以内存读为例:
typedef struct _KPHM_READ_VIRTUAL_MEMORY { NTSTATUS Status; // 返回码, 调用方据此判断成败 HANDLE ProcessHandle; // 操作哪个进程 PVOID BaseAddress; // 读哪段地址 PVOID Buffer; // 结果落到哪 SIZE_T BufferSize; // 读多少 PSIZE_T NumberOfBytesRead;// 实际读到多少 } KPHM_READ_VIRTUAL_MEMORY, *PKPHM_READ_VIRTUAL_MEMORY;这个结构体本质上就是个"消息头+参数",写内存版KPHM_WRITE_VIRTUAL_MEMORY字段同理。普通进程走系统自带 API 就够;一旦目标是受保护进程,PhWriteVirtualMemory会自动改走这条端口,把活转给内核。消息打包好了,但谁来执行?看内核层。
内核层——驱动里真正动手的地方
内核侧是 KSystemInformer/ 驱动;它调用 KSystemInformer/ksidll.c 提供的特权原语(安全卸载 APC、工作项、DPC、最小系统进程)。ksidll.def 的导出表就是这层的"手":
LIBRARY ksi.dll EXPORTS KsiInitialize KsiInitializeApc KsiInsertQueueApc KsiInitializeWorkItem KsiQueueWorkItem KsiInitializeDpc KsiInitializeSystemProcess这些导出不是注入 API 本身,而是让驱动能"安全地在系统里动手"的底层积木:比如保证驱动卸载时未完成的 APC 仍能收尾。注入时受保护进程的内存读写,就是由这一层代为执行。🔍
功能点文件位置速查表
| 功能点 | 所在模块 | 关键文件 | 备注 |
|---|---|---|---|
| 注入入口(远程线程/APC) | 用户态 phlib | phlib/nativethread.c | PhLoadDllProcess / ApcThread |
| 端口消息发送 | 用户态 phlib | phlib/kph.c | KphSendMessage、KPH_PORT_NAME |
| 消息结构体定义 | kphlib | kphlib/include/kphmsgdefs.h | KPHM_READ/WRITE_VIRTUAL_MEMORY |
| 特权内存/进程操作 | 内核驱动 | KSystemInformer/ | 驱动内处理 KPH 消息 |
| 内核原语(APC/DPC/工作项) | 内核驱动 | KSystemInformer/ksidll.c | 见 ksidll.def 导出表 |
| 旧版 CreateRemoteThread 痕迹 | 主程序 | SystemInformer/heapinfo.c | 已注释,仅供对照 |
找不到入口先查这张表,比翻代码快。
动手跑一遍注入
- 启动 SystemInformer,在进程列表里选中目标进程。
- 打开该进程的操作入口(上下文菜单/动作),选择 DLL 注入。
- 选中要注入的 .dll 文件并确认。
- 触发后走
PhLoadDllProcess:解析地址 → 写路径 → 拉远程线程 → 等待返回。 - 若目标受保护,内存读写会自动改走 KPH 端口到内核驱动执行。
如果界面和文中对不上,回到第四节查表。
边界与坑
主要面向现代 Windows(x64/x86);操作受保护进程需要管理员/提升权限。最常见的坑:目标 32/64 位或运行时库地址不匹配导致 LoadLibraryW 解析失败,或注入线程等待超时卡住。要动手改的话,先看 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),仅供参考