枚举PEB获取进程模块列表

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

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

[cpp] view plain copy

print?

  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;  

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

[cpp] view plain copy

print?

  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

时间: 2024-10-12 13:36:35

枚举PEB获取进程模块列表的相关文章

将dll从进程模块列表中移除并保持正常运行

将dll从进程模块列表中移除并保持正常运行,这玩意想想是挺简单,n久前byshell就用了, 简单的思路就是给当前的dll内存映像做份拷贝,然后跳到那份拷贝的地址空间的代码,回头free掉原来的dll, 然后马上用VirtualAlloc在原基址上申请块同样大小的空间,并将那份拷贝还原回去,再跳回去执行.完. 代码写完后再实际程序中应用后发现问题,一旦调用到malloc或new的话就会崩溃,于是去看了下byshell的代码,发现他申请内存是用VirtualAlloc,但是我大量的代码都是用new

获取进程列表及相关信息

闲着没事,看着任务管理器好玩,查资料先简单实现一下,代码中没有加入获取CPU占用率的代码,这个代码网上很多,只是不喜欢那种写法,这里就不写了.以后继续完善,对于System Process和System的信息还没法获得,那位兄弟知道可以提个醒. 代码如下 [delphi] view plaincopy unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Form

获取进程列表

获取进程列表: public static string GetProcessList() { string str=""; Process[] processes=Process.GetProcesses(); Process proces; for (int i=0;i<processes.Length;i++) { proces=processes[i]; str += Convert.ToString(proces.Id) + ":" + proces

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

使用方法: QMap<QString,qint64> app_pid; getAllAppPidList( app_pid ); #include <tlhelp32.h>// for CreateToolhelp32Snapshot #include <Psapi.h> // for GetModuleFileNameEx #define FORMAT_PATH(path) path.replace('\\','/').toLower() QString GetPat

驱动层 完成获取进程网络流量模块(总结)

xp平台下是使用TDI,win 7平台采用的是WFP的模式 WFP框架下思路 获取进程ID  获取进程的上传数据大小和下载数据大小,然后存储到链表中 链表中节点结构体如下: typedef struct tagFlowInfoItem { /**  链表结构 */ LIST_ENTRY  m_listEntry; /**  进程ID */ HANDLE  m_processID; /** 已上传流量,BYTE为单位 */ UINT64 m_uploadFlow; /** 已下载流量,BYTE为单

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

Atitit,通过pid获取进程文件路径 java php  c#.net版本大总结 1. 通过PID获取进程路径的几种方法2 1.1. GetModuleFileNameEx 想获得进程可执行文件的路径最常用的方法是通过GetModuleFileNameEx函数获得可执行文件的模块路径这个函数从Windows NT 4.0开始到现在的Vista系统都能使用,向后兼容性比较好.2 1.2. 第二种方法是GetProcessImageFileName函数,这个函数在Windows XP及其以后的系

Android之——获取进程总数、内存、任务列表

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47263863 如今,基于Android平台的应用越来越多,不乏这样一些应用程序,这些应用可以多手机中的进程,内存和任务列表进行管理.Android系统中没有自带的应用程序对这些数据进行管理.大家不禁会说,Android的应用设置里面有这些功能啊!是的,虽然应用设置里面有,但是我们如果想看一下系统的进程,还要跑到系统设置里面去看吗?这样是不是很麻烦?是不是很挫呢?那获取Androi

C#根据进程名称获取进程的句柄?

C#根据进程名称获取进程的句柄或C#如何获取其他进程的句柄? 不用FindWindow方法! [StructLayout(LayoutKind.Sequential)] public struct ProcessEntry32 { public uint dwSize; public uint cntUsage; public uint th32ProcessID; public IntPtr th32DefaultHeapID; public uint th32ModuleID; public

C#依据进程名称获取进程的句柄?

C#依据进程名称获取进程的句柄或C#怎样获取其它进程的句柄? 有时候标题名是动态变化的,所以不使用FindWindow方法! [StructLayout(LayoutKind.Sequential)] public struct ProcessEntry32 { public uint dwSize; public uint cntUsage; public uint th32ProcessID; public IntPtr th32DefaultHeapID; public uint th32