枚举PEB获取进程模块列表
枚举进程模块的方法有很多种,常见的有枚举PEB和内存搜索法,今天,先来看看实现起来最简单的枚举PEB实现获取进程模块列表。
首先,惯例是各种繁琐的结构体定义。需要包含 ntifs.h 和 WinDef.h, 此处不再列出,各位看官根据情况自行添加。
- typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);
- typedef ULONG PPS_POST_PROCESS_INIT_ROUTINE;
- typedef struct _PEB_LDR_DATA {
- BYTE Reserved1[8];
- PVOID Reserved2[3];
- LIST_ENTRY InMemoryOrderModuleList;
- } PEB_LDR_DATA, *PPEB_LDR_DATA;
- typedef struct _RTL_USER_PROCESS_PARAMETERS {
- BYTE Reserved1[16];
- PVOID Reserved2[10];
- UNICODE_STRING ImagePathName;
- UNICODE_STRING CommandLine;
- } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
- typedef struct _PEB {
- BYTE Reserved1[2];
- BYTE BeingDebugged;
- BYTE Reserved2[1];
- PVOID Reserved3[2];
- PPEB_LDR_DATA Ldr;
- PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
- BYTE Reserved4[104];
- PVOID Reserved5[52];
- PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
- BYTE Reserved6[128];
- PVOID Reserved7[1];
- ULONG SessionId;
- } PEB, *PPEB;
- typedef struct _LDR_DATA_TABLE_ENTRY
- {
- LIST_ENTRY InLoadOrderLinks;
- LIST_ENTRY InMemoryOrderLinks;
- LIST_ENTRY InInitializationOrderLinks;
- PVOID DllBase;
- PVOID EntryPoint;
- DWORD SizeOfImage;
- UNICODE_STRING FullDllName;
- UNICODE_STRING BaseDllName;
- DWORD Flags;
- WORD LoadCount;
- WORD TlsIndex;
- LIST_ENTRY HashLinks;
- PVOID SectionPointer;
- DWORD CheckSum;
- DWORD TimeDateStamp;
- PVOID LoadedImports;
- PVOID EntryPointActivationContext;
- PVOID PatchInformation;
- }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);
typedef ULONG PPS_POST_PROCESS_INIT_ROUTINE;
typedef struct _PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
DWORD SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
DWORD Flags;
WORD LoadCount;
WORD TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
DWORD CheckSum;
DWORD TimeDateStamp;
PVOID LoadedImports;
PVOID EntryPointActivationContext;
PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
下面进入真正的实现代码:
- NTSTATUS GetProcessModules(ULONG ulProcessId)
- {
- NTSTATUS nStatus;
- //PEB结构指针
- PPEB pPEB = NULL;
- //EPROCESS结构指针
- PEPROCESS pEProcess = NULL;
- //查找的函数名称
- UNICODE_STRING uniFunctionName;
- //进程参数信息
- PRTL_USER_PROCESS_PARAMETERS pParam = NULL;
- //LDR数据结构
- PPEB_LDR_DATA pPebLdrData = NULL;
- //LDR链表入口
- PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
- //链表头节点、尾节点
- PLIST_ENTRY pListEntryStart = NULL;
- PLIST_ENTRY pListEntryEnd = NULL;
- //函数指针
- PFNPsGetProcessPeb PsGetProcessPeb = NULL;
- //保存APC状态
- KAPC_STATE KAPC ={0};
- //是否已经附加到进程
- BOOLEAN bIsAttached = FALSE;
- //获取进程的EPROCESS结构指针
- nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);
- if (!NT_SUCCESS(nStatus))
- {
- return STATUS_UNSUCCESSFUL;
- }
- //查找函数地址
- RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
- PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);
- if (PsGetProcessPeb == NULL)
- {
- KdPrint(("Get PsGetProcessPeb Failed~!\n"));
- return STATUS_UNSUCCESSFUL;
- }
- //获取PEB指针
- pPEB = PsGetProcessPeb(pEProcess);
- if (pPEB == NULL)
- {
- KdPrint(("Get pPEB Failed~!\n"));
- return STATUS_UNSUCCESSFUL;
- }
- //附加到进程
- KeStackAttachProcess(pEProcess, &KAPC);
- bIsAttached = TRUE;
- //指向LDR
- pPebLdrData = pPEB->Ldr;
- //头节点、尾节点
- pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;
- //开始遍历_LDR_DATA_TABLE_ENTRY
- do
- {
- //通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构
- pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
- //输出DLL全路径
- KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName));
- pListEntryStart = pListEntryStart->Flink;
- }while(pListEntryStart != pListEntryEnd);
- //Detach进程
- if (bIsAttached != FALSE)
- {
- KeUnstackDetachProcess(&KAPC);
- }
- //减少引用计数
- if (pEProcess != NULL)
- {
- ObDereferenceObject(pEProcess);
- pEProcess = NULL;
- }
- return STATUS_SUCCESS;
- }

