3

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

这是我的代码:

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 下运行它,并且在两者上我都得到了相同的错误结果。

4

3 回答 3

2

你只是在做指针算术,你实际上并没有取消引用内存,在这一行:

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

你只是增加8*sizeof(DWORD) = 32contx.Ebx. 您真正想要做的是读取contx.Ebx+8 新进程地址空间中地址处的数据。为了做到这一点,您需要使用ReadProcessMemory,并且不要费心进行强制转换——您想使用原始偏移量,而不是乘以 的偏移量sizeof(DWORD),这就是当您对DWORD*值进行指针运算时会发生的情况。

但是,我强烈警告您不要深入研究这样的实现细节,这可以而且确实会在不同版本的 Windows 之间发生变化。请记住,您链接到的文章写于 2004 年,只是一个概念验证,因此在 Vista、Windows 7、Windows 8 和未来版本中可能存在许多隐藏的陷阱和意想不到的问题.

Windows API 没有像 Unix 的fork(2)函数一样的函数,因此,您应该尽可能避免需要 fork -- useCreateProcess代替fork+execetc。Cygwin 的实现fork既丑陋又慢,它可以由于 DLL 内存映射问题而意外失败。

于 2012-10-09T21:27:54.817 回答
2

除了其他人所说的之外,还有一种更简单的方法可以检索进程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;

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

于 2012-10-09T23:42:35.633 回答
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);
于 2012-10-09T22:05:20.587 回答