System Hacking/인터루드 스터디

260514 [picoCTF] format string 0

daaaay 2026. 5. 14. 18:50

문제

 
 
바이너리 말고 소스코드만 먼저 다운받기

format-string-0.c
0.00MB

 
 

풀이

문제 실행해보면 아래처럼 나온다.

 
아무거나 입력해보면 아니라고 나온다. 

 
 

format-string-0.c 코드 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 32
#define FLAGSIZE 64

char flag[FLAGSIZE];

void sigsegv_handler(int sig) {
    printf("\n%s\n", flag);
    fflush(stdout);
    exit(1);
}

int on_menu(char *burger, char *menu[], int count) {
    for (int i = 0; i < count; i++) {
        if (strcmp(burger, menu[i]) == 0)
            return 1;
    }
    return 0;
}

void serve_patrick();

void serve_bob();


int main(int argc, char **argv){
    FILE *f = fopen("flag.txt", "r");
    if (f == NULL) {
        printf("%s %s", "Please create 'flag.txt' in this directory with your",
                        "own debugging flag.\n");
        exit(0);
    }

    fgets(flag, FLAGSIZE, f);
    signal(SIGSEGV, sigsegv_handler);

    gid_t gid = getegid();
    setresgid(gid, gid, gid);

    serve_patrick();
  
    return 0;
}

void serve_patrick() {
    printf("%s %s\n%s\n%s %s\n%s",
            "Welcome to our newly-opened burger place Pico 'n Patty!",
            "Can you help the picky customers find their favorite burger?",
            "Here comes the first customer Patrick who wants a giant bite.",
            "Please choose from the following burgers:",
            "Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe",
            "Enter your recommendation: ");
    fflush(stdout);

    char choice1[BUFSIZE];
    scanf("%s", choice1);
    char *menu1[3] = {"Breakf@st_Burger", "Gr%114d_Cheese", "Bac0n_D3luxe"};
    if (!on_menu(choice1, menu1, 3)) {
        printf("%s", "There is no such burger yet!\n");
        fflush(stdout);
    } else {
        int count = printf(choice1);
        if (count > 2 * BUFSIZE) {
            serve_bob();
        } else {
            printf("%s\n%s\n",
                    "Patrick is still hungry!",
                    "Try to serve him something of larger size!");
            fflush(stdout);
        }
    }
}

void serve_bob() {
    printf("\n%s %s\n%s %s\n%s %s\n%s",
            "Good job! Patrick is happy!",
            "Now can you serve the second customer?",
            "Sponge Bob wants something outrageous that would break the shop",
            "(better be served quick before the shop owner kicks you out!)",
            "Please choose from the following burgers:",
            "Pe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak",
            "Enter your recommendation: ");
    fflush(stdout);

    char choice2[BUFSIZE];
    scanf("%s", choice2);
    char *menu2[3] = {"Pe%to_Portobello", "$outhwest_Burger", "Cla%sic_Che%s%steak"};
    if (!on_menu(choice2, menu2, 3)) {
        printf("%s", "There is no such burger yet!\n");
        fflush(stdout);
    } else {
        printf(choice2);
        fflush(stdout);
    }
}

 
 
메뉴 배열 안에 존재하는 입력값인지 확인하는 힘수이다. 

 
 
입력값이 메뉴에 있다면 취약점 부분이 출력된다.
출력된 문자 수가 64를 넘으면 serve_bob()을 실행한다. 

 
 
코드에 플래그 출력이 없다.
\
serve_patrick(): 출력 문자 길이 > 64이면 serve_bob() 호출한다.
int count = printf(choice1); -> 이부분이 포멧 스트링 버그다.
 
erve_bob(): 입력한 메뉴를 출력
printf(choice2); ← FSB(여기도 포맷 스트링 버그)
 
매번 입력값이 메뉴에 존재하는지 확인한다.
 
= 포맷 스트링 버그를 이용해서 플래그를 출력해야한다. 
 
 

취약점 

 
원래 printf는 printf("%s", choice1);과 같이 포맷 지정자(%s)를 사용해야 안전하다. 
하지만 위 코드처럼 변수를 직접 넣으면, 변수 안에 %d, %x, %n, %s 같은 포맷 스트링이 포함되어 있을 때 printf가 이를 명령어로 해석하게 된다. 
 

익스플로잇

메뉴 

menu1menu2
Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxePe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak

 
 
메뉴 중에 포맷 스트링이 포함된 것

serve_patrick()의 menu1 serve_bob()의 menu2
Gr%114d_CheeseCla%sic_Che%s%steak

 

  • %114d
    • 포맷 스트링이 필요한 인자가 주어지지 않았다. 하지만 최소 114만큼은 출력해야 하므로 공백 114자가 출력된다.
    • 여기서 출력된 길이를 int count에 저장하므로, count = 114 > 64가 되어 serve_bob()을 실행시킬 수 있다
  • %s %s %s
    • 마찬가지로 필요한 인자가 주어지지 않았기 때문에 의도치 않은 값(flag 포함됨)이 출력된다. 

 
따라서 첫 번째 입력은 Gr%114d_Cheese , 두 번째 입력은 Cla%sic_Che%s%steak 로 하면 된다.
 

플래그

 

picoCTF{7h3_cu570m3r_15_n3v3r_SEGFAULT_c8362f05}

 
정답이다

'System Hacking > 인터루드 스터디' 카테고리의 다른 글

260521 [Dreamhack] basic_exploitation_002  (0) 2026.05.21
260514 [picoCTF] format string 1  (0) 2026.05.14
[picoCTF] buffer overflow 2  (0) 2026.04.02
[picoCTF] buffer overflow 1  (0) 2026.04.02
[picoCTF:] buffer overflow 0  (0) 2026.04.02