2

I wrote the following program to teach myself about buffer overflow and memory registers:

#include <stdio.h>
int main(int argc, char *argv[])
{
    char name[400];
    strcpy(name,argv[1]);
    printf("Hello %s!\n",name);
    return 0;
}

It takes about 432 bytes to overflow it.

$ ./bof `python -c 'print "A"*432'`
Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
Segmentation fault: 11

The problem comes when I try to get it to execute actual shell code. I started by trying to find the offset using pattern_create.rb (included in the metasploit framework). However, instead of a segmentation fault I get EXC_BAD_ACCESS.

(gdb) run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6
Starting program: /Users/me/Downloads/bof Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6
Reading symbols for shared libraries +.............................. done
Hello Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6!

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 13 at address: 0x0000000000000000
0x0000000100000f0d in main ()
(gdb) 

I am running OS X 10.8.5. Does anyone have any ideas?

[EDIT]

When I run it with a whole bunch of nops I get the following output, which is different but still not what I was expecting:

(gdb) run `python -c 'print "0x90"*108'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /Users/me/Downloads/bof `python -c 'print "0x90"*108'`
Hello 0x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x900x90!

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00007fff8539d700 in tlv_load_notification ()
(gdb) 
735Tesla
  • 3,162
  • 4
  • 34
  • 57
  • did you turn off the protection? – aliep Oct 20 '13 at 00:16
  • If you mean compiling with -fno-stack-protector yes – 735Tesla Oct 20 '13 at 00:19
  • 1
    The command I have been using is: gcc bof.c -fno-stack-protector -mpreferred-stack-boundary=4 -o bof – 735Tesla Oct 20 '13 at 00:19
  • 1
    this may help http://thexploit.com/secdev/turning-off-buffer-overflow-protections-in-gcc/ – aliep Oct 20 '13 at 00:20
  • 1
    Thanks, I think I learned a few things from reading that but I am actually trying to overwrite rip so that it points to some executable code – 735Tesla Oct 20 '13 at 00:25
  • try this : gcc -g -fno-stack-protector -D_FORTIFY_SOURCE=0 -o bof bof.c – aliep Oct 20 '13 at 00:26
  • I tried compiling again with -D_FORTIFY_SOURCE=0, nothing changes – 735Tesla Oct 20 '13 at 00:28
  • maybe it's natural, it's trying to execute the overflowed string, and there's no such an instruction... – aliep Oct 20 '13 at 00:33
  • Something interesting: I get illegal instruction when I supply exactly 433 bytes. – 735Tesla Oct 20 '13 at 00:42
  • exaclty, if you don't those flags on compile time, after execution you get and Abort trap:6 but after using those flags you get segmentation fault, it's because cpu is trying to execute the overflowed string, but it's not a valid instruction. you may try "nop" instruction and see what happens next. i think the code for nop is 0x0 – aliep Oct 20 '13 at 00:45

1 Answers1

1

As the program argument[1] gets long, OP is experiencing various Undefined Behavior (UB).

int main(int argc, char *argv[]) {
  char name[400];
  strcpy(name,argv[1]);
  printf("Hello %s!\n",name);

Once argv[1] has 400 characters or more, strcpy(name,argv[1]); begins to copy data into various unowned portions of memory.

OP experienced seg fault with an input string length of 432, but since it is UB, it may change tomorrow, with different data, on another machine. OP did not explain how this data was set. I assume the argv[1] was set via OP's development environment.

OP ran in a shell and had different results "EXC_BAD_ACCESS". Since it is UB, anything can happen. This type of error is certainly an expected type of UB given the buffer overrun.

OP says: "The problem comes when I try to get it to execute actual shell code." I would assert the problem simple happens when the program executes strcpy(name, TooMuchData).

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    Running ./bof2 `python -c 'print "\x90"*433'` gives the same output as running ./bof2 `python -c 'print "q"*433'` It is: $ ./bof2 `python -c 'print "q"*433'` 68 Segmentation fault: 11 – 735Tesla Oct 20 '13 at 01:01
  • 1
    I am confused why it gives me the same error regardless of whether I give it a valid opcode. – 735Tesla Oct 20 '13 at 01:04
  • 1
    Global and `main()` memory may not reside where you think. If you want your overrun data on a classic stack, try putting `strcpy()` in a function, not in main. Of course, one could dump the executable and analyze the code there. – chux - Reinstate Monica Oct 20 '13 at 01:12