x64进程如何获得wow64进程的PEB

wow64进程存在2个PEB,如果通过ZWQueryInformationProcess查询的到的是wow64进程的native层PEB,有的信息并不是我们想要的

wow64进程的实质是通过2个不同的代码段,共享一个相同的数据段来确保一个进程内能同时运行32位程序和64位

这2个段的CS分别位23 和33,不过这个和PEB无关,

PEB的位置:(1)native的gs段 (2)wow64的是fs段


相关api使用:


BOOL WINAPI MyWow64GetThreadSelectorEntry(HANDLE hThread, DWORD dwSelector, PWOW64_LDT_ENTRY lpSelectorEntry)
{
	typedef BOOL (WINAPI * pfn_Wow64GetThreadSelectorEntry)(HANDLE hThread, DWORD dwSelector, PWOW64_LDT_ENTRY lpSelectorEntry);
	HMODULE hk = GetModuleHandle(L"kernel32.dll");

	if(hk)
	{
		pfn_Wow64GetThreadSelectorEntry fn_Wow64GetThreadSelectorEntry = (pfn_Wow64GetThreadSelectorEntry)::GetProcAddress(hk, "Wow64GetThreadSelectorEntry");

		if(fn_Wow64GetThreadSelectorEntry)
		{
			return fn_Wow64GetThreadSelectorEntry(hThread, dwSelector, lpSelectorEntry);
		}
	}

	return FALSE;
}

BOOL WINAPI MyWow64GetThreadContext(HANDLE hThread, PWOW64_CONTEXT lpContext)
{
	typedef BOOL (WINAPI * pfn_Wow64GetThreadContext)(HANDLE hThread, PWOW64_CONTEXT lpContext);
	HMODULE hk = GetModuleHandle(L"kernel32.dll");

	if(hk)
	{
		pfn_Wow64GetThreadContext f = (pfn_Wow64GetThreadContext)::GetProcAddress(hk, "Wow64GetThreadContext");

		if(f)
		{
			return f(hThread, lpContext);
		}
	}

	return FALSE;
}


这两个函数是native64模式的导出函数,可以获得一个线程的当前上下文和查询段选择子对应的LDT,有了这个就可以计算fs段了

剩下的事情简单了

大概步骤

(1)找到属于wow64进程的一个线程

(2)获得fs段

(3)通过TEB结构查询PEB结构


注意的是在64位编译器编译的时候TEB PEB等结构中的指针被编译成64位的了,你应该改改!!


BOOL GetWow64ProcessCurrentDirectoryByTibAddress(HANDLE hProcess, DWORD dwTibAddress, WCHAR* OUT szDir, DWORD cchDir)
{
	BOOL bRet = FALSE;
	SIZE_T szRead = 0;

	if(hProcess)
	{
		WOW64_TEB teb = {};

		if(ReadProcessMemory(hProcess, (LPCVOID)dwTibAddress, &teb, sizeof(WOW64_TEB), &szRead) && szRead <= sizeof(WOW64_TEB))
		{
			WOW64_PEB_FOR_PROCESS_PARAMETERS peb = {};

			if(ReadProcessMemory(hProcess, (LPCVOID)teb.ProcessEnvironmentBlock, &peb, sizeof(WOW64_PEB_FOR_PROCESS_PARAMETERS), &szRead) && szRead <= sizeof(WOW64_PEB_FOR_PROCESS_PARAMETERS))
			{
				WOW64_PROCESS_PARAMETERS params = {};

				if(ReadProcessMemory(hProcess, (LPCVOID)peb.PWOW64_PROCESS_PARAMETERS_ProcessParameters, ¶ms, sizeof(WOW64_PROCESS_PARAMETERS), &szRead) && szRead <= sizeof(WOW64_PROCESS_PARAMETERS))
				{
					if(params.CurrentDirectory.DosPath.Length > 0)
					{
						LPVOID  Buffer = ::HeapAlloc(::GetProcessHeap(), 0, params.CurrentDirectory.DosPath.Length + sizeof(WCHAR));

						// 读取进程启动命令行参数
						if(Buffer && ReadProcessMemory(hProcess, (LPCVOID) params.CurrentDirectory.DosPath.Buffer, Buffer, params.CurrentDirectory.DosPath.Length, &szRead) &&  szRead <= params.CurrentDirectory.DosPath.Length)
						{
							PWCHAR  cl = (PWCHAR)Buffer;
							cl[params.CurrentDirectory.DosPath.Length / 2] = 0;
							StringCchCopy(szDir, cchDir, cl);
							//
							bRet = TRUE;
						}

						::HeapFree(::GetProcessHeap(), 0, Buffer);
					}
				}
			}
		}
	}

	return bRet;
}

