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

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

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

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

我不完全知道这些指令会做什么,但是x00指令似乎没有问题。将EIP切换到程序中的任何其他位置似乎都会引起问题,但是当我将EIP指向该阵列的地址时,我在EIP的该位置收到一些“访问冲突”异常。

为什么会出现此错误?这是由于某种Windows保护机制引起的吗?还是Windows无法以这种字符串形式运行指令?您如何获得执行这些指令的程序?

最佳答案

我猜你如果不使用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


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

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

void f( void ) { return; };


由VC ++在调试模式下编译。

#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的已分配内存页。

关于c - 内联程序集在Visual C 2010中发生访问冲突,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13799472/

10-12 16:09