将字符串强制转换为函数

Casting a character string as a function

本文关键字:函数 转换 字符串      更新时间:2023-10-16

我试图学习从程序内执行shellcode,但我甚至不能得到最基本的代码运行。下面的代码应该在终端运行时退出:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/mman.h>
char exitcode[] = "xb0x01x31xdbxcdx80";
int main() {
    int (*func)();
    func = (int (*)())exitcode;
    (int)(*func)();
    return 0;
}

但是我得到的是一个段错误。GDB说它发生在程序访问exitcode [at (int)(*func)();,但我不确定为什么这会造成问题。我用的是64位的Linux Mint操作系统。如有任何帮助,不胜感激。

现代操作系统使用内存保护。内存页和文件一样具有访问权限:可读、可写、可执行。程序的数据段通常在一个不可执行的页面中,试图执行它会导致段错误。

如果你想在linux上执行动态编写的二进制代码,你首先必须使用mmap()映射一个可以写入的页面,然后将你的代码放在那里,然后使用mprotect()将其更改为只读,可执行的。然后你可以跳到那里。

例如,你可以阅读这篇文章了解详情。

EDIT:如果这是关于安全漏洞,请注意堆栈现在通常也是不可执行的…所以所有这些旧的"黑客教程"将不再有效。如果您对新技术感兴趣,请阅读面向返回的编程

代码必须标记为可执行代码。一种方法是将二进制机器码复制到可执行缓冲区中。

#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
char exitcode[] = "xb0x01x31xdbxcdx80";
int main(int argc, char **argv)
{   
    void *buf;
  /* copy code to executable buffer */    
  buf = mmap (0,sizeof(exitcode),PROT_READ|PROT_WRITE|PROT_EXEC,
              MAP_PRIVATE|MAP_ANON,-1,0);
  memcpy (buf, exitcode, sizeof(code));
  /* run code */
  int i = ((int (*) (void))buf)();
  printf("OK. returned: %d", i);
return 0;
}

你的shellcode是:

mov    $0x1,%al
xor    %ebx,%ebx
int    $0x80

有两个问题:

  1. Syscall 0x1在64位上是sys_write(但在32位上是sys_exit)
  2. 你应该分配给%rax,而不是%al。%rax将包含高位数的剩余部分。

我遇到了这个问题,并寻找了很多来解决它。

你必须使用这段代码来编译你的C代码(禁用堆栈保护,使其可执行):

gcc -fno-stack-protector -z execstack -o hello hello.c

在Kali 32/64位测试。

好运