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

时间:2023-02-04 21:41:04

I am trying to implement the known method of "Dynamic Forking of Win32 EXE", which is knows as RunPE. My problem is that i am can't get the right result of the "base address" as it mentioned in the 3rd point at http://www.security.org.sg/code/loadexe.html

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

This is my code:

这是我的代码:

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);

and the output is as follwos:

输出如下:

The EBX [PEB] is: 0x7FFD4000

EBX [PEB]是:0x7FFD4000。

The base address is: 0x7FFD4020

基本地址是:0x7FFD4020。

The Entry Point is: 0x00401000

入口点是:0x00401000。

I think that my problem is with the implementation of my baseAddress pointer, but i can't figure out exactly what is the issue. Or could be that i havn't understand the above article correctly and baseAddress isn't ImageBase, if so what is baseAddress ?

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

I have tried to run it under Win 7 64b and Win-XP and on both i am get the same incorrect results.

我已经试着在Win 7 64b和Win- xp下运行它,并且在这两个方面我都得到了同样不正确的结果。

3 个解决方案

#1


2  

Note that the instructions say "at [EBX+8]". The brackets mean the value at that address location. There are several problems with

注意,说明书上写着“at [EBX+8]”。括号表示地址位置的值。有几个问题。

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

First, the compiler doesn't pay attention spacing, only to parenthesizing, so this means

首先,编译器不注意间距,只注意圆括号,所以这意味着。

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

which is wrong because the 8 is counting DWORDs, rather than bytes. You want

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

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

but this just gets you the address where the baseAddress is stored, not the value of the baseAddress. For that you need

但这只会告诉你,baseAddress存储的地址,而不是baseAddress的值。为你需要

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

However, this only works if contx.Ebx refers to an address in your process, but every process has its own address space, and you need to access the address space of the suspended process; for that you need to use ReadProcessMemory ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx ):

然而,这只有在contx的情况下才有效。Ebx是指您的进程中的一个地址,但是每个进程都有自己的地址空间,您需要访问被挂起进程的地址空间;因为您需要使用ReadProcessMemory (http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553% 28v=vs.85%29aspx):

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

#2


2  

You're just doing pointer arithmetic, you're not actually dereferencing the memory, in this line:

你只是在做指针运算,你实际上并没有取消记忆,在这一行:

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

You're just adding 8*sizeof(DWORD) = 32 to the value of contx.Ebx. What you really want to do is read the data at the address of contx.Ebx+8 in the new process's address space. In order to do that, you need to use ReadProcessMemory, and don't bother to cast -- you want to use raw offsets, not offsets multiplied by sizeof(DWORD), which is what happens when you do pointer arithmetic with DWORD* values.

你只是将8*sizeof(DWORD) = 32添加到contx.Ebx的值。你真正想做的是在contx的地址读取数据。Ebx+8在新进程的地址空间。为了做到这一点,您需要使用ReadProcessMemory,并且不必费心去转换——您想要使用原始的偏移量,而不是用sizeof(DWORD)来乘以偏移量(DWORD),这就是用DWORD*值做指针算术时所发生的事情。

However, I'd strongly caution you against digging into implementation details like this, which can and do change between different versions of Windows. Keep in mind that the article you linked to was written in 2004, and it was just a proof-of-concept, so there are likely to be lots of hidden gotchas and unexpected problems in Vista, Windows 7, Windows 8, and future versions.

但是,我强烈建议您不要深入挖掘实现细节,这是可以的,并且可以在不同版本的Windows之间进行更改。请记住,您链接到的文章是在2004年编写的,它只是一个概念验证,所以可能会有很多隐藏的问题,在Vista、Windows 7、Windows 8和将来的版本中会出现一些意想不到的问题。

The Windows API does not have a function that behaves like Unix's fork(2) function, and as a result, you should try as much as possible to avoid needing to fork -- use CreateProcess instead of fork+exec etc. The Cygwin implementation of fork is ugly and slow, and it can fail unexpectedly due to DLL memory mapping issues.

