๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[Dreamhack] Misc/Wargame&CTF

[Dreamhack] CTF Season5 Round #2 - addition-quiz

by Yun2๐Ÿ‘ 2024. 1. 28.
๋ฐ˜์‘ํ˜•

๐Ÿ›Ž๏ธ Access

๋žœ๋คํ•œ 2๊ฐœ์˜ ์ˆซ์ž๋ฅผ ๋”ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ž…๋ ฅ ๊ฐ’๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ 50๋ฒˆ ๋ฐ˜๋ณตํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ๋ชจ๋‘ ์ผ์น˜ํ•˜๋ฉด flag ํŒŒ์ผ์— ์žˆ๋Š” ํ”Œ๋ž˜๊ทธ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์•Œ๋งž์€ ๊ฐ’์„ ์ž…๋ ฅํ•˜์—ฌ ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜์„ธ์š”.
ํ”Œ๋ž˜๊ทธ ํ˜•์‹์€ DH{…} ์ž…๋‹ˆ๋‹ค.
Hint) pwntools

 

 

๐Ÿ‘พ Exploit Algorithm & Payload

> chall.c

๋”๋ณด๊ธฐ
// Name: chall.c
// Compile Option: gcc chall.c -o chall -fno-stack-protector

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

#define FLAG_SIZE 0x45

void alarm_handler() {
    puts("TIME OUT");
    exit(1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
}

int main(void) {
    int fd;
    char *flag;

    initialize();
    srand(time(NULL)); 

    flag = (char *)malloc(FLAG_SIZE);
    fd = open("./flag", O_RDONLY);
    read(fd, flag, FLAG_SIZE);
    close(fd);

    int num1 = 0;
    int num2 = 0;
    int inpt = 0; 

    for (int i = 0; i < 50; i++){
        alarm(1);
        num1 = rand() % 10000;
        num2 = rand() % 10000;
        printf("%d+%d=?\n", num1, num2);
        scanf("%d", &inpt);

        if(inpt != num1 + num2){
            printf("Wrong...\n");
            return 0;
        }
    } 
    
    puts("Nice!");
    puts(flag);

    return 0;
}

> chall

> flag

 

 

#1


 

: ๋ฌธ์ œ๋ฅผ ๋‹ค์šด๋ฐ›์•„์„œ ํ™•์ด๋ƒˆ๋”๋‹ˆ ์ด๋ฏธ ์ปดํŒŒ์ผ ํŒŒ์ผ์ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ์ฝ”๋“œ ์–ด์…ˆ ๋ถ„์„์ด ๊ฐ€๋Šฅํ–ˆ๋‹ค.
(๋งŒ์•ฝ ์—†์—ˆ๋‹ค๋ฉด gcc chall.c -o chall -fno-stack-protector)

: ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ช…๋ น์–ด์˜ ์‹คํ–‰๋งˆ๋‹ค ๋ ˆ์ง€์Šคํ„ฐ, ์Šคํƒ, ์‹คํ–‰ ์ค‘์ธ ์ฝ”๋“œ์˜ ์ •๋ณด...๋ฅผ ๋‹ค์–‘ํ•˜๊ฒŒ ํ™•์ธํ–ˆ๋‹ค.

 

readelf -h chall

: ์ง„์ž…์  ๊ฐ’์„ ํ™•์ธํ•˜๊ณ  ๋ถ„์„์„ ์‹œ์ž‘ํ–ˆ๋‹ค.

 

 

#2


: ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ–ˆ์„ ๋•Œ, alarm_handler()์ด ์‚ฌ์šฉ์ž์˜ ์ œํ•œ ์‹œ๊ฐ„์„ ๋ถ€์—ฌํ•˜๊ณ , ๋ฌด์ž‘์œ„ ์ƒ์„ฑ๋œ ๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•œ ๊ฐ’์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž…๋ ฅ๋ฐ›๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

: ์ฒ˜์Œ์—๋Š” ๋ฐ˜๋ณต๋ฌธ์„ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  jumpํ•œ๋‹ค๋ฉด ๋ฐ”๋กœ flag๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ์‹ถ์—ˆ์ง€๋งŒ ์–ป์ง€ ๋ชปํ–ˆ๋‹ค.

: ๊ทธ๋Ÿฐ๋ฐ ์‚ฌ์šฉ์ž๊ฐ€ 50๋ฒˆ์˜ ๋ง์…ˆ ๋ฌธ์ œ๋ฅผ ๋ชจ๋‘ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ’€๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋‚˜ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ถœ๋ ฅํ•˜์ง€ ์•Š์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

* issue) ์ฒ˜์Œ ๋ฐ˜๋ณต๋ฌธ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  flag๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ˜๋ณต๋ฌธ ์‹œ์ž‘์ ๊ณผ ๋๋‚˜๋Š” ์ง€์ ์„ ์ค‘๋‹จ์ ์œผ๋กœ ์žก์€ ํ›„, exploit code๋ฅผ ์ž‘์„ฑํ–ˆ์œผ๋‚˜ ์˜ณ์ง€ ์•Š์Œ์„ ๊นจ๋‹ฌ์•˜์Œ.

 

 

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


๋”๋ณด๊ธฐ
from pwn import *

# ์›๊ฒฉ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ
conn = remote(['address'], [port number])

for _ in range(50):
    question = conn.revline().decode().strip()
    num_str, _ = quetion.split("=")
    num1, num2 = map(int, num_str.split('+'))
    conn.sendline(str(num1 + num2))

print(conn.revall().decode())

1) from pwn import *: pwn ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž„ํฌํŠธ. ๋ฐ”์ด๋„ˆ๋ฆฌ ์ต์Šคํ”Œ๋กœ์ดํ…Œ์ด์…˜๊ณผ ๋ฆฌ๋ฒ„์Šค ์—”์ง€๋‹ˆ์–ด๋ง์„ ์œ„ํ•œ ๋„๊ตฌ ์ œ๊ณต.

2) conn = remote(['address'], [port number]): ์›๊ฒฉ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ. 'address'์™€ 'port number'๋Š” ์‹ค์ œ ์„œ๋ฒ„์˜ ์ฃผ์†Œ์™€ ํฌํŠธ ๋ฒˆํ˜ธ.

3) question = conn.revline().decode().strip(): ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ํ•œ ์ค„ ์ˆ˜์‹ ํ•˜๊ณ , ์ด๋ฅผ ๋””์ฝ”๋“œํ•˜์—ฌ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜, ์–‘ ๋์˜ ๊ณต๋ฐฑ์„ ์ œ๊ฑฐ.

4) num_str, _ = question.split("="): ์ˆ˜์‹ ํ•œ ๋ฌธ์ž์—ด์„ '=' ๊ธฐํ˜ธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„๋ฆฌ, ๋ถ„๋ฆฌํ•œ ์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„์„ num_str์— ์ €์žฅ.

5) num1, num2 = map(int, num_str.split('+')): num_str์„ '+' ๊ธฐํ˜ธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„๋ฆฌ, ๋ถ„๋ฆฌํ•œ ๊ฐ ๋ถ€๋ถ„์„ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜, ์ด๋ฅผ num1๊ณผ num2์— ์ €์žฅ.

6) conn.sendline(str(num1 + num2)): num1๊ณผ num2๋ฅผ ๋”ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜, ์ด๋ฅผ ์„œ๋ฒ„์— ์ „์†ก.

7) print(conn.revall().decode()): ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ˆ˜์‹ ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋””์ฝ”๋“œํ•˜์—ฌ ์ถœ๋ ฅ.

 

๋ฐ˜์‘ํ˜•