帮我理解这段C代码 (*(void(*) ()) scode) ()

2024-01-06

Source: http://milw0rm.org/papers/145 http://milw0rm.org/papers/145

#include <stdio.h>
#include <stdlib.h>

int main()
{
 char scode[]="\x31\xc0\xb0\x01\x31\xdb\xcd\x80";
 (*(void(*) ()) scode) ();
}

本文是关于Linux平台上的shellcode的教程,但是没有解释以下语句如何实现“(*(void(*) ()) scode) ();”有效。我正在使用《C 语言编程参考,2ed by Brian.W.Kernighan, Dennis.M.Ritchie》一书来查找答案,但没有找到答案。也许有人可以指出正确的方向,也许一个网站,另一本 C 参考书,我可以在那里找到答案。


其机器代码(编译后的汇编指令)在scode然后它转换为可调用的 void 函数指针并调用它。GMan https://stackoverflow.com/questions/1469559/help-me-understand-this-c-code-void-scode/1469628#1469628展示了一种等效的、更清晰的方法:

typedef void(*void_function)(void);
int main()
{
  char scode[]="\x31\xc0\xb0\x01\x31\xdb\xcd\x80";
  void_function f = (void_function)scode;
  f(); //or (*f)();
}

scode包含 x86 机器代码,可反汇编为(谢谢迈克尔·伯格 https://stackoverflow.com/questions/1469559/help-me-understand-this-c-code-void-scode/1469577#1469577)

31 c0        xor    %eax,%eax
b0 01        mov    $0x1,%al
31 db        xor    %ebx,%ebx
cd 80        int    $0x80

这是 Linux 中系统调用的代码(中断 0x80)。根据系统调用表 http://bluemaster.iu.hio.no/edu/ca/lin-asm/syscalls.html,这就是调用sys_exit()系统调用(eax=1),参数为 0(在ebx)。这会导致进程立即退出,就好像它调用了一样_exit(0) http://linux.die.net/man/2/_exit.

乔纳森·莱夫勒 https://stackoverflow.com/questions/1469559/help-me-understand-this-c-code-void-scode/1469593#1469593指出这最常用来调用外壳代码 http://en.wikipedia.org/wiki/Shellcode,“用作利用软件漏洞的有效负载的一小段代码。”因此,现代操作系统采取措施来防止这种情况发生。

如果堆栈不可执行,则此代码将严重失败。 shell代码被加载到堆栈中的局部变量中,然后我们跳转到该位置。如果堆栈不可执行,那么一旦 CPU 尝试执行代码,就会发生某种 CPU 故障,并且控制权将转移到内核的中断处理程序中。然后内核将以异常方式终止该进程。堆栈可能不可执行的一种情况是,如果您在支持的 CPU 上运行物理地址扩展 http://en.wikipedia.org/wiki/Physical_Address_Extension,并且您在页表中设置了 NX(不可执行)位。

某些 CPU 上也可能存在指令缓存问题——如果指令缓存尚未刷新,CPU 可能会读取过时的数据(而不是我们显式加载到堆栈中的 shell 代码)并开始执行随机指令。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

帮我理解这段C代码 (*(void(*) ()) scode) () 的相关文章

随机推荐