zoukankan      html  css  js  c++  java
  • 进程管理02 通过PEB枚举进程所有模块

    0x01  结构探究

    先在win7 x86下通过windbg来探究通过peb来得到进程模块的步骤:

     命令!process 0 0 exeplorer.exe 先获取到explorer.exe的EPROCESS的地址,如图我们可以看到EPROCESS的地址为:0x87782d40 ,PEB的地址为:0x7ffdf000 

    使用 .process /p /r 87ede940 命令切换到explorer.exe进程后才能够访问它的peb用户地址空间:

    切换到explorer.exe后,使用命令dt _EPROCESS 877822d40 查看EPROCESS,可以看到在偏移0x1a8的位置就是_PEB,地址为0x7ffdf000

     

    继续查看_PEB结构,使用命令 dt _PEB 0x7ffdf000查看PEB的信息,可以看到在偏移0x00c的位置就是_PEB_LDR_DATA,地址为: 0x77697880:

    继续查看_PEB_LDR_DATA结构,使用命令dt _PEB_LDR_DATA 0x77697880 查看_PEB_LDR_DATA结构,可以看到一共有3个_LIST_ENTRY,这三个链表只是结点的排列顺序不一样,总的内容是相同的。我利用的是第一个InLoadOrderModuleList:

    现在再来看一个最后的关键结构:_LDR_DATA_TABLE_ENTRY

    使用命令dt _LDR_DATA_TABLE_ENTRY查看_LDR_DATA_TABLE_ENTRY的结构:

    从结构中可以看到InLoadOrderModuleList位于结构体的首部,所以我们获取到的_LIST_ENTRY地址就直接指向了_LDR_DATA_TABLE_ENTRY!(这就是为什么选择InLoadOrderModuleList这条链表的原因。)

    回头看一下眼链表的第一个结点的地址位0x3316a8,使用命令dt _LDR_DATA_TABLE_ENTRY 0x3316a8查看检验一下:

     

    可以看到看到explore.exe这个进程本身的完整路径!因为InLoadOrderModuleList这条链表是按照模块加载顺序遍历的,所以第一个模块儿就是进程本身了,加上0x80的偏移向后看一个进行检验:dt _LDR_DATA_TABLE_ENTRY 0x331ae8

     

    大功告成~

    0x02  步骤实现

    1.先通过NtQueryInformationProcess函数根据传入的进程句柄找到进程的ProcessBasicInformation,就得到ProcessBasicInfo.PebBaseAddress,再传入ProcessBasicInfo.PebBaseAddress借由ReadProcessMemory函数读取出peb结构。

    (附:获得peb的方法有其他,比如去读fs的0x30处等:

      __asm  
        {  
            //1、通过fs:[30h]获取当前进程的_PEB结构  
            mov eax,dword ptr fs:[30h];  
            mov pPeb,eax  
        }  

    2.得到peb之后,传入peb的成员_PEB_LDR_DATA的基地址,通过ReadProcessMemory函数得到_PEB_LDR_DATA

    3.再次使用ReadProcessMemory函数得到_PEB_LDR_DATA的成员变量InLoadOrderModuleList链表进行遍历,由于InLoadOrderModuleList的基地址也是_LDR_DATA_TABLE_ENTRY的第一成员,所以InLoadOrderModuleList的基地址也就是_LDR_DATA_TABLE_ENTRY的基地址。_LDR_DATA_TABLE_ENTRY中就含有进程加载模块的名称和完整路径,分别是FullDllName和BaseDlllName两个成员。

    介绍一下ReadProcessMemory函数:

    BOOL ReadProcessMemory(
      HANDLE hProcess, 
      LPCVOID lpBaseAddress,
      LPVOID lpBuffer, 
      DWORD nSize,      
      LPDWORD lpNumberOfBytesRead 
                      
    );


    参数
    hProcess 
                   目标进程的句柄,该句柄必须对目标进程具有PROCESS_VM_READ 的访问权限。 
    lpBaseAddress 
                   从目标进程中读取数据的起始地址。 在读取数据前,系统将先检验该地址的数据是否可读,如果不可读,函数将调用失败。
    lpBuffer 
                   用来接收数据的缓存区地址。
    nSize 
                  从目标进程读取数据的字节数。
    lpNumberOfBytesRead   

            记录实际读取的字节数的变量地址。如果对这个值 不关心,填入NULL即可。

    返回值
                  如果函数执行成功,返回值非零。
             如果函数执行失败,返回值为零。调用 GetLastError 函数可以获取该函数执行错误的信息。
             如果要读取一个进程中不可访问空间的数据,该函数就会失败。


      注意:ReadProcessMemory 函数从目标进程复制指定大小的数据到自己进程的缓存区,任何拥有PROCESS_VM_READ 权限句柄的进程都可以调用该函数,目标进程的地址空间很显然要是可读的,但也并不是必须的,如果目标进程处于被调试状态的话。

    0x03  代码

    头文件

    #pragma once
    #include <windows.h>
    #include <winternl.h>
    #include <ntstatus.h>
    #include <TlHelp32.h>
    #include <Psapi.h>
    #include <vector>
    using namespace std;
    
    
    enum MODULE_TYPE
    {
    	MODULE_X86,
    	MODULE_X64,
    };
    struct _PROCESS_MODULE_INFORMATION_
    {
    	ULONG64   ModuleBase;                                //操作系统中可能存在64位与32位的程序
    	size_t    ModuleSize;
    	WCHAR     ModuleFullPathData[MAX_PATH];
    	MODULE_TYPE ModuleType;
    };
    template <typename T>
    struct _LIST_ENTRY_
    {
    	T Flink;
    	T Blink;
    };
    
    template <typename T>
    struct _UNICODE_STRING_
    {
    	WORD BufferLength;
    	WORD MaximumLength;
    	T BufferData;
    };
    
    
    
    template <typename T, typename NGF, int A>
    struct _PEB_
    {
    	typedef T type;
    
    	union
    	{
    		struct
    		{
    			BYTE InheritedAddressSpace;
    			BYTE ReadImageFileExecOptions;
    			BYTE BeingDebugged;
    			BYTE BitField;
    		};
    		T dummy01;
    	};
    	T Mutant;
    	T ImageBaseAddress;
    	T Ldr;
    	T ProcessParameters;
    	T SubSystemData;
    	T ProcessHeap;
    	T FastPebLock;
    	T AtlThunkSListPtr;
    	T IFEOKey;
    	T CrossProcessFlags;
    	T UserSharedInfoPtr;
    	DWORD SystemReserved;
    	DWORD AtlThunkSListPtr32;
    	T ApiSetMap;
    	T TlsExpansionCounter;
    	T TlsBitmap;
    	DWORD TlsBitmapBits[2];
    	T ReadOnlySharedMemoryBase;
    	T HotpatchInformation;
    	T ReadOnlyStaticServerData;
    	T AnsiCodePageData;
    	T OemCodePageData;
    	T UnicodeCaseTableData;
    	DWORD NumberOfProcessors;
    	union
    	{
    		DWORD NtGlobalFlag;
    		NGF dummy02;
    	};
    	LARGE_INTEGER CriticalSectionTimeout;
    	T HeapSegmentReserve;
    	T HeapSegmentCommit;
    	T HeapDeCommitTotalFreeThreshold;
    	T HeapDeCommitFreeBlockThreshold;
    	DWORD NumberOfHeaps;
    	DWORD MaximumNumberOfHeaps;
    	T ProcessHeaps;
    	T GdiSharedHandleTable;
    	T ProcessStarterHelper;
    	T GdiDCAttributeList;
    	T LoaderLock;
    	DWORD OSMajorVersion;
    	DWORD OSMinorVersion;
    	WORD OSBuildNumber;
    	WORD OSCSDVersion;
    	DWORD OSPlatformId;
    	DWORD ImageSubsystem;
    	DWORD ImageSubsystemMajorVersion;
    	T ImageSubsystemMinorVersion;
    	T ActiveProcessAffinityMask;
    	T GdiHandleBuffer[A];
    	T PostProcessInitRoutine;
    	T TlsExpansionBitmap;
    	DWORD TlsExpansionBitmapBits[32];
    	T SessionId;
    	ULARGE_INTEGER AppCompatFlags;
    	ULARGE_INTEGER AppCompatFlagsUser;
    	T pShimData;
    	T AppCompatInfo;
    	_UNICODE_STRING_<T> CSDVersion;
    	T ActivationContextData;
    	T ProcessAssemblyStorageMap;
    	T SystemDefaultActivationContextData;
    	T SystemAssemblyStorageMap;
    	T MinimumStackCommit;
    	T FlsCallback;
    	_LIST_ENTRY_<T> FlsListHead;
    	T FlsBitmap;
    	DWORD FlsBitmapBits[4];
    	T FlsHighIndex;
    	T WerRegistrationData;
    	T WerShipAssertPtr;
    	T pContextData;
    	T pImageHeaderHash;
    	T TracingFlags;
    	T CsrServerReadOnlySharedMemoryBase;
    };
    typedef _PEB_<DWORD, DWORD64, 34> _PEB32_;
    typedef _PEB_<DWORD64, DWORD, 30> _PEB64_;
    template<typename T>
    struct _PEB_T
    {
    	typedef typename std::conditional<std::is_same<T, DWORD>::value, _PEB32_, _PEB64_>::type type;
    };
    
    template<typename T>
    struct _PEB_LDR_DATA_
    {
    	unsigned long Length;
    	unsigned char Initialized;
    	T SsHandle;
    	_LIST_ENTRY_<T> InLoadOrderModuleList;
    	_LIST_ENTRY_<T> InMemoryOrderModuleList;
    	_LIST_ENTRY_<T> InInitializationOrderModuleList;
    	T EntryInProgress;
    	unsigned char ShutdownInProgress;
    	T ShutdownThreadId;
    };
    
    
    template<typename T>
    struct _LDR_DATA_TABLE_ENTRY_
    {
    	_LIST_ENTRY_<T> InLoadOrderLinks;
    	_LIST_ENTRY_<T> InMemoryOrderLinks;
    	_LIST_ENTRY_<T> InInitializationOrderLinks;
    	T DllBase;
    	T EntryPoint;
    	unsigned long SizeOfImage;
    	_UNICODE_STRING_<T> FullDllName;
    	_UNICODE_STRING_<T> BaseDllName;
    	unsigned long Flags;
    	unsigned short LoadCount;
    	unsigned short TlsIndex;
    	_LIST_ENTRY_<T> HashLinks;
    	unsigned long TimeDateStamp;
    	T EntryPointActivationContext;
    	T PatchInformation;
    };
    template<typename T>
    struct _PROCESS_BASIC_INFORMATION_
    {
    	NTSTATUS ExitStatus;
    	ULONG    Reserved0;
    	T	     PebBaseAddress;
    	T	     AffinityMask;
    	LONG	 BasePriority;
    	ULONG	 Reserved1;
    	T	     UniqueProcessId;
    	T	     InheritedFromUniqueProcessId;
    };
    
    
    
    
    
    typedef decltype(&NtQueryInformationProcess) LPFN_NTQUERYINFORMATIONPROCESS;
    
    
    
    typedef NTSTATUS(NTAPI *LPFN_NTWOW64QUERYINFORMATIONPROCESS64)(
    	IN  HANDLE ProcessHandle,
    	IN  ULONG  ProcessInformationClass,
    	OUT PVOID  ProcessInformation,
    	IN  ULONG  ProcessInformationLength,
    	OUT PULONG ReturnLength OPTIONAL);
    
    typedef NTSTATUS(NTAPI *LPFN_NTWOW64READVIRTUALMEMORY64)(
    	IN  HANDLE   ProcessHandle,
    	IN  ULONG64  BaseAddress,
    	OUT PVOID    BufferData,
    	IN  ULONG64  BufferLength,
    	OUT PULONG64 ReturnLength OPTIONAL);
    struct _PROCESS_INFORMATION_
    {
    	ULONG  ProcessID;
    	char   ImageNameData[MAX_PATH];
    	char   ProcessFullPathData[MAX_PATH];
    };
    typedef struct
    {
    	DWORD ExitStatus;
    	DWORD PebBaseAddress;
    	DWORD AffinityMask;
    	DWORD BasePriority;
    	ULONG UniqueProcessId;
    	ULONG InheritedFromUniqueProcessId;
    }   __PROCESS_BASIC_INFORMATION__;
    
    typedef LONG(__stdcall *PROCNTQSIP)(HANDLE, UINT, PVOID, ULONG, PULONG);
    
    
    
    SIZE_T SeEnumProcessModuleList(ULONG ProcessID, vector<_PROCESS_MODULE_INFORMATION_>& ProcessModuleInfo);
    SIZE_T SeEnumModuleInfoByPeb(ULONG ProcessID, vector<_PROCESS_MODULE_INFORMATION_>& ProcessModuleInfo);
    template<typename T>
    SIZE_T EnumModuleInfoByPeb(HANDLE ProcessHandle, vector<_PROCESS_MODULE_INFORMATION_>& ProcessModuleInfo);
    ULONG64 GetPeb(HANDLE ProcessHandle, _PEB64_* Peb);
    ULONG32 GetPeb(HANDLE ProcessHandle, _PEB32_* Peb);
    BOOL SeReadProcessMemory(HANDLE ProcessHandle, DWORD BaseAddress, LPVOID BufferData, size_t BufferLength, DWORD64* ReturnLength);
    BOOL SeReadProcessMemory(HANDLE ProcessHandle, DWORD64 BaseAddress, LPVOID BufferData, size_t BufferLength, DWORD64 *ReturnLength);
    

      

     源文件:

    BOOL EnumDllLoaderedProcess(vector<_PROCESS_INFORMATION_>  ProcessInfo, string DllName)
    {
    	OnInitMember();
    	vector<_PROCESS_INFORMATION_>::iterator i;
    	string DllFullPath;
    	int j = 0;
    	for (i = ProcessInfo.begin(); i != ProcessInfo.end(); i++)
    	{
    		ULONG ProcessID = i->ProcessID;
    		vector<_PROCESS_MODULE_INFORMATION_>ProcessModuleInfomationVector;
    		SeEnumProcessModuleList(ProcessID, ProcessModuleInfomationVector);
    		int index = 0;
    		vector<_PROCESS_MODULE_INFORMATION_>::iterator m;
    
    		for (m = ProcessModuleInfomationVector.begin(); m != ProcessModuleInfomationVector.end(); m++)
    		{
    
    			DllFullPath = SeUtf16ToUtf8(m->ModuleFullPathData);
    			index = DllFullPath.find(DllName);
    			if (index == -1)
    			{
    				continue;
    			}
    			else
    			{
    				printf("%s", i->ProcessFullPathData);
    				printf("-----------------------------
    
    ");
    				break;
    			}
    		}
    
    
    
    	}
    	return TRUE;
    }
    
    SIZE_T SeEnumProcessModuleList(ULONG ProcessID, vector<_PROCESS_MODULE_INFORMATION_>& ProcessModuleInfo)
    {
    	SeEnumModuleInfoByPeb(ProcessID, ProcessModuleInfo);
    
    	return ProcessModuleInfo.size();
    }
    SIZE_T SeEnumModuleInfoByPeb(ULONG ProcessID, vector<_PROCESS_MODULE_INFORMATION_>& ProcessModuleInfo)
    {
    	HANDLE ProcessHandle = NULL;
    	BOOL   IsWow64 = FALSE;
    	ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
    	int a = GetLastError();
    	if (ProcessHandle == NULL)
    	{
    		goto Error;
    	}
    	IsWow64Process(ProcessHandle, &IsWow64);
    
    	if (IsWow64 == TRUE)
    	{
    		EnumModuleInfoByPeb<DWORD>(ProcessHandle, ProcessModuleInfo);
    	}
    	else
    	{
    		EnumModuleInfoByPeb<DWORD64>(ProcessHandle, ProcessModuleInfo);
    	}
    Error:
    	if (ProcessHandle != NULL)
    	{
    		CloseHandle(ProcessHandle);
    		ProcessHandle = NULL;
    	}
    	return ProcessModuleInfo.size();
    }
    template<typename T>
    SIZE_T EnumModuleInfoByPeb(HANDLE ProcessHandle, vector<_PROCESS_MODULE_INFORMATION_>& ProcessModuleInfo)
    {
    	typename _PEB_T<T>::type Peb = { { { 0 } } };
    	_PEB_LDR_DATA_<T> PebLdrData = { 0 };
    
    	ProcessModuleInfo.clear();
    
    
    	if (GetPeb(ProcessHandle, &Peb) != 0 && SeReadProcessMemory(ProcessHandle,
    		Peb.Ldr, &PebLdrData, sizeof(PebLdrData), 0) == TRUE)
    	{
    		for (T CheckPtr = PebLdrData.InLoadOrderModuleList.Flink;
    			CheckPtr != (Peb.Ldr + FIELD_OFFSET(_PEB_LDR_DATA_<T>, InLoadOrderModuleList));
    			SeReadProcessMemory(ProcessHandle, static_cast<ULONG64>(CheckPtr), &CheckPtr, sizeof(CheckPtr), 0))
    		{
    			_PROCESS_MODULE_INFORMATION_ v1;
    			wchar_t ModuleFullPathData[MAX_PATH] = { 0 };
    			_LDR_DATA_TABLE_ENTRY_<T> LdrDataTableEntry = { { 0 } };
    
    			SeReadProcessMemory(ProcessHandle, CheckPtr, &LdrDataTableEntry, sizeof(LdrDataTableEntry), 0);
    			SeReadProcessMemory(ProcessHandle, LdrDataTableEntry.FullDllName.BufferData, ModuleFullPathData,
    				LdrDataTableEntry.FullDllName.BufferLength, 0);
    
    			v1.ModuleBase = LdrDataTableEntry.DllBase;
    			v1.ModuleSize = LdrDataTableEntry.SizeOfImage;
    			wmemcpy(v1.ModuleFullPathData, ModuleFullPathData, MAX_PATH);
    			printf("%ls
    ", v1.ModuleFullPathData);
    
    			v1.ModuleType = std::is_same<T, DWORD>::value ? MODULE_X86 : MODULE_X64;
    
    			ProcessModuleInfo.emplace_back(v1);
    		}
    	}
    
    	return ProcessModuleInfo.size();
    }
    ULONG64 GetPeb(HANDLE ProcessHandle, _PEB64_* Peb)
    {
    	_PROCESS_BASIC_INFORMATION_<DWORD64> ProcessBasicInfo = { 0 };
    	ULONG ReturnLength = 0;
    	if (NT_SUCCESS(__NtWow64QueryInformationProcess64(ProcessHandle, ProcessBasicInformation, &ProcessBasicInfo,
    		(ULONG)sizeof(ProcessBasicInfo), &ReturnLength)) && Peb)
    	{
    		__NtWow64ReadVirtualMemory64(ProcessHandle, ProcessBasicInfo.PebBaseAddress, Peb, sizeof(_PEB64_), NULL);
    	}
    
    	return ProcessBasicInfo.PebBaseAddress;
    }
    ULONG32 GetPeb(HANDLE ProcessHandle, _PEB32_* Peb)
    {
    	PROCESS_BASIC_INFORMATION ProcessBasicInfo = { 0 };
    	ULONG ReturnLength = 0;
    
    
    	if (NT_SUCCESS(__NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &ProcessBasicInfo,
    		(ULONG)sizeof(ProcessBasicInfo), &ReturnLength)) && Peb)
    	{
    		ReadProcessMemory(ProcessHandle, ProcessBasicInfo.PebBaseAddress, Peb, sizeof(_PEB32_), NULL);
    	}
    	return reinterpret_cast<ULONG32>(ProcessBasicInfo.PebBaseAddress);
    }
    BOOL SeReadProcessMemory(HANDLE ProcessHandle, DWORD BaseAddress, LPVOID BufferData, size_t BufferLength, DWORD64* ReturnLength)
    {
    	return ReadProcessMemory(ProcessHandle, reinterpret_cast<LPVOID>(BaseAddress), BufferData,
    		BufferLength, reinterpret_cast<SIZE_T*>(ReturnLength));
    
    }
    BOOL SeReadProcessMemory(HANDLE ProcessHandle, DWORD64 BaseAddress, LPVOID BufferData, size_t BufferLength, DWORD64 *ReturnLength)
    {
    	if (__NtWow64ReadVirtualMemory64(ProcessHandle,
    		BaseAddress, BufferData, BufferLength, ReturnLength) != STATUS_SUCCESS)
    	{
    		return FALSE;
    	}
    
    	return TRUE;
    }
    
    
    BOOL OnInitMember()
    {
    	HMODULE NtdllModuleBase = NULL;
    	NtdllModuleBase = GetModuleHandle("Ntdll.dll");
    	if (NtdllModuleBase == NULL)
    	{
    		return FALSE;
    	}
    	__NtWow64QueryInformationProcess64 = (LPFN_NTWOW64QUERYINFORMATIONPROCESS64)GetProcAddress(NtdllModuleBase,
    		"NtWow64QueryInformationProcess64");
    	__NtWow64ReadVirtualMemory64 = (LPFN_NTWOW64READVIRTUALMEMORY64)GetProcAddress(NtdllModuleBase,
    		"NtWow64ReadVirtualMemory64");
    	__NtQueryInformationProcess = (LPFN_NTQUERYINFORMATIONPROCESS)GetProcAddress(NtdllModuleBase,
    		"NtQueryInformationProcess");
    	if (__NtWow64QueryInformationProcess64 == NULL || __NtWow64ReadVirtualMemory64 == NULL || __NtQueryInformationProcess == NULL)
    	{
    		return FALSE;
    	}
    	return TRUE;
    }
    

      

  • 相关阅读:
    CUBRID学习笔记 4 端口和win7下连接数据库cubrid教程
    CUBRID学习笔记 3 net连接数据库并使用cubrid教程示例
    CUBRID学习笔记 2 安装教程
    CUBRID学习笔记 1 简介 cubrid教程
    vs无法打开项目的解决方案
    迷你sql profile,给缺少sql跟踪的朋友们
    EntityFramework 开始小试
    网站安全扫描工具--Netsparker的使用
    ServiceStack.OrmLite 笔记10-group having 分页orderby等
    pyqt5 笔记(四)cx_Freeze 实现代码打包exe
  • 原文地址:https://www.cnblogs.com/lsh123/p/8295774.html
Copyright © 2011-2022 走看看