问题
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;
}
The string f contains the machine code of the following function.
int f(int*a, int*b)
{
return *a-*b;
}
c.f.:
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
This is compiled using:
gcc test.c -Wall -Werror
./a.out
Segmentation fault
The expected output is -2 - how can I get it to work?
回答1:
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.
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[].
From Smashing The Stack For Fun And Profit, by Aleph One:
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.
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.
Example:
/* 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;
}
yields:
$ gcc test.c -Wall && ./a.out
-2
(Fedora 16, gcc 4.6.3)
回答2:
If I understand you correctly you're trying to run simple code that is not in text space, but instead is in your initialized static storage? If this is failing then there can only be three reasons: either your code was initialized incorrectly (unlikely in this simple case), your data space has been stepped on (doesn't look like it in this simple case), or your system is preventing it as a security measure (quite likely since what you're trying to do is fairly atypical, primarily used for buffer overflow exploitation).
来源:https://stackoverflow.com/questions/12446965/segmentation-fault-when-byte-coding-a-function