通过CONTEXT.Ebx + 8指向baseAddress的指针

时间:2012-10-09 21:13:35

标签: c winapi pointers

我正在尝试实现“动态分叉Win32 EXE”的已知方法,它被称为RunPE。 我的问题是我无法得到“基地址”的正确结果,正如它在http://www.security.org.sg/code/loadexe.html

的第3点所提到的那样

这是我的代码:

DWORD* peb;
DWORD* baseAddress;
...snip...

GetThreadContext(hTarget, &contx)

peb = (DWORD *) contx.Ebx;
baseAddress = (DWORD *) contx.Ebx+8;

_tprintf(_T("The EBX [PEB] is: 0x%08X\nThe base address is: 0x%08X\nThe Entry Point is: 0x%08X\n"), peb, baseAddress, contx.Eax);

,输出如下:

  

EBX [PEB]是:0x7FFD4000

     

基地址是:0x7FFD4020

     

入口点是:0x00401000

我认为我的问题是我的baseAddress指针的实现,但我无法弄清楚到底是什么问题。或者可能是我没有正确理解上面的文章而baseAddress不是ImageBase,如果是这样,什么是baseAddress?

我试图在Win 7 64b和Win-XP下运行它,但我得到的结果都是错误的。

3 个答案:

答案 0 :(得分:2)

你只是做指针算法,你实际上并没有解除引用内存,在这一行:

baseAddress = (DWORD *) contx.Ebx+8;

您只需将8*sizeof(DWORD) = 32添加到contx.Ebx的值即可。您真正想要做的是在新进程的地址空间中的contx.Ebx+8 地址读取数据。为了做到这一点,你需要使用ReadProcessMemory,而不用费力去投射 - 你想要使用原始偏移,而不是偏移乘以sizeof(DWORD),这是当你做指针时会发生的事情具有DWORD*值的算术。

但是,我强烈建议您不要深入研究这样的实现细节,它可以在不同版本的Windows之间进行更改。请记住,您链接到的文章是在2004年编写的,它只是一个概念验证,因此Vista,Windows 7,Windows 8和未来版本中可能存在大量隐藏的问题和意外问题

Windows API没有像Unix的fork(2)函数那样的函数,因此,您应该尽可能地尝试避免需要fork - 使用CreateProcess而不是{ {1}}等Cygwin implementation of fork是丑陋且缓慢的,并且由于DLL内存映射问题,它可能会意外失败。

答案 1 :(得分:2)

请注意,说明说“在[EBX + 8]”。括号表示该地址位置的值。

有几个问题
baseAddress = (DWORD *) contx.Ebx+8;

首先,编译器没有注意间距,只是为了括号,所以这意味着

baseAddress = ((DWORD *)contx.Ebx) + 8;

这是错误的,因为8计算DWORD而不是字节。你想要

baseAddress = (DWORD *)(contx.Ebx + 8);

但这只是获取存储baseAddress的地址,而不是baseAddress的值。为此你需要

baseAddress = *(DWORD *)(contx.Ebx + 8);

但是,这仅在contx.Ebx引用进程中的地址时才有效,但每个进程都有自己的地址空间,并且您需要访问挂起进程的地址空间;为此你需要使用ReadProcessMemory(http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx):

ok = ReadProcessMemory(hTarget, (LPCVOID)(contx.Ebx + 8), (LPVOID)&baseAddress, sizeof baseAddress, NULL);

答案 2 :(得分:1)

除了其他人所说的内容之外,还有一种更简单的方法来检索进程的PEB结构的基址。请改用NtQueryInformationProcess(),将其ProcessInformationClass参数设置为ProcessBasicInformation。输出将是PROCESS_BASIC_INFORMATION结构:

typedef struct _PROCESS_BASIC_INFORMATION {
    PVOID Reserved1;
    PPEB PebBaseAddress;
    PVOID Reserved2[2];
    ULONG_PTR UniqueProcessId;
    PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

第二个成员就是你要找的。