Windows API函数没有像Unix的叉(2)函数,因此,你应该尽可能地避免需要叉——用CreateProcess代替叉+ exec等等的Cygwin实现叉是丑陋和缓慢,它可以意外失败由于DLL内存映射问题。

#3


1  

In addition to what others have said, there is a much simplier way to retreive the base address of the process's PEB structure. Use NtQueryInformationProcess() instead, setting its ProcessInformationClass parameter set to ProcessBasicInformation. The output will be a PROCESS_BASIC_INFORMATION structure:

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

The second member is what you are looking for.

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

#1


2  

Note that the instructions say "at [EBX+8]". The brackets mean the value at that address location. There are several problems with

注意,说明书上写着“at [EBX+8]”。括号表示地址位置的值。有几个问题。

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

First, the compiler doesn't pay attention spacing, only to parenthesizing, so this means

首先,编译器不注意间距,只注意圆括号,所以这意味着。

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

which is wrong because the 8 is counting DWORDs, rather than bytes. You want

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

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

but this just gets you the address where the baseAddress is stored, not the value of the baseAddress. For that you need

但这只会告诉你,baseAddress存储的地址,而不是baseAddress的值。为你需要

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

However, this only works if contx.Ebx refers to an address in your process, but every process has its own address space, and you need to access the address space of the suspended process; for that you need to use ReadProcessMemory ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx ):

然而,这只有在contx的情况下才有效。Ebx是指您的进程中的一个地址,但是每个进程都有自己的地址空间,您需要访问被挂起进程的地址空间;因为您需要使用ReadProcessMemory (http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553% 28v=vs.85%29aspx):

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

#2


2  

You're just doing pointer arithmetic, you're not actually dereferencing the memory, in this line:

你只是在做指针运算,你实际上并没有取消记忆,在这一行:

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

You're just adding 8*sizeof(DWORD) = 32 to the value of contx.Ebx. What you really want to do is read the data at the address of contx.Ebx+8 in the new process's address space. In order to do that, you need to use ReadProcessMemory, and don't bother to cast -- you want to use raw offsets, not offsets multiplied by sizeof(DWORD), which is what happens when you do pointer arithmetic with DWORD* values.

你只是将8*sizeof(DWORD) = 32添加到contx.Ebx的值。你真正想做的是在contx的地址读取数据。Ebx+8在新进程的地址空间。为了做到这一点,您需要使用ReadProcessMemory,并且不必费心去转换——您想要使用原始的偏移量,而不是用sizeof(DWORD)来乘以偏移量(DWORD),这就是用DWORD*值做指针算术时所发生的事情。

However, I'd strongly caution you against digging into implementation details like this, which can and do change between different versions of Windows. Keep in mind that the article you linked to was written in 2004, and it was just a proof-of-concept, so there are likely to be lots of hidden gotchas and unexpected problems in Vista, Windows 7, Windows 8, and future versions.

但是,我强烈建议您不要深入挖掘实现细节,这是可以的,并且可以在不同版本的Windows之间进行更改。请记住,您链接到的文章是在2004年编写的,它只是一个概念验证,所以可能会有很多隐藏的问题,在Vista、Windows 7、Windows 8和将来的版本中会出现一些意想不到的问题。

The Windows API does not have a function that behaves like Unix's fork(2) function, and as a result, you should try as much as possible to avoid needing to fork -- use CreateProcess instead of fork+exec etc. The Cygwin implementation of fork is ugly and slow, and it can fail unexpectedly due to DLL memory mapping issues.

Windows API函数没有像Unix的叉(2)函数,因此,你应该尽可能地避免需要叉——用CreateProcess代替叉+ exec等等的Cygwin实现叉是丑陋和缓慢,它可以意外失败由于DLL内存映射问题。

#3


1  

In addition to what others have said, there is a much simplier way to retreive the base address of the process's PEB structure. Use NtQueryInformationProcess() instead, setting its ProcessInformationClass parameter set to ProcessBasicInformation. The output will be a PROCESS_BASIC_INFORMATION structure:

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

The second member is what you are looking for.

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