2

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?

Jens Gustedt
  • 72,200
  • 3
  • 92
  • 164
Jo0o0
  • 531
  • 2
  • 15
  • 31
  • Where is the code for the `f` function? – Ed Heal Sep 16 '12 at 12:50
  • 1
    running such a code where you don't even really seem to know what it is doing with root priveledges (`sudo` etc) is irresponsible. You deserve that your own program eats your hard drive. – Jens Gustedt Sep 16 '12 at 15:03

2 Answers2

4

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.


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)

moooeeeep
  • 28,315
  • 14
  • 88
  • 166
0

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).

mah
  • 37,085
  • 9
  • 70
  • 91
  • i run sudo ./a.out getting the same error too – Jo0o0 Sep 16 '12 at 12:59
  • there is no overflow in the code, how to bypass security measure – Jo0o0 Sep 16 '12 at 13:03
  • 1
    Running as root does not let you bypass buffer overflow protection -- in fact, it's most importantly where you need it. As to forcing a bypass -- I'm not sure what system calls let you modify MMU protection bits. – mah Sep 16 '12 at 14:05