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;
}
剩下的事情简单了
大概步骤
(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;
}
其他的代码不多说了,自己动手丰衣足食!!