机器指令中退出(0)处的“访问违规读数”?

时间:2012-12-11 02:39:50

标签: c visual-c++ assembly

关于同一条消息有other个问题,但当我尝试执行一系列调用某些函数的机器代码时,我似乎特意遇到了这个问题。在我的情况下,我调用exit(0),它在同一程序中被调用为典型的C时工作正常。但是,作为练习,我将EIP设置为某些机器代码的地址(您可以称之为“shellcode”),例如

const char code[] = 
"\x6A\x00"      // push        0"
"\xFF\x15\x00\x00\x00\x00"  //system call, 'read access violation':   call dword ptr [__imp__exit]
"\x5D"  //pop ebp    
"\xC3"; //ret

我将收到消息“访问冲突读取位置0x00000000。”。 “\ x6A \ x00”指令将运行,但对exit(0)的调用将抛出此异常。

这是使用/ GS-在VS2010中编译的C,并且还运行具有执行权限的“shellcode”,但是仍然存在某种不可执行的内存或堆栈保护?为什么这条指令会导致错误?

    int main() 
{ 

    void *exec = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, code, sizeof(code));
//EIP = exec in debug->immediate
    exit(0);

}

1 个答案:

答案 0 :(得分:1)

如果你反汇编你的shellcode,你会得到类似的东西(AT& T语法):

00000000 <_code>:
   0:   6a 00                   push   $0x0
   2:   ff 15 00 00 00 00       call   *0x0
   8:   5d                      pop    %ebp
   9:   c3                      ret

call指令通过地址0进行内存间接跳转:它从内存地址0加载目标并跳转到该位置。由于内存地址0无效(在极少数情况下它可能有效,但这也不例外),会导致访问冲突。

通常,在编译C代码时,外部函数的跳转会被占位符替换,并且链接器会在链接时填充这些占位符。当您在运行时生成shellcode时,您没有链接器的帮助,因此您必须自己完成。您需要弄清楚您想要的目标地址是什么,并直接在shellcode中填写,如果您不确切知道shellcode将在哪个地址执行,可能会使用一些与位置无关的技巧。