BOOL GetWow64ProcessCurrentDirectoryByTibAddress(DWORD dwPID, DWORD dwTibAddress, WCHAR* OUT szDir, DWORD cchDir)
{
	if(!szDir || !cchDir)
		return FALSE;

	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
	BOOL   bRet		= FALSE;

	if(hProcess)
	{
		bRet = GetWow64ProcessCurrentDirectoryByTibAddress(hProcess, dwTibAddress, szDir, cchDir);
		CloseHandle(hProcess);
	}

	return bRet;
}

BOOL GetWow64ProcessCurrentDirectory(DWORD pid, WCHAR* OUT szDir, DWORD cchDir)
{
	if(!szDir || !cchDir)
		return FALSE;

	BOOL bRet = FALSE;
	WOW64_CONTEXT wow64Context = {};
	wow64Context.ContextFlags = /*CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS|*/CONTEXT_SEGMENTS;
	WOW64_LDT_ENTRY selector_entry = {};
	BOOL bGetContextOK = FALSE;
	BOOL bGetSelector = FALSE;
	HANDLE hProcessSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pid);

	if(INVALID_HANDLE_VALUE != hProcessSnapShot)
	{
		THREADENTRY32 thread_entry = {sizeof(THREADENTRY32)};
		DWORD dwFirstThreadID = 0;
		BOOL bFindFirstThread = FALSE;

		if(Thread32First(hProcessSnapShot, &thread_entry))
		{
			do
			{
				if(thread_entry.th32OwnerProcessID == pid)
				{
					bFindFirstThread = TRUE;
					dwFirstThreadID = thread_entry.th32ThreadID;
					break;
				}
			}
			while(Thread32Next(hProcessSnapShot, &thread_entry));
		}

		if(bFindFirstThread)
		{
			HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION /*| THREAD_SUSPEND_RESUME*/, FALSE, dwFirstThreadID);

			if(hThread)
			{
		
				if(MyWow64GetThreadContext(hThread, &wow64Context))
				{
					bGetContextOK = TRUE;

					if(MyWow64GetThreadSelectorEntry(hThread, (wow64Context.SegFs), &selector_entry))
					{
						bGetSelector = TRUE;
					}
				}

				CloseHandle(hThread);
			}
		}

		CloseHandle(hProcessSnapShot);
	}

	if(bGetContextOK && bGetSelector)
	{
		DWORD dwBase = (selector_entry.BaseLow) | (selector_entry.HighWord.Bits.BaseMid << 16) | (selector_entry.HighWord.Bits.BaseHi << 24);
		return GetWow64ProcessCurrentDirectoryByTibAddress(pid, dwBase, szDir, cchDir);
	}

	return bRet;
}


