字节编码函数时出现分段错误? [英] Segmentation fault when byte coding a function?

查看:60
本文介绍了字节编码函数时出现分段错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行以下 C 程序(在 Ubuntu 中使用 gcc 编译)时出现分段错误.

I get a segmentation fault when I run the following C program (compiled with gcc in Ubuntu).

#include <stdio.h>

char f[] = "\x55\x48\x89\xe5\x48\x89\x7d\xf8\x48\x89\x75\xf0\x48\x8b\x45\xf8\x8b\x10\x48\x8b\x45\xf0\x8b\x00\x89\xd1\x29\xc1\x89\xc8\xc9\xc3";

int main()
{
    int (*func)();
    func = (int (*)()) f;

    int x=3,y=5;
    printf("%d\n",(int)(*func)(&x,&y));
    return 0;
}

字符串 f 包含以下函数的机器码.

The string f contains the machine code of the following function.

int f(int*a, int*b)
{
    return *a-*b;
}

参考:

f.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <f>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
   8:   48 89 75 f0             mov    %rsi,-0x10(%rbp)
   c:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  10:   8b 10                   mov    (%rax),%edx
  12:   48 8b 45 f0             mov    -0x10(%rbp),%rax
  16:   8b 00                   mov    (%rax),%eax
  18:   89 d1                   mov    %edx,%ecx
  1a:   29 c1                   sub    %eax,%ecx
  1c:   89 c8                   mov    %ecx,%eax
  1e:   c9                      leaveq 
  1f:   c3                      retq   

这是使用以下编译的:

gcc test.c -Wall -Werror
./a.out
Segmentation fault

预期的输出是 -2 - 我怎样才能让它工作?

The expected output is -2 - how can I get it to work?

推荐答案

显然以下建议不再适用于 gcc,因为现在数组数据位于单独的不可执行的只读 ELF 段中.

Apparantly below suggestion no longer works with gcc, as the array data nowadays gets located in a separate non-executable read-only ELF segment.

出于历史原因,我会把它留在这里.

I'll leave it here for historical reasons.

有趣的是,链接器并没有抱怨您尝试将 char f[] = "..."; 作为函数 f() 链接到您的应用.您尝试调用函数 f().有一个符号 f 链接到可执行文件,但令人惊讶的是它根本不是函数,而是一些变量.因此它无法执行它.这可能是由于堆栈执行保护机制所致.

Interestingly, the linker didn't complain that you attempt to link a char f[] = "..."; as a function f() to your application. You attempt to call a function f(). There is a symbol f linked to the executable, but suprisingly it is no function at all, but some variable. And thus it fails to execute it. This is likely due to a stack execution protection mechanism.

为了避免这种情况,显然,您只需要将字符串获取到进程内存的文本段.如果将字符串声明为 const char f[],则可以实现此目的.

To circumvent this, apparantly, you just need to get the string to the text segment of the process memory. You can achieve this, if you declare the string as const char f[].

来自 为了乐趣和利润而粉碎堆栈:

文本区域由程序固定并包含代码(指令)和只读数据.该区域对应于文本部分可执行文件.

The text region is fixed by the program and includes code (instructions) and read-only data. This region corresponds to the text section of the executable file.

由于const char[] 只读的,编译器将其与代码一起放入文本区域.从而绕过执行阻止机制,机器可以执行其中的机器代码.

As the const char[] is read-only, the compiler puts it together with the code into the text region. Thereby the execution prevention mechanism is circumvented and the machine is able to execute the machine code therein.

示例:

/* test.c */
#include <stdio.h>

const char f[] = "\x55\x48\x89\xe5\x48\x89\x7d\xf8\x48\x89\x75\xf0\x48\x8b\x45\xf8\x8b\x10\x48\x8b\x45\xf0\x8b\x00\x89\xd1\x29\xc1\x89\xc8\xc9\xc3";

int main()
{
    int (*func)();
    func = (int (*)()) f;

    int x=3,y=5;
    printf("%d\n",(int)(*func)(&x,&y));
    return 0;
}

产量:

$ gcc test.c -Wall && ./a.out
-2

(Fedora 16,gcc 4.6.3)

(Fedora 16, gcc 4.6.3)

这篇关于字节编码函数时出现分段错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