枚举进程模块的方法有很多种,常见的有枚举PEB和内存搜索法,今天,先来看看实现起来最简单的枚举PEB实现获取进程模块列表。

首先,惯例是各种繁琐的结构体定义。需要包含 ntifs.h 和 WinDef.h, 此处不再列出,各位看官根据情况自行添加。

  1. typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);
  2. typedef ULONG   PPS_POST_PROCESS_INIT_ROUTINE;
  3. typedef struct _PEB_LDR_DATA {
  4. BYTE       Reserved1[8];
  5. PVOID      Reserved2[3];
  6. LIST_ENTRY InMemoryOrderModuleList;
  7. } PEB_LDR_DATA, *PPEB_LDR_DATA;
  8. typedef struct _RTL_USER_PROCESS_PARAMETERS {
  9. BYTE           Reserved1[16];
  10. PVOID          Reserved2[10];
  11. UNICODE_STRING ImagePathName;
  12. UNICODE_STRING CommandLine;
  13. } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
  14. typedef struct _PEB {
  15. BYTE                          Reserved1[2];
  16. BYTE                          BeingDebugged;
  17. BYTE                          Reserved2[1];
  18. PVOID                         Reserved3[2];
  19. PPEB_LDR_DATA                 Ldr;
  20. PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  21. BYTE                          Reserved4[104];
  22. PVOID                         Reserved5[52];
  23. PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  24. BYTE                          Reserved6[128];
  25. PVOID                         Reserved7[1];
  26. ULONG                         SessionId;
  27. } PEB, *PPEB;
  28. typedef struct _LDR_DATA_TABLE_ENTRY
  29. {
  30. LIST_ENTRY InLoadOrderLinks;
  31. LIST_ENTRY InMemoryOrderLinks;
  32. LIST_ENTRY InInitializationOrderLinks;
  33. PVOID DllBase;
  34. PVOID EntryPoint;
  35. DWORD SizeOfImage;
  36. UNICODE_STRING FullDllName;
  37. UNICODE_STRING BaseDllName;
  38. DWORD Flags;
  39. WORD LoadCount;
  40. WORD TlsIndex;
  41. LIST_ENTRY HashLinks;
  42. PVOID SectionPointer;
  43. DWORD CheckSum;
  44. DWORD TimeDateStamp;
  45. PVOID LoadedImports;
  46. PVOID EntryPointActivationContext;
  47. PVOID PatchInformation;
  48. }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;