NTSTATUS GetProcessModules(ULONG ulProcessId)
{
NTSTATUS nStatus;
//PEB结构指针
PPEB pPEB = NULL; //EPROCESS结构指针
PEPROCESS pEProcess = NULL; //查找的函数名称
UNICODE_STRING uniFunctionName; //进程参数信息
PRTL_USER_PROCESS_PARAMETERS pParam = NULL; //LDR数据结构
PPEB_LDR_DATA pPebLdrData = NULL; //LDR链表入口
PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL; //链表头节点、尾节点
PLIST_ENTRY pListEntryStart = NULL;
PLIST_ENTRY pListEntryEnd = NULL; //函数指针
PFNPsGetProcessPeb PsGetProcessPeb = NULL; //保存APC状态
KAPC_STATE KAPC ={0}; //是否已经附加到进程
BOOLEAN bIsAttached = FALSE; //获取进程的EPROCESS结构指针
nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);
if (!NT_SUCCESS(nStatus))
{
return STATUS_UNSUCCESSFUL;
} //查找函数地址
RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);
if (PsGetProcessPeb == NULL)
{
KdPrint(("Get PsGetProcessPeb Failed~!\n"));
return STATUS_UNSUCCESSFUL;
} //获取PEB指针
pPEB = PsGetProcessPeb(pEProcess);
if (pPEB == NULL)
{
KdPrint(("Get pPEB Failed~!\n"));
return STATUS_UNSUCCESSFUL;
} //附加到进程
KeStackAttachProcess(pEProcess, &KAPC); bIsAttached = TRUE; //指向LDR
pPebLdrData = pPEB->Ldr; //头节点、尾节点
pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink; //开始遍历_LDR_DATA_TABLE_ENTRY
do
{
//通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构
pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); //输出DLL全路径
KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName)); pListEntryStart = pListEntryStart->Flink; }while(pListEntryStart != pListEntryEnd); //Detach进程
if (bIsAttached != FALSE)
{
KeUnstackDetachProcess(&KAPC);
} //减少引用计数
if (pEProcess != NULL)
{
ObDereferenceObject(pEProcess);
pEProcess = NULL;
} return STATUS_SUCCESS;
}
下面是运行截图:
本帖为原创,转帖请说明出处,谢谢合作。
本帖地址:http://blog.csdn.net/sonsie007/article/details/22622177

枚举PEB获取进程模块列表的更多相关文章
- 【旧文章搬运】《从PEB获取内存中模块列表》的补充
原文发表于百度空间,2008-7-26========================================================================== 继续研究PE ...
- 进程管理02 通过PEB枚举进程所有模块
0x01 结构探究 先在win7 x86下通过windbg来探究通过peb来得到进程模块的步骤: 命令!process 0 0 exeplorer.exe 先获取到explorer.exe的EPRO ...
- Qt 扫描进程列表以及获取进程信息
使用方法: QMap<QString,qint64> app_pid; getAllAppPidList( app_pid ); #include <tlhelp32.h>// ...
- python 获取进程pid号
#-*- encoding:UTF-8 -*- import os import sys import string import psutil import re def get_pid(name) ...
- 获取进程ID,父进程ID,进程完整路径
准备写一个进程管理的功能模块,今天下午先写了扫描获取本机各个进程路径,获取各个进程映像名称,进程完整路径. 要获取进程信息,第一步想到的就是提权,提权代码用过多次了,今天也小结了一下(http://w ...
- Atitit,通过pid获取进程文件路径 java php c#.net版本大总结
Atitit,通过pid获取进程文件路径 java php c#.net版本大总结 1. 通过PID获取进程路径的几种方法2 1.1. GetModuleFileNameEx 想获得进程可执行文件的 ...
- python学习笔记(13)常用模块列表总结
os模块: os.remove() 删除文件 os.unlink() 删除文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有文件 os.chdir() 改变当前工作 ...
- C# 获取进程或线程的相关信息
信息来自: http://blog.163.com/kunkun0921@126/blog/static/169204332201293023432113/ using System; using S ...
- 通过PID获取进程路径的几种方法
通过PID获取进程路径的几种方法 想获得进程可执行文件的路径最常用的方法是通过GetModuleFileNameEx函数获得可执行文件的模块路径这个函数从Windows NT 4.0开始到现在的Vis ...
随机推荐
- Unity3d《Shader篇》变胖
变胖前 变胖后 //Shader Shader "Custom/NormalExt" { Properties { _MainTex("Base (RGB)", ...
- ACM/ICPC 之 暴力打表(求解欧拉回路)-编码(POJ1780)
///找到一个数字序列包含所有n位数(连续)一次且仅一次 ///暴力打表 ///Time:141Ms Memory:2260K #include<iostream> #include< ...
- ATS(App Transport Security)对HTTP协议屏蔽引起的问题
一.问题描述 在学习网络处理的过程,发现代码都没错,运行时会收到如下错误提示: App Transport Security has blocked a cleartext HTTP (http:// ...
- 【编程题目】有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配...
37.(字符串)有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配,则两个字符串可以联接,问这 n 个字符串最多可以连成一个多长的字符串,如果出现循环, ...
- JavaEE编码题
1.请编写代码实现登录效果(5分) 要求: 1)手写出相应的HTML和CSS代码 2)字体大小12px,表格宽300px,按钮行占两列并水平居中, 3)可以写在style节点内,也可使用行内CSS或者 ...
- 240个jquery插件(转)
http://www.kollermedia.at/archive/2007/11/21/the-ultimate-jquery-plugin-list/File upload Ajax File U ...
- Web上的支持的图片格式以及它们之间的区别
一.GIF(图形交换格式) GIF格式的图片最多只能保存256中颜色,该格式支持透明色,支持动画效果. 二.JPEG(联合图像专家组) JPEG格式不支持透明色及动画,颜色可达1670种. 三.PNG ...
- MVC4过滤器
MVC4提供的四种基本类型过滤器接口,IAuthorizationFilter.IActionFilter.IResultFilter和IExceptionFilter,可通过继承对应的接口和Filt ...
- PHP数据库操作
PHP实现数据库的增删改查 <?php $conn=mysql_connect('localhost','root','root'); if(!$conn){ echo "connec ...
- 安装less
1.下载安装iterm(http://www.iterm2.com/) 2.打开iterm,输入 sudo npm install -g less