0

我有一个简单的 C 语言程序,带有编译器开关:/GS-

这只是将 EIP 更改为机器代码字符串位置的概念证明。

假设我们设置 EIP = 0x012f5000,这会将 EIP 置于以下数组的地址:

char code[] = "\x00\x00\x8B\x00\x00";

我不确切知道这些指令会做什么,但 x00 指令似乎是 noops。将 EIP 切换到程序中的任何其他位置似乎会导致问题,但是当我将 EIP 指向该数组的地址时,我会在 EIP 的该位置遇到一些“访问冲突”异常。

为什么我会收到此错误?这是因为某种 Windows 保护机制吗?还是 Windows 无法以这种字符串形式运行指令?你如何让程序执行这些指令?

4

2 回答 2

2

如果不是我的答案不正确,我猜你使用 x86 32 位机器代码。

您的机器代码提供以下内容

0000          ADD BYTE PTR DS:[EAX],AL
8B00          MOV EAX,DWORD PTR DS:[EAX]
00XX          ADD BYTE PTR ???  ; depends on the next byte

如您所见,如果您尝试执行此操作,它会尝试访问地址中的内存eaxret它也不会以 a或其他东西结尾,因此它会直接运行而无需关心接下来的内容。在大多数情况下,这会崩溃。无论如何,您也可能无法执行 DATA 段中定义的代码。

如果你想执行一些 shellcode,你可以试试下面这个简单的模板。这个想法是在堆栈上创建代码并在那里执行它。给定的机器代码功能没有很好地实现,但至少是正确的,不会导致崩溃。它相当于 C 代码

void f( void ) { return; };

VC++在Debug模式下编译。

#include <stdio.h> 

int main() 
{ 
    const char code[] = "\x55\x8B\xEC\x81\xEC\xC0\x00\x00" 
    "\x00\x53\x56\x57\x8D\xBD\x40\xFF" 
    "\xFF\xFF\xB9\x30\x00\x00\x00\xB8" 
    "\xCC\xCC\xCC\xCC\xF3\xAB\x5F\x5E" 
    "\x5B\x8B\xE5\x5D\xC3"; 

    printf("Start execution\r\n"); 
    ((void (*)())code)(); 
    printf("End execution\r\n"); 
    _getch(); 
}

如果上述方法不起作用,您可以尝试。

#include "stdafx.h"
#include <stdio.h> 
#include <Windows.h>

int main() 
{ 
    const char code[] = "\x55\x8B\xEC\x81\xEC\xC0\x00\x00" 
    "\x00\x53\x56\x57\x8D\xBD\x40\xFF" 
    "\xFF\xFF\xB9\x30\x00\x00\x00\xB8" 
    "\xCC\xCC\xCC\xCC\xF3\xAB\x5F\x5E" 
    "\x5B\x8B\xE5\x5D\xC3"; 

    void *exec = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, code, sizeof(code));

    printf("Start execution\r\n"); 
    ((void(*)())exec)();
    printf("End execution\r\n"); 
    //_getch(); 
}

这个想法是使用带有标志的分配内存页面PAGE_EXECUTE_READWRITE

于 2012-12-10T11:12:11.353 回答
0

费马的回答很好,但我更喜欢这个

__asm { jmp [exec] }
于 2012-12-27T05:27:29.437 回答