为什么kernel32.dll 中的WriteProcessMemory 会这样做?(ASM)

逆向工程 视窗 部件
2021-06-26 18:09:33

有人说这样做是为了避免扫描 WPM 调用:

__declspec(naked) BOOL WINAPI SafeWriteProcessMemory(HANDLE hProcess,
    LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize,
    SIZE_T *lpNumberOfBytesRead)
{
    __asm
    {
            mov edi, edi
            push ebp
            mov ebp, esp
            pop ebp
            mov eax, WriteProcessMemory
            add eax, 6
            jmp eax
    }
}

我把它放在一个程序中并在olly中调试它。我看着kernel32.WriteProcessMemory我们正在使用add eax, 6从这里跳转:

MOV EDI,EDI                              ; BOOL kernel32.WriteProcessMemory(hProcess, ...)
PUSH EBP
MOV EBP,ESP
POP EBP
JMP <JMP.&API-MS-Win-Core-Memory-L1-1-0. ; Jump to KERNELBASE.WriteProcessMemory

到那里。有效地跳过两者之间的指令。我们在自己的调用中执行这些指令。但我不明白为什么要执行这些指令。我们正在推EBP入堆栈,ESP进入EBP,然后EBP从堆栈中恢复那实际上不应该做任何事情。

我逐条指令调试它,但仍然无法弄清楚为什么要这样做。

是不是和windowsmov edi,edi在函数开头的无用s允许跳转补丁有关系?

2个回答

该意图可能会导致在第一条WriteProcessMemory()不触发指令上设置断点

但是,这是一种非常不安全的方法,并且如果 API 函数的序言发生更改,则很容易中断。

这是“窃取字节”技术,其中函数的前几个字节被复制到远程位置并从那里执行,然后从复制的字节之后的位置调用原始函数。

跳过函数的前几个字节的目的是让您可以在不被“检测到”的情况下调用函数体。也就是说,任何在开始时绕过函数的代码都将被绕过。

在您的示例中,EBP 操作毫无意义。这些指令存在于原始函数中,以便为例程提供熟悉的签名,例如,绕开代码(但可能由于还包含热补丁支持而被破坏)。请注意,随着 kernelbase.dll 的引入,在 Windows 7 之前,该位置不存在 POP 指令。以前,真正的函数体会遵循 MOV 指令。