其他的代码不多说了,自己动手丰衣足食!!









  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PEB(Process Environment Block)是Windows操作系统中的一个重要结构体,它包含了当前进程的环境信息。通过PEB,我们可以获取当前进程的模块信息,包括模块的基地址、模块的名称等。 在x64wow64下,PEB结构体的定义并没有变化,但是由于x64wow64的指针长度不同,所以在使用PEB时需要注意指针长度的问题。 以下是通过PEB遍历进程模块的代码示例: ```c++ #include <windows.h> #include <winternl.h> #include <iostream> typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { ULONG TimeDateStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; LIST_ENTRY ForwarderLinks; LIST_ENTRY ServiceTagLinks; LIST_ENTRY StaticLinks; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA LoaderData; PVOID ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PVOID FastPebLock; PVOID AtlThunkSListPtr; PVOID IFEOKey; PVOID CrossProcessFlags; PVOID UserSharedInfoPtr; ULONG SystemReserved; ULONG AtlThunkSListPtr32; PVOID ApiSetMap; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[2]; PVOID ReadOnlySharedMemoryBase; PVOID HotpatchInformation; PVOID ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; ULONG NumberOfProcessors; ULONG NtGlobalFlag; LARGE_INTEGER CriticalSectionTimeout; ULONG_PTR HeapSegmentReserve; ULONG_PTR HeapSegmentCommit; ULONG_PTR HeapDeCommitTotalFreeThreshold; ULONG_PTR HeapDeCommitFreeBlockThreshold; ULONG_PTR NumberOfHeaps; ULONG_PTR MaximumNumberOfHeaps; PVOID ProcessHeaps; PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; PVOID GdiDCAttributeList; PVOID LoaderLock; ULONG OSMajorVersion; ULONG OSMinorVersion; USHORT OSBuildNumber; USHORT OSCSDVersion; ULONG OSPlatformId; ULONG ImageSubsystem; ULONG ImageSubsystemMajorVersion; ULONG ImageSubsystemMinorVersion; ULONG_PTR ImageProcessAffinityMask; ULONG_PTR GdiHandleBuffer[34]; PVOID PostProcessInitRoutine; PVOID TlsExpansionBitmap; ULONG TlsExpansionBitmapBits[32]; ULONG SessionId; ULARGE_INTEGER AppCompatFlags; ULARGE_INTEGER AppCompatFlagsUser; PVOID pShimData; PVOID AppCompatInfo; UNICODE_STRING CSDVersion; PVOID ActivationContextData; PVOID ProcessAssemblyStorageMap; PVOID SystemDefaultActivationContextData; PVOID SystemAssemblyStorageMap; ULONG_PTR MinimumStackCommit; } PEB, *PPEB; void EnumerateProcessModules(HANDLE hProcess) { PEB peb; ZeroMemory(&peb, sizeof(PEB)); // 获取PEB地址 BOOL bRet = ReadProcessMemory(hProcess, &NtCurrentTeb()->ProcessEnvironmentBlock, &peb, sizeof(PEB), NULL); if (!bRet) { std::cout << "ReadProcessMemory failed!" << std::endl; return; } // 遍历模块列表 PPEB_LDR_DATA pLdrData = peb.LoaderData; if (pLdrData == NULL) { std::cout << "LoaderData is NULL!" << std::endl; return; } PLIST_ENTRY pListHead = &pLdrData->InMemoryOrderModuleList; PLIST_ENTRY pListEntry = pListHead->Flink; while (pListEntry != pListHead) { PLDR_DATA_TABLE_ENTRY pLdrEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if (pLdrEntry->DllBase != NULL) { // 获取模块基地址和名称 wchar_t szModule[MAX_PATH] = { 0 }; bRet = ReadProcessMemory(hProcess, pLdrEntry->FullDllName.Buffer, szModule, pLdrEntry->FullDllName.Length, NULL); if (bRet) { std::wcout << L"Module Base: " << pLdrEntry->DllBase << L", Module Name: " << szModule << std::endl; } } pListEntry = pListEntry->Flink; } } int main(int argc, char* argv[]) { DWORD dwProcessId = 0; if (argc > 1) { dwProcessId = atoi(argv[1]); } HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == NULL) { std::cout << "OpenProcess failed!" << std::endl; return 0; } EnumerateProcessModules(hProcess); CloseHandle(hProcess); return 0; } ``` 需要注意的是,以上代码中使用了一些Windows内部的结构体和函数,如`UNICODE_STRING`、`LIST_ENTRY`、`NtCurrentTeb()`等,需要包含相应的头文件,并且这些结构体和函数都不是官方公开的API,可能会在未来的操作系统版本中发生变化。因此,开发者在使用这些结构体和函数时需要特别注意。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值