1

I am trying return to libc trick with the following simple code:

#define SYSTEM_CALL_ADDR 0xb7ec5e50  /*my system call addr*/
#define EXIT_CALL_ADDR  0xb7ebbb80   /*my exit call addr*/
char shell[] = "/bin/sh";

int main(){
 int* p; 
 p = (int*)&p + 2;
 *p = SYSTEM_CALL_ADDR;

 p = (int*)&p + 3;
 *p = EXIT_CALL_ADDR;

 p = (int*)&p + 4;
 *p = shell;

 return 1;
}

Interestingly when I run this program, it ends with "Segmentation error", but if I debug it using gdb and run it step by step, it's totally fine, spawning a shell and then exiting program. Anybody meet this situation? or could somebody please guide me how to correct this? Thanks first. I am on ArchLinux kernel:2.6.33, gcc 4.5.0.

iceagle
  • 1,507
  • 2
  • 13
  • 13
  • If you're playing around with exploits like this, you should probably turn off address space layout randomization to make it easier. `echo '0' > /proc/sys/kernel/randomize_va_space` – R.. GitHub STOP HELPING ICE Nov 14 '10 at 17:50
  • could you provide some more details about what you're code is supposed to do? if it's an exploit, as @R suggests, it's like you're trying to start a shell, are you? – Kevin Nov 14 '10 at 21:15
  • Thanks allyou guys. First I have done turning off the ALSR and I am sure the system/exit call addrs are correct. – iceagle Nov 15 '10 at 01:52
  • @Kevin, yes I am trying to start a shell from system("/bin/sh") libc call. – iceagle Nov 15 '10 at 01:53

3 Answers3

3

gdb disables some of the buffer overflow exploit mitigation techniques such as ProPolice and address space layout randomization (ASLR).

jilles
  • 10,509
  • 2
  • 26
  • 39
1

gdb sets the ADDR_NO_RANDOMIZE personality(2) to facilitate debugging.

ninjalj
  • 42,493
  • 9
  • 106
  • 148
  • do you mean it's ASLR that's responsible for the crash. but I have already disabled it. thanks – iceagle Nov 15 '10 at 02:27
  • A disassembly of main's prologue would be interesting. Also, could you add `printf("system=%p exit=%p &p=%p\n", **(void ***)((char *)system + 2), **(void ***)((char *)exit + 2), &p);` ? – ninjalj Nov 15 '10 at 22:05
0

The crash occurs because your declaration of variable 'p' allocates only enough space on your stack for a single (int *) pointer, but then you stuff values into (&p + 2), etc. so you end up overwriting who-knows-what. It behaves differently with or without gdb because the who-knows-what part just might not be critical in one environment but is critical in the other.

You might be able to "fix" your program by making sure that the space you're about to trash isn't anything critical.

int main(){
 int* p;
 char junk[100];    /* ADD THIS */

Now, the space following the storage allocated for 'p' will (most likely) be the junk char array, which you can get away with overwriting. (At least that "fixes" the program on my particular Linux system, when I compile with "gcc -O0 -g").

All that said -- the method you're using there is not in any way portable or safe. The compiler makes no promise that its going to arrange the storage allocations in the particular order that we declare them. Also, compiling with different optimization switches may change the behavior. So while this might be an interesting exercise, you should certainly not expect this sort of method to work consistently.

Manually manipulating the C stack this way is a BAD IDEA!

Kamal
  • 7,160
  • 2
  • 21
  • 12
  • Of course it is a bad idea, but that's not the question here. – jilles Nov 14 '10 at 16:29
  • cf my comment for the question, maybe I missed one point-- with your `junk` space, don't you just create some 'allocated' space in the stack, then put values in `junk[1-3] and exit, with nothing done *at all*? – Kevin Nov 14 '10 at 21:19