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
很多人搜"SystemInformer DLL 注入",第一个问题其实是同一个:入口到底在哪,底层到底怎么跑的。先把结论摆出来:这个仓库并没有一个独立的一键"注入 DLL"对话框,它把注入这件事拆成了三层——内核驱动干脏活、通信库做协议、界面层提供操作面。本文就沿着"进程内存写入"这条线,把三层各自的路径和职责讲清楚。
先看地图:注入链路按三层拆开
先建立空间感,整条链路长这样:
| 层 | 职责 | 关键源码位置 |
|---|---|---|
| 内核驱动层 | 执行跨进程内存读写、插入内核 APC / 工作项等特权操作 | KSystemInformer/、kphlib/ |
| 用户态通信封装层 | 连接内核服务,编解码 KPH 消息,向上提供NTSTATUS风格接口 | phlib/kph.c、phlib/include/kphuser.h |
| 界面层 | 进程列表、内存页与内存编辑器,承担手工"写"操作 | SystemInformer/memlist.c、SystemInformer/memedit.c、SystemInformer/memmod.c |
💡 注意方向:请求永远从上往下走,驱动只暴露原语,不关心你要拿原语干什么。
内核层:怎么读 KSystemInformer 的导出表
导出表才是注入原语的真身
看内核能力,最直接的入口是KSystemInformer/ksidll.def,这是驱动的用户态导出表,摘录如下:
LIBRARY ksi.dll EXPORTS KsiInitializeApc KsiInsertQueueApc KsiRemoveQueueApc KsiInitializeWorkItem KsiQueueWorkItem KsiInitializeDpc KsiInitializeThreadedDpc KsiInitializeSystemProcess简单说就是:内核 APC(异步过程调用,让目标线程在内核态执行你指定的函数)和工作项(内核态的延迟执行队列)两套原语,外加 DPC 定时器类能力。要做一个"内核态 LoadLibrary"式注入,KsiInsertQueueApc这类导出就是最核心的积木。
为什么把内存读写下沉到内核
两个原因。第一,ReadProcessMemory/WriteProcessMemory这套用户态 API 受对象权限和完整性级别约束,碰到受保护进程就无解;由驱动代读代写,权限判定发生在内核内部。第二,内核态注入原语(APC/工作项)本身只能在环 0 调度,用户态根本碰不到。所以KSystemInformer/里围绕进程、线程、对象做了一整组 informer(进程/线程/文件等事件通知),注入相关能力只是其中一部分。
通信层:Kph 函数族把端口细节藏了起来
上层调用者拿到的是什么
phlib/kph.c负责连接名为\KSystemInformer的 ALPC 通信端口(端口名定义在phlib/include/kphuser.h),消息结构由kphlib/kphmsg.c等文件约定。对上层来说,这一切都被封装成普通 C 函数,比如跨进程读内存:
// phlib/include/kphuser.h PHLIBAPI NTSTATUS NTAPI KphReadVirtualMemory( _In_opt_ HANDLE ProcessHandle, // 可为空,空则读本进程 _In_ PVOID BaseAddress, _Out_writes_bytes_(BufferSize) PVOID Buffer, _In_ SIZE_T BufferSize, _Out_opt_ PSIZE_T NumberOfBytesRead );同一头文件里还有KphOpenProcess(内核态打开任意访问权限的进程句柄)、KphTerminateProcess、KphCreateMessage(构造发给驱动的消息)等。也就是说,界面代码不需要知道端口在哪、消息怎么打包,拿到NTSTATUS和缓冲区就完事。
界面层:"注入 DLL"菜单项去了哪里
内存页是手工注入的主战场
直白点:翻遍plugins/目录,当前仓库里并没有一个叫"注入 DLL"的图形化插件入口,想注入得自己用下面这些积木拼。真正在界面上能落地的操作路径是进程属性窗的内存页:SystemInformer/memlist.c列出目标进程的区域,SystemInformer/memedit.c是十六进制编辑器,memmod.c、memprot.c分别负责改属性/权限。把 DLL 字节或一段 IAT 补丁写进目标进程,靠的就是这条"内存写入"链路。
历史痕迹:被注释的 CreateRemoteThread
SystemInformer/heapinfo.c里还留着一段整块注释掉的代码(第 1225 行附近),能看出项目当年走的是经典远程线程路线:
// SystemInformer/heapinfo.c(整块已被注释) // if (!(threadHandle = CreateRemoteThread( // processHandle, // NULL, // 0, // PhGetModuleProcAddress(L"ntdll.dll", "RtlDestroyHeap"), // HeapHandle, // 0, // NULL // )))这段是给"销毁进程堆"功能用的,用CreateRemoteThread+ntdll!RtlDestroyHeap组合。它被注释掉、能力下沉到驱动,正说明路线从用户态 API 换到了内核服务(具体演进过程以当前仓库版本为准)。
五步上手:从启动到内存写入生效
- 以管理员身份启动 SystemInformer 主程序(加载内核服务需要管理员权限,
KsiLoadUnloadService就定义在phlib/include/kphuser.h)。 - 在程序内启动 KSystemInformer 内核服务,相关支撑代码在
SystemInformer/ksisup.c与SystemInformer/phsvc/(服务客户端/服务端)。 - 在进程列表双击目标进程,打开属性窗口。
- 切到内存页,双击目标内存区域进入内存编辑器(
SystemInformer/memedit.c)。 - 写入目标字节后回到内存列表确认内容变化,写入即完成。
⚠️ 第 4、5 步的菜单层级不同版本可能微调,以当前仓库版本为准。
常见疑问与使用注意
Q1:为什么找不到一键注入 DLL 的入口?仓库没有内置该对话框,它提供的是"内核 APC/工作项原语 + 内存读写"两块积木,完整的 LoadLibrary 注入流程(找线程、写字节、构造 APC)需要调用方自己编排。
Q2:驱动加载失败或被系统拦截怎么办?常见于未给管理员权限,或开启 HVCI 的 Windows 拒绝加载未获豁免的第三方驱动;仓库KSystemInformer/bin-signed/下有预签名产物可尝试。
Q3:32/64 位怎么匹配?写入的 DLL 或代码段必须与目标进程位数一致,往 64 位进程写 32 位模块地址直接就是无效指针。
Q4:碰受保护进程被拒绝?封装层提供了KphStripProtectedProcessMasks(见phlib/include/kphuser.h),由驱动侧剥离保护掩码;但用不用、对哪个进程用,属于高风险操作,务必只在自己的测试机上做。
Q5:权限最小化怎么把握?跨进程写入至少需要PROCESS_VM_WRITE级别访问,驱动路径则由内核按DesiredAccess判定,别默认请求PROCESS_ALL_ACCESS。
仓库内相关资源
- 驱动导出表:KSystemInformer/ksidll.def
- 用户态通信接口声明:phlib/include/kphuser.h
- 消息协议实现:kphlib/kphmsg.c
- 内存编辑器:SystemInformer/memedit.c
【免费下载链接】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),仅供参考