下面进入真正的实现代码:

  1. NTSTATUS GetProcessModules(ULONG ulProcessId)
  2. {
  3. NTSTATUS nStatus;
  4. //PEB结构指针
  5. PPEB pPEB = NULL;
  6. //EPROCESS结构指针
  7. PEPROCESS  pEProcess = NULL;
  8. //查找的函数名称
  9. UNICODE_STRING uniFunctionName;
  10. //进程参数信息
  11. PRTL_USER_PROCESS_PARAMETERS pParam  = NULL;
  12. //LDR数据结构
  13. PPEB_LDR_DATA pPebLdrData = NULL;
  14. //LDR链表入口
  15. PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
  16. //链表头节点、尾节点
  17. PLIST_ENTRY pListEntryStart = NULL;
  18. PLIST_ENTRY pListEntryEnd = NULL;
  19. //函数指针
  20. PFNPsGetProcessPeb  PsGetProcessPeb = NULL;
  21. //保存APC状态
  22. KAPC_STATE KAPC ={0};
  23. //是否已经附加到进程
  24. BOOLEAN bIsAttached = FALSE;
  25. //获取进程的EPROCESS结构指针
  26. nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);
  27. if (!NT_SUCCESS(nStatus))
  28. {
  29. return STATUS_UNSUCCESSFUL;
  30. }
  31. //查找函数地址
  32. RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");
  33. PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);
  34. if (PsGetProcessPeb == NULL)
  35. {
  36. KdPrint(("Get PsGetProcessPeb Failed~!\n"));
  37. return STATUS_UNSUCCESSFUL;
  38. }
  39. //获取PEB指针
  40. pPEB = PsGetProcessPeb(pEProcess);
  41. if (pPEB == NULL)
  42. {
  43. KdPrint(("Get pPEB Failed~!\n"));
  44. return STATUS_UNSUCCESSFUL;
  45. }
  46. //附加到进程
  47. KeStackAttachProcess(pEProcess, &KAPC);
  48. bIsAttached = TRUE;
  49. //指向LDR
  50. pPebLdrData = pPEB->Ldr;
  51. //头节点、尾节点
  52. pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;
  53. //开始遍历_LDR_DATA_TABLE_ENTRY
  54. do
  55. {
  56. //通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构
  57. pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
  58. //输出DLL全路径
  59. KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName));
  60. pListEntryStart = pListEntryStart->Flink;
  61. }while(pListEntryStart != pListEntryEnd);
  62. //Detach进程
  63. if (bIsAttached != FALSE)
  64. {
  65. KeUnstackDetachProcess(&KAPC);
  66. }
  67. //减少引用计数
  68. if (pEProcess != NULL)
  69. {
  70. ObDereferenceObject(pEProcess);
  71. pEProcess = NULL;
  72. }
  73. return STATUS_SUCCESS;
  74. }
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获取进程模块列表的更多相关文章

  1. 【旧文章搬运】《从PEB获取内存中模块列表》的补充

    原文发表于百度空间,2008-7-26========================================================================== 继续研究PE ...

  2. 进程管理02 通过PEB枚举进程所有模块

    0x01  结构探究 先在win7 x86下通过windbg来探究通过peb来得到进程模块的步骤: 命令!process 0 0 exeplorer.exe 先获取到explorer.exe的EPRO ...

  3. Qt 扫描进程列表以及获取进程信息

    使用方法: QMap<QString,qint64> app_pid; getAllAppPidList( app_pid ); #include <tlhelp32.h>// ...

  4. python 获取进程pid号

    #-*- encoding:UTF-8 -*- import os import sys import string import psutil import re def get_pid(name) ...

  5. 获取进程ID,父进程ID,进程完整路径

    准备写一个进程管理的功能模块,今天下午先写了扫描获取本机各个进程路径,获取各个进程映像名称,进程完整路径. 要获取进程信息,第一步想到的就是提权,提权代码用过多次了,今天也小结了一下(http://w ...

  6. Atitit,通过pid获取进程文件路径 java php  c#.net版本大总结

    Atitit,通过pid获取进程文件路径 java php  c#.net版本大总结 1. 通过PID获取进程路径的几种方法2 1.1. GetModuleFileNameEx 想获得进程可执行文件的 ...

  7. python学习笔记(13)常用模块列表总结

    os模块: os.remove() 删除文件 os.unlink() 删除文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有文件 os.chdir() 改变当前工作 ...

  8. C# 获取进程或线程的相关信息

    信息来自: http://blog.163.com/kunkun0921@126/blog/static/169204332201293023432113/ using System; using S ...

  9. 通过PID获取进程路径的几种方法

    通过PID获取进程路径的几种方法 想获得进程可执行文件的路径最常用的方法是通过GetModuleFileNameEx函数获得可执行文件的模块路径这个函数从Windows NT 4.0开始到现在的Vis ...

随机推荐

  1. POJ 2352

    ---恢复内容开始--- http://poj.org/problem?id=2352 这是一个树状数组的题目,也是我第一次接触这类的题目,也正是因为之前的一道题,TLE了,超时太严重了,我看disc ...

  2. linux skill

    linux console终端乱码解决 1.console终端乱码 在/etc/profile文件的最后一行添加如下内容: export LC_ALL="zh_CN.GB18030" ...

  3. iso网络各层协议

    (1)网卡的作用就是把数据进行串并转换(串连数据是比特流形式的,存在与本计算机内部,而计算机与计算机之间是通过帧形式的数据来进行数据传输的),MAC子层规定了如何在物理线路上传输的frame,LLC的 ...

  4. selenium WebDriver 操作高德地图

    String URL="http://www.amap.com/"; WebDriver driver = new FirefoxDriver(profile); driver.g ...

  5. pydev导入eclipse

    编辑器:Python 自带的 IDLE 简单快捷, 学习Python或者编写小型软件的时候.非常有用. 编辑器: Eclipse + pydev插件 1. Eclipse是写JAVA的IDE, 这样就 ...

  6. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  7. Divide and conquer:Median(POJ 3579)

        快速求两数距离的中值 题目大意:给你一个很大的数组,要你求两个数之间的距离的中值 二分法常规题,一个pos位就搞定的事情 #include <iostream> #include ...

  8. codeforces 507B. Amr and Pins 解题报告

    题目链接:http://codeforces.com/problemset/problem/507/B 题目意思:给出圆的半径,以及圆心坐标和最终圆心要到达的坐标位置.问最少步数是多少.移动见下图.( ...

  9. 使用iScroll时,input等不能输入内容的解决方法

    做移动平台的应用,使用iscroll使屏幕上下滑动.发现当使用iscroll后,input等不能输入内容了.只要在iscroll.js文件中加入如下代码就ok了. function allowForm ...

  10. 【leetcode】Spiral Matrix(middle)

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...