0

关于同一消息还有其他问题,但是当我尝试执行调用某些函数的机器代码字符串时,我似乎特别遇到了这个问题。在我的情况下,我调用了 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) 的调用将引发此异常。

这是在 VS2010 中使用 /GS- 编译的 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);

}
4

1 回答 1

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 将在哪个地址执行,可能会使用一些与位置无关的技巧。

于 2012-12-11T02:46:53.903 回答