枚举PEB获取进程模块列表

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


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


 

  1. typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess);  
  2.   
  3. typedef ULONG   PPS_POST_PROCESS_INIT_ROUTINE;    
  4.   
  5. typedef struct _PEB_LDR_DATA {  
  6.     BYTE       Reserved1[8];  
  7.     PVOID      Reserved2[3];  
  8.     LIST_ENTRY InMemoryOrderModuleList;  
  9. } PEB_LDR_DATA, *PPEB_LDR_DATA;  
  10.   
  11. typedef struct _RTL_USER_PROCESS_PARAMETERS {  
  12.     BYTE           Reserved1[16];  
  13.     PVOID          Reserved2[10];  
  14.     UNICODE_STRING ImagePathName;  
  15.     UNICODE_STRING CommandLine;  
  16. } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;  
  17.   
  18. typedef struct _PEB {  
  19.     BYTE                          Reserved1[2];  
  20.     BYTE                          BeingDebugged;  
  21.     BYTE                          Reserved2[1];  
  22.     PVOID                         Reserved3[2];  
  23.     PPEB_LDR_DATA                 Ldr;  
  24.     PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;  
  25.     BYTE                          Reserved4[104];  
  26.     PVOID                         Reserved5[52];  
  27.     PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;  
  28.     BYTE                          Reserved6[128];  
  29.     PVOID                         Reserved7[1];  
  30.     ULONG                         SessionId;  
  31. } PEB, *PPEB;  
  32.   
  33. typedef struct _LDR_DATA_TABLE_ENTRY    
  34. {    
  35.     LIST_ENTRY InLoadOrderLinks;    
  36.     LIST_ENTRY InMemoryOrderLinks;    
  37.     LIST_ENTRY InInitializationOrderLinks;    
  38.     PVOID DllBase;    
  39.     PVOID EntryPoint;    
  40.     DWORD SizeOfImage;    
  41.     UNICODE_STRING FullDllName;    
  42.     UNICODE_STRING BaseDllName;    
  43.     DWORD Flags;    
  44.     WORD LoadCount;    
  45.     WORD TlsIndex;    
  46.     LIST_ENTRY HashLinks;    
  47.     PVOID SectionPointer;    
  48.     DWORD CheckSum;    
  49.     DWORD TimeDateStamp;    
  50.     PVOID LoadedImports;    
  51.     PVOID EntryPointActivationContext;    
  52.     PVOID PatchInformation;    
  53. }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.   
  7.     //EPROCESS结构指针  
  8.     PEPROCESS  pEProcess = NULL;  
  9.   
  10.     //查找的函数名称  
  11.     UNICODE_STRING uniFunctionName;  
  12.       
  13.     //进程参数信息  
  14.     PRTL_USER_PROCESS_PARAMETERS pParam  = NULL;  
  15.   
  16.     //LDR数据结构  
  17.     PPEB_LDR_DATA pPebLdrData = NULL;    
  18.   
  19.     //LDR链表入口  
  20.     PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;    
  21.   
  22.     //链表头节点、尾节点  
  23.     PLIST_ENTRY pListEntryStart = NULL;  
  24.     PLIST_ENTRY pListEntryEnd = NULL;   
  25.   
  26.     //函数指针  
  27.     PFNPsGetProcessPeb  PsGetProcessPeb = NULL;  
  28.   
  29.     //保存APC状态  
  30.     KAPC_STATE KAPC ={0};  
  31.   
  32.     //是否已经附加到进程  
  33.     BOOLEAN bIsAttached = FALSE;  
  34.   
  35.     //获取进程的EPROCESS结构指针  
  36.     nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess);  
  37.     if (!NT_SUCCESS(nStatus))  
  38.     {  
  39.         return STATUS_UNSUCCESSFUL;  
  40.     }  
  41.   
  42.     //查找函数地址  
  43.     RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");  
  44.     PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);  
  45.     if (PsGetProcessPeb == NULL)  
  46.     {  
  47.         KdPrint(("Get PsGetProcessPeb Failed~!\n"));  
  48.         return STATUS_UNSUCCESSFUL;  
  49.     }  
  50.   
  51.     //获取PEB指针  
  52.     pPEB = PsGetProcessPeb(pEProcess);  
  53.     if (pPEB == NULL)  
  54.     {  
  55.         KdPrint(("Get pPEB Failed~!\n"));  
  56.         return STATUS_UNSUCCESSFUL;  
  57.     }  
  58.   
  59.     //附加到进程  
  60.     KeStackAttachProcess(pEProcess, &KAPC);  
  61.   
  62.     bIsAttached = TRUE;  
  63.   
  64.     //指向LDR  
  65.     pPebLdrData = pPEB->Ldr;  
  66.   
  67.     //头节点、尾节点  
  68.     pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;  
  69.   
  70.   
  71.     //开始遍历_LDR_DATA_TABLE_ENTRY  
  72.     do    
  73.     {    
  74.         //通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构    
  75.         pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);    
  76.   
  77.         //输出DLL全路径  
  78.         KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName));  
  79.   
  80.         pListEntryStart = pListEntryStart->Flink;    
  81.   
  82.     }while(pListEntryStart != pListEntryEnd);    
  83.   
  84.   
  85.     //Detach进程  
  86.     if (bIsAttached != FALSE)  
  87.     {  
  88.         KeUnstackDetachProcess(&KAPC);  
  89.     }  
  90.   
  91.     //减少引用计数  
  92.     if (pEProcess != NULL)  
  93.     {  
  94.         ObDereferenceObject(pEProcess);  
  95.         pEProcess = NULL;  
  96.     }  
  97.   
  98.     return STATUS_SUCCESS;  
  99. }  
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


posted @ 2016-08-11 16:18  狂客  阅读(3108)  评论(0编辑  收藏  举报