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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值