大家好,本文讨论了ARK工具在XP/WIN7 32位在内核通过ActiveProcessLinks手动遍历进程的方法,文末贴了遍历进程和内核模块的代码。在下新手,不足之处多多包涵~
在进行进程附加读写操作之前,我们首先需要找到目标进程,传进程PID给读写函数。遍历系统中的所有进程是ARK工具的基础功能之一,用于:
下面看看遍历进程的方法,看雪上有些相关文章:
[原创]简单利用_CSR_PROCESS结构枚举出进程-软件逆向-看雪-安全社区|安全招聘|kanxue.com
[原创]驱动遍历系统进程-软件逆向-看雪-安全社区|安全招聘|kanxue.com
本文讲通过ActiveProcessLinks获取进程链表的方法
在Windows内核中,每个进程都对应一个EPROCESS结构体,所有活跃进程通过ActiveProcessLinks字段形成一个双向循环链表。
EPROCESS结构简化示意:
要遍历进程,我们需要:
找到入口点:获取当前进程的EPROCESS结构
遍历链表:通过ActiveProcessLinks访问其他进程,只要拿到当前进程在ActiveProcessLinks中的节点,我们就可以遍历列表拿到数据。
循环检测:当回到起始进程的节点时停止遍历
获取EPROCESS涉及了大量的结构体
硬件层面:
FS寄存器 → 指向当前处理器的KPCR
内核层面:
KPCR (处理器控制区域)
├── PrcbData → KPRCB (处理器控制块)
└── CurrentThread → ETHREAD (当前执行线程)
线程层面:
ETHREAD (执行线程)
├── ApcState → KAPC_STATE (APC状态)
│ └── Process → EPROCESS (所属进程)
└── ThreadsProcess → EPROCESS (直接指向所属进程)
进程层面:
EPROCESS (执行进程)
├── Pcb → KPROCESS (内核进程块)
├── ActiveProcessLinks → LIST_ENTRY (进程链表)
├── UniqueProcessId → 进程ID
├── InheritedFromUniqueProcessId → 父进程ID
├── ImageFileName[16] → 进程名
└── 其他进程相关信息
关注这条路径:FS → KPCR → KPRCB → ETHREAD → EPROCESS → 找链表遍历其他进程的EPROCESS
由于影响观感,截取了部分XP下的结构体贴在文末,建议在windbg中查看这些结构体进行学习,命令:
要拿EPROCESS就得计算这些结构体的偏移,然而windows各个版本的结构体是不同的,工作量不小,这里有几种方法:
1.人肉计算结构体偏移量,在驱动启动时RtlGetVersion(&versionInfo)获得当前windows版本然后设置对应的偏移量。我刚开始也是这样干的,文末有使用这种方式的代码
2.特征API: PsGetCuurentProcessId 、PsGetNextProcess直接拿链表头。缺陷:如果API被hook需要考虑被改jmp的情况,且如果需要的函数没有导出,定位不到函数入口点,需要利用api调用层级进行逐级特征定位。(真有人这么干吗0.0

看这个偏移[eax+0x1EC],Cid 可以拿到UniqueProcess和UniqueThread的指针


这里可以特征到链表头PsActiveProcessHead

3.解析pdb:下载pdb,写工具代码解析pdp获取偏移量。解析pdb很累?其实可以调用symsrv.dll和dbghelp.dll的导出函数解析,也可以使用VS目录下自带的DIA2dump,以及它已经编译好的dll。Dia2dump 示例 - Visual Studio (Windows) | Microsoft Learn
有相关文章介绍DIA2DUMP[原创]通过pdb解析SSDT表地址-编程技术-看雪-安全社区|安全招聘|kanxue.com

cmd输入regsvr32 msdia140.dll之后就可以在工程里下断点调试?
4.调API,哎谁爱解析谁解析,我先调了=。=
NtQuerySystemInformation 函数 (winternl.h) - Win32 apps | Microsoft Learn)在文档中找到SYSTEM_PROCESS_INFORMATION
SYSTEM_PROCESS_INFORMATION 算是半公开的结构体,直接查微软文档他会有一些保留字段显示Reserved,可以使用SourceInsight查看WRK1.2的源码观察他。
SourceInsight官网: 202K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2K6L8%4g2J5j5$3g2A6L8Y4y4A6k6$3S2@1i4K6u0W2j5$3!0E0i4K6u0r3N6s2u0A6j5h3I4Q4x3V1j5`.
WRK1.2下载: 4c3K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6S2P5i4W2#2j5$3g2V1k6h3#2A6M7X3u0S2M7#2)9J5c8W2N6A6L8X3c8G2N6%4y4Q4x3X3c8d9k6i4y4W2j5i4u0U0K9q4)9J5k6p5E0W2M7X3&6W2L8q4)9J5k6q4N6d9d9#2)9J5k6l9`.`.
看一下这个结构体,想要什么自己说(狗头

微软自己也会使用这些API,所以直接抄他代码就行。WRK1.2中搜索PerInfoProcessRundown与PerfInfoSysModuleRunDown。文末代码中遍历模块使用了这些API
注意
高版本看NT开头的函数
都是第一次获取数量,申请缓冲区,第二次获取数据。你直接申请巨大缓冲区也行。
这里没有处理头节点? 有个空的

遍历模块列表,看到了一堆sys

遍历进程的代码 检测Windows版本手动设置偏移量 然后遍历ActiveProcessLinks拿进程信息
遍历模块的代码 直接调用API




挖坑,后续补充一下ARK集成DIA2dump解析PDB的方法~
typedef struct _EPROCESS {
LIST_ENTRY ActiveProcessLinks;
HANDLE UniqueProcessId;
CHAR ImageFileName[16];
} EPROCESS, *PEPROCESS;
具体结构在文末
typedef struct _EPROCESS {
LIST_ENTRY ActiveProcessLinks;
HANDLE UniqueProcessId;
CHAR ImageFileName[16];
} EPROCESS, *PEPROCESS;
具体结构在文末
dt!_KPCR
dt!_KPRCB
dt!_ETHREAD
dt!_EPROCESS
dt!_KAPC_STATE
dt!_LIST_ENTRY
!pcr ; 查看当前处理器的KPCR
!prcb ; 查看当前处理器的KPRCB
!thread ; 查看当前线程的ETHREAD
!process ; 查看当前进程的EPROCESS
!process 0 0 ; 列出所有进程
; 查看ActiveProcessLinks链表
dt _EPROCESS nt!PsInitialSystemProcess ActiveProcessLinks
dt!_KPCR
dt!_KPRCB
dt!_ETHREAD
dt!_EPROCESS
dt!_KAPC_STATE
dt!_LIST_ENTRY
!pcr ; 查看当前处理器的KPCR
!prcb ; 查看当前处理器的KPRCB
!thread ; 查看当前线程的ETHREAD
!process ; 查看当前进程的EPROCESS
!process 0 0 ; 列出所有进程
; 查看ActiveProcessLinks链表
dt _EPROCESS nt!PsInitialSystemProcess ActiveProcessLinks
DriverEntry启动时:
├─ DetectWindowsVersion() 检测系统版本
├─ InitProcessOffsets() 根据版本设置偏移量
FS寄存器到ETHREAD:
├─ FS:[0x124] → 当前ETHREAD指针
└─ 这个0x124是KPCR结构中CurrentThread字段的偏移
WinXP偏移量:
├─ ProcessId: 0x84 // EPROCESS + 0x84 → UniqueProcessId字段
├─ ActiveProcessLinks: 0x88 // EPROCESS + 0x88 → ActiveProcessLinks字段
├─ ParentProcessId: 0x14C // EPROCESS + 0x14C → InheritedFromUniqueProcessId字段
├─ ImageFileName: 0x174 // EPROCESS + 0x174 → ImageFileName[16]字段
└─ DirectoryTableBase: 0x18 // EPROCESS + 0x18 → DirectoryTableBase字段
Win7偏移量:
├─ ProcessId: 0xB4 // EPROCESS + 0xB4 → UniqueProcessId字段
├─ ActiveProcessLinks: 0xB8 // EPROCESS + 0xB8 → ActiveProcessLinks字段
├─ ParentProcessId: 0x140 // EPROCESS + 0x140 → InheritedFromUniqueProcessId字段
├─ ImageFileName: 0x16C // EPROCESS + 0x16C → ImageFileName[16]字段
└─ DirectoryTableBase: 0x18 // EPROCESS + 0x18 → DirectoryTableBase字段 (两个版本相同)
DriverEntry启动时:
├─ DetectWindowsVersion() 检测系统版本
├─ InitProcessOffsets() 根据版本设置偏移量
FS寄存器到ETHREAD:
├─ FS:[0x124] → 当前ETHREAD指针
└─ 这个0x124是KPCR结构中CurrentThread字段的偏移
WinXP偏移量:
├─ ProcessId: 0x84 // EPROCESS + 0x84 → UniqueProcessId字段
├─ ActiveProcessLinks: 0x88 // EPROCESS + 0x88 → ActiveProcessLinks字段
├─ ParentProcessId: 0x14C // EPROCESS + 0x14C → InheritedFromUniqueProcessId字段
├─ ImageFileName: 0x174 // EPROCESS + 0x174 → ImageFileName[16]字段
└─ DirectoryTableBase: 0x18 // EPROCESS + 0x18 → DirectoryTableBase字段
Win7偏移量:
├─ ProcessId: 0xB4 // EPROCESS + 0xB4 → UniqueProcessId字段
├─ ActiveProcessLinks: 0xB8 // EPROCESS + 0xB8 → ActiveProcessLinks字段
├─ ParentProcessId: 0x140 // EPROCESS + 0x140 → InheritedFromUniqueProcessId字段
├─ ImageFileName: 0x16C // EPROCESS + 0x16C → ImageFileName[16]字段
└─ DirectoryTableBase: 0x18 // EPROCESS + 0x18 → DirectoryTableBase字段 (两个版本相同)
进程遍历流程
R3 R0
│ │
├─1. UI响应 ─────┤
├─2. ProcessGetCount()调用──┤
├─3. DeviceIoControl────────►│
│ [CTL_ENUM_PROCESS_COUNT] ├─4. EnumProcessEx第一次调用
│ │ ├─ GetCurrentEprocess()获取起始进程
│ │ │ ├─ mov eax, fs:[0x124] 获取ETHREAD
│ │ │ └─ mov eax, [eax + 0x44/0x150] 获取EPROCESS
│ │ ├─ 遍历ActiveProcessLinks双向链表
│ │ │ ├─ 只统计进程数量,不提取数据
│ │ │ ├─ 获取Flink指针: *(CurrentProcess + 0x88/0xB8)
│ │ │ └─ 计算下一个EPROCESS: Flink - 0x88/0xB8
│ │ └─ 返回进程总数
│◄─5. 返回[进程数量]────────┤
├─6. ProcessGetVec()调用────┤
├─7. DeviceIoControl────────►│
│ [CTL_ENUM_PROCESS] ├─8. 分配PROCESS_INFO数组缓冲区
│ ├─9. EnumProcessEx第二次调用
│ │ ├─ 参数: (buffer, false, &processCount)
│ │ ├─ 重复相同的链表遍历过程
│ │ ├─ 但这次提取并填充进程信息:
│ │ │ ├─ ProcessId: *(EPROCESS + 0x84/0xB4)
│ │ │ ├─ ParentProcessId: *(EPROCESS + 0x14C/0x140)
│ │ │ ├─ DirectoryTableBase: *(EPROCESS + 0x18)
│ │ │ ├─ ImageFileName: RtlCopyMemory(EPROCESS + 0x174/0x16C)
│ │ │ └─ EprocessAddr: EPROCESS指针本身
│ │ └─ 将数据复制到SystemBuffer
│ ├─10. 转换为PROCESS_INFO格式
│◄─11. 返回[PROCESS_INFO数组]┤
进程遍历流程
R3 R0
│ │
├─1. UI响应 ─────┤
├─2. ProcessGetCount()调用──┤
├─3. DeviceIoControl────────►│
│ [CTL_ENUM_PROCESS_COUNT] ├─4. EnumProcessEx第一次调用
│ │ ├─ GetCurrentEprocess()获取起始进程
│ │ │ ├─ mov eax, fs:[0x124] 获取ETHREAD
│ │ │ └─ mov eax, [eax + 0x44/0x150] 获取EPROCESS
│ │ ├─ 遍历ActiveProcessLinks双向链表
│ │ │ ├─ 只统计进程数量,不提取数据
│ │ │ ├─ 获取Flink指针: *(CurrentProcess + 0x88/0xB8)
│ │ │ └─ 计算下一个EPROCESS: Flink - 0x88/0xB8
│ │ └─ 返回进程总数
│◄─5. 返回[进程数量]────────┤
├─6. ProcessGetVec()调用────┤
├─7. DeviceIoControl────────►│
│ [CTL_ENUM_PROCESS] ├─8. 分配PROCESS_INFO数组缓冲区
│ ├─9. EnumProcessEx第二次调用
│ │ ├─ 参数: (buffer, false, &processCount)
│ │ ├─ 重复相同的链表遍历过程
│ │ ├─ 但这次提取并填充进程信息:
│ │ │ ├─ ProcessId: *(EPROCESS + 0x84/0xB4)
│ │ │ ├─ ParentProcessId: *(EPROCESS + 0x14C/0x140)
│ │ │ ├─ DirectoryTableBase: *(EPROCESS + 0x18)
│ │ │ ├─ ImageFileName: RtlCopyMemory(EPROCESS + 0x174/0x16C)
│ │ │ └─ EprocessAddr: EPROCESS指针本身
│ │ └─ 将数据复制到SystemBuffer
│ ├─10. 转换为PROCESS_INFO格式
│◄─11. 返回[PROCESS_INFO数组]┤
内核模块遍历流程
R3 R0
│ │
├─1. UI响应 ─────┤
├─2. ModuleGetCount()调用───┤
├─3. DeviceIoControl────────►│
│ [CTL_ENUM_MODULE_COUNT] ├─4. ZwQuerySystemInformation第一次调用
│ │ ├─ SystemInformationClass = SystemModuleInformation
│◄─5. 返回[模块数量]────────┤
├─6. ModuleGetVec()调用─────┤
├─7. DeviceIoControl────────►│
│ [CTL_ENUM_MODULE] ├─8. 分配足够大小的缓冲区
│ ├─9. ZwQuerySystemInformation第二次调用
│ │ ├─ 传入充足的缓冲区
│ │ ├─ 获取SYSTEM_MODULE_INFORMATION数组
│ │ └─ 解析每个模块信息:
│ │ ├─ ImageBase (模块基址)
│ │ ├─ ImageSize (模块大小)
│ │ ├─ FullPathName (完整路径)
│ │ └─ 提取模块名 (路径最后部分)
│ ├─10. 转换为MODULE_INFO格式
│◄─11. 返回[MODULE_INFO数组]─┤
内核模块遍历流程
R3 R0
│ │
├─1. UI响应 ─────┤
├─2. ModuleGetCount()调用───┤
├─3. DeviceIoControl────────►│
│ [CTL_ENUM_MODULE_COUNT] ├─4. ZwQuerySystemInformation第一次调用
│ │ ├─ SystemInformationClass = SystemModuleInformation
│◄─5. 返回[模块数量]────────┤
├─6. ModuleGetVec()调用─────┤
├─7. DeviceIoControl────────►│
│ [CTL_ENUM_MODULE] ├─8. 分配足够大小的缓冲区
│ ├─9. ZwQuerySystemInformation第二次调用
│ │ ├─ 传入充足的缓冲区
│ │ ├─ 获取SYSTEM_MODULE_INFORMATION数组
│ │ └─ 解析每个模块信息:
│ │ ├─ ImageBase (模块基址)
│ │ ├─ ImageSize (模块大小)
│ │ ├─ FullPathName (完整路径)
│ │ └─ 提取模块名 (路径最后部分)
│ ├─10. 转换为MODULE_INFO格式
│◄─11. 返回[MODULE_INFO数组]─┤
ULONG g_WindowsVersion = 0;
ENUM_PROCESS_OFFSETS g_ProcessOffsets;
enum WindowsVersion
{
WinXP,
Win7,
Other
};
NTSTATUS DetectWindowsVersion()
{
RTL_OSVERSIONINFOW versionInfo = { 0 };
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
NTSTATUS status = RtlGetVersion(&versionInfo);
if (!NT_SUCCESS(status)) {
return status;
}
if (versionInfo.dwMajorVersion == 5) {
g_WindowsVersion = WinXP;
KdPrint(("[test] Version: WinXP\n"));
}
else if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 1) {
g_WindowsVersion = Win7;
KdPrint(("[test] Version: Win7\n"));
}
else {
KdPrint(("[test] Version: Other\n"));
return STATUS_NOT_SUPPORTED;
}
return STATUS_SUCCESS;
}
typedef struct ENUM_PROCESS_OFFSETS {
ULONG EThreadToProcess;
ULONG ProcessId;
ULONG ActiveProcessLinks;
ULONG ParentProcessId;
ULONG ImageFileName;
ULONG DirectoryTableBase;
}*PENUM_PROCESS_OFFSETS;
NTSTATUS InitProcessOffsets() {
if (g_WindowsVersion == WinXP) {
g_ProcessOffsets.EThreadToProcess = 0x44;
g_ProcessOffsets.ProcessId = 0x84;
g_ProcessOffsets.ActiveProcessLinks = 0x88;
g_ProcessOffsets.ParentProcessId = 0x14C;
g_ProcessOffsets.ImageFileName = 0x174;
g_ProcessOffsets.DirectoryTableBase = 0x18;
}
else if (g_WindowsVersion == Win7) {
g_ProcessOffsets.EThreadToProcess = 0x150;
g_ProcessOffsets.ProcessId = 0xB4;
g_ProcessOffsets.ActiveProcessLinks = 0xB8;
g_ProcessOffsets.ParentProcessId = 0x140;
g_ProcessOffsets.ImageFileName = 0x16C;
g_ProcessOffsets.DirectoryTableBase = 0x18;
}
return STATUS_SUCCESS;
}
PEPROCESS GetCurrentEprocess() {
PEPROCESS Process = NULL;
__asm {
mov eax, fs: [0x124]
mov ebx, g_ProcessOffsets.EThreadToProcess
mov eax, [eax + ebx]
mov Process, eax
}
return Process;
}
NTSTATUS EnumProcessEx(PPROCESS_INFO processBuffer, bool onlyGetCount, PULONG processCount) {
PEPROCESS CurrentProcess = NULL;
PEPROCESS StartProcess = NULL;
ULONG Counter = 0;
__try {
StartProcess = GetCurrentEprocess();
CurrentProcess = StartProcess;
KdPrint(("[test] 开始遍历进程,起始EPROCESS: %p\n", CurrentProcess));
do {
if (!onlyGetCount&& processBuffer!=NULL) {
PPROCESS_INFO pInfo = &processBuffer[Counter];
RtlZeroMemory(pInfo, sizeof(PROCESS_INFO));
pInfo->ProcessId = *(PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.ProcessId);
pInfo->ParentProcessId = *(PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.ParentProcessId);
pInfo->EprocessAddr = CurrentProcess;
pInfo->DirectoryTableBase = *(PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.DirectoryTableBase);
PUCHAR ImageFileName = (PUCHAR)CurrentProcess + g_ProcessOffsets.ImageFileName;
RtlCopyMemory(pInfo->ImageFileName, ImageFileName, 16);
pInfo->ImageFileName[15] = '\0';
KdPrint(("[test] 进程[%d]: PID=%d, Name=%s, EPROCESS=%p\n",
Counter, pInfo->ProcessId, pInfo->ImageFileName, CurrentProcess));
}
Counter++;
PULONG ActiveProcessLinksPtr = (PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.ActiveProcessLinks);
ULONG NextLinkAddress = *ActiveProcessLinksPtr;
CurrentProcess = (PEPROCESS)(NextLinkAddress - g_ProcessOffsets.ActiveProcessLinks);
} while (CurrentProcess != StartProcess && Counter < 1000);
*processCount = Counter;
KdPrint(("[test] 遍历完成,总共找到 %d 个进程\n", Counter));
return STATUS_SUCCESS;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
KdPrint(("[test] err EnumerateProcessCount \n"));
return STATUS_UNSUCCESSFUL;
}
}
case CTL_ENUM_PROCESS_COUNT:
{
ULONG processCount = 0;
status = EnumProcessEx(NULL, true, &processCount);
if (NT_SUCCESS(status)) {
*(PULONG)Irp->AssociatedIrp.SystemBuffer = processCount;
info = sizeof(ULONG);
KdPrint(("[test] CTL_ENUM_PROCESS_COUNT: %d 个进程\n", processCount));
}
}
break;
case CTL_ENUM_PROCESS:
{
ULONG processCount = 0;
status = EnumProcessEx((PPROCESS_INFO)Irp->AssociatedIrp.SystemBuffer,
false, &processCount);
if (NT_SUCCESS(status)) {
info = processCount * sizeof(PROCESS_INFO);
KdPrint(("[test] CTL_ENUM_PROCESS: 返回 %d 个进程信息\n", processCount));
}
}
break;
ULONG g_WindowsVersion = 0;
ENUM_PROCESS_OFFSETS g_ProcessOffsets;
enum WindowsVersion
{
WinXP,
Win7,
Other
};
NTSTATUS DetectWindowsVersion()
{
RTL_OSVERSIONINFOW versionInfo = { 0 };
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
NTSTATUS status = RtlGetVersion(&versionInfo);
if (!NT_SUCCESS(status)) {
return status;
}
if (versionInfo.dwMajorVersion == 5) {
g_WindowsVersion = WinXP;
KdPrint(("[test] Version: WinXP\n"));
}
else if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 1) {
g_WindowsVersion = Win7;
KdPrint(("[test] Version: Win7\n"));
}
else {
KdPrint(("[test] Version: Other\n"));
return STATUS_NOT_SUPPORTED;
}
return STATUS_SUCCESS;
}
typedef struct ENUM_PROCESS_OFFSETS {
ULONG EThreadToProcess;
ULONG ProcessId;
ULONG ActiveProcessLinks;
ULONG ParentProcessId;
ULONG ImageFileName;
ULONG DirectoryTableBase;
}*PENUM_PROCESS_OFFSETS;
NTSTATUS InitProcessOffsets() {
if (g_WindowsVersion == WinXP) {
g_ProcessOffsets.EThreadToProcess = 0x44;
g_ProcessOffsets.ProcessId = 0x84;
g_ProcessOffsets.ActiveProcessLinks = 0x88;
g_ProcessOffsets.ParentProcessId = 0x14C;
g_ProcessOffsets.ImageFileName = 0x174;
g_ProcessOffsets.DirectoryTableBase = 0x18;
}
else if (g_WindowsVersion == Win7) {
g_ProcessOffsets.EThreadToProcess = 0x150;
g_ProcessOffsets.ProcessId = 0xB4;
g_ProcessOffsets.ActiveProcessLinks = 0xB8;
g_ProcessOffsets.ParentProcessId = 0x140;
g_ProcessOffsets.ImageFileName = 0x16C;
g_ProcessOffsets.DirectoryTableBase = 0x18;
}
return STATUS_SUCCESS;
}
PEPROCESS GetCurrentEprocess() {
PEPROCESS Process = NULL;
__asm {
mov eax, fs: [0x124]
mov ebx, g_ProcessOffsets.EThreadToProcess
mov eax, [eax + ebx]
mov Process, eax
}
return Process;
}
NTSTATUS EnumProcessEx(PPROCESS_INFO processBuffer, bool onlyGetCount, PULONG processCount) {
PEPROCESS CurrentProcess = NULL;
PEPROCESS StartProcess = NULL;
ULONG Counter = 0;
__try {
StartProcess = GetCurrentEprocess();
CurrentProcess = StartProcess;
KdPrint(("[test] 开始遍历进程,起始EPROCESS: %p\n", CurrentProcess));
do {
if (!onlyGetCount&& processBuffer!=NULL) {
PPROCESS_INFO pInfo = &processBuffer[Counter];
RtlZeroMemory(pInfo, sizeof(PROCESS_INFO));
pInfo->ProcessId = *(PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.ProcessId);
pInfo->ParentProcessId = *(PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.ParentProcessId);
pInfo->EprocessAddr = CurrentProcess;
pInfo->DirectoryTableBase = *(PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.DirectoryTableBase);
PUCHAR ImageFileName = (PUCHAR)CurrentProcess + g_ProcessOffsets.ImageFileName;
RtlCopyMemory(pInfo->ImageFileName, ImageFileName, 16);
pInfo->ImageFileName[15] = '\0';
KdPrint(("[test] 进程[%d]: PID=%d, Name=%s, EPROCESS=%p\n",
Counter, pInfo->ProcessId, pInfo->ImageFileName, CurrentProcess));
}
Counter++;
PULONG ActiveProcessLinksPtr = (PULONG)((PUCHAR)CurrentProcess + g_ProcessOffsets.ActiveProcessLinks);
ULONG NextLinkAddress = *ActiveProcessLinksPtr;
CurrentProcess = (PEPROCESS)(NextLinkAddress - g_ProcessOffsets.ActiveProcessLinks);
} while (CurrentProcess != StartProcess && Counter < 1000);
*processCount = Counter;
KdPrint(("[test] 遍历完成,总共找到 %d 个进程\n", Counter));
return STATUS_SUCCESS;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
KdPrint(("[test] err EnumerateProcessCount \n"));
return STATUS_UNSUCCESSFUL;
}
}
case CTL_ENUM_PROCESS_COUNT:
{
ULONG processCount = 0;
status = EnumProcessEx(NULL, true, &processCount);
if (NT_SUCCESS(status)) {
*(PULONG)Irp->AssociatedIrp.SystemBuffer = processCount;
info = sizeof(ULONG);
KdPrint(("[test] CTL_ENUM_PROCESS_COUNT: %d 个进程\n", processCount));
}
}
break;
case CTL_ENUM_PROCESS:
{
ULONG processCount = 0;
status = EnumProcessEx((PPROCESS_INFO)Irp->AssociatedIrp.SystemBuffer,
false, &processCount);
if (NT_SUCCESS(status)) {
info = processCount * sizeof(PROCESS_INFO);
KdPrint(("[test] CTL_ENUM_PROCESS: 返回 %d 个进程信息\n", processCount));
}
}
break;
DWORD ArkR3::ProcessGetCount()
{
DWORD dwBytes;
DWORD dwEntryNum = NULL;
DeviceIoControl(m_hDriver, CTL_ENUM_PROCESS_COUNT, NULL, NULL, &dwEntryNum, sizeof(DWORD), &dwBytes, NULL);
return dwEntryNum;
}
std::vector<PROCESS_INFO> ArkR3::ProcessGetVec(DWORD processCount)
{
DWORD dwRetBytes;
DWORD dwBufferSize = sizeof(PROCESS_INFO) * processCount;
PPROCESS_INFO pEntryInfo = (PPROCESS_INFO)malloc(dwBufferSize);
BOOL bResult = DeviceIoControl(m_hDriver, CTL_ENUM_PROCESS, NULL, NULL, pEntryInfo, dwBufferSize, &dwRetBytes, NULL);
ProcVec_.clear();
DWORD Count = 0;
if (bResult) {
Count = dwRetBytes / sizeof(PROCESS_INFO);
for (DWORD i = 0; i < Count; i++) {
PROCESS_INFO pInfo = pEntryInfo[i];
ProcVec_.emplace_back(pInfo);
Log("ProcessGetVec 进程[%d]: PID=%d, 父PID=%d, 名称=%s, EPROCESS=%p\n",
i, pInfo.ProcessId, pInfo.ParentProcessId,
pInfo.ImageFileName, pInfo.EprocessAddr);
}
}
free(pEntryInfo);
return ProcVec_;
}
DWORD ArkR3::ProcessGetCount()
{
DWORD dwBytes;
DWORD dwEntryNum = NULL;
DeviceIoControl(m_hDriver, CTL_ENUM_PROCESS_COUNT, NULL, NULL, &dwEntryNum, sizeof(DWORD), &dwBytes, NULL);
return dwEntryNum;
}
std::vector<PROCESS_INFO> ArkR3::ProcessGetVec(DWORD processCount)
{
DWORD dwRetBytes;
DWORD dwBufferSize = sizeof(PROCESS_INFO) * processCount;
PPROCESS_INFO pEntryInfo = (PPROCESS_INFO)malloc(dwBufferSize);
BOOL bResult = DeviceIoControl(m_hDriver, CTL_ENUM_PROCESS, NULL, NULL, pEntryInfo, dwBufferSize, &dwRetBytes, NULL);
ProcVec_.clear();
DWORD Count = 0;
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2025-7-16 14:56
被X66iaM编辑
,原因: