본문 바로가기

Cryptography/Cryptography CTF

[Dreamhack] flag-shop

Description

flag-shop에 오신 것을 환영합니다! 주어진 10개의 아이템 중 flag를 정확히 골라서 구매해야 합니다. 제한 시간은 10초입니다.

제한 시간이 지나면 연결이 종료됩니다.

 

 

Source Code

import random
import time

if __name__ == "__main__":
    print("Welcome to flag-shop!")
    print("Find the flag among 10 items and buy it!")
    print("There are 50 rounds.")

    items = [
        "flag",
        "grape",
        "orange",
        "apple",
        "banana",
        "mango",
        "melon",
        "pineapple",
        "peach",
        "strawberry"
    ]

    start = time.time()
    for round in range(50):
        random.shuffle(items)
        print()
        for idx, item in enumerate(items):
            print(f"{idx}. {item}")
        print("Which item do you want to buy?")
        choice = int(input("> "))

        if items[choice] != "flag":
            print("Failed to get flag...")
            exit()
    end = time.time()

    if end - start >= 10:
        print("TIME OUT")
        exit()
    
    with open("flag", "r") as f:
        print(f.read())

 

 

 

소스코드 실행화면

 

 

소스코드 분석

  • 50번 반복하는 반복문을 10초 내로 수행하면 플래그를 얻을 수 있음
    for round in range(50):
        random.shuffle(items)
        print()
        for idx, item in enumerate(items):
            print(f"{idx}. {item}")
        print("Which item do you want to buy?")
        choice = int(input("> "))

        if items[choice] != "flag":
            print("Failed to get flag...")
            exit()
  • item 리스트를 랜덤하게 섞은 후 순서대로 품목을 출력
  • 사용자로부터 인덱스를 입력받고 그 값이 flag인지 확인
  • flag가 아니라면 플래그를 얻지 못하고 바로 종료

⇒ 플래그를 얻기 위해서는 랜덤하게 섞인 item들 중에서 flag가 몇 번째로 출력되는지 알아내어 그 인덱스를 입력해야함

 

 

풀이 코드

import sys
from pwn import *

if len(sys.argv) != 3:
    print("how to use: python3 solver.py [HOST] [PORT]")
    exit()
    
r = remote(sys.argv[1], int(sys.argv[2]))

r.recvuntil(b"There are 50 rounds.\n")

for round in range(50):
    r.recvline()
    response = 0
    for i in range(10):
        if b"flag" in r.recvline():
            response = i
            break
    r.sendlineafter(b"> ", str(response).encode())

r.interactive()

 

 

풀이 코드 분석

import sys
print(sys.argv)

//결과
['파일명', 인자1, 인자2, 인자3]

 

 

if len(sys.argv) != 3:
    print("how to use: python3 solver.py [HOST] [PORT]")
    exit()
  • 파일을 실행할 때 인자 3개를 전달하지 않으면 사용법을 알려준 후 프로그램을 종료한다.
  • python3 solver.py example.com 1234 ← 이런 식으로 실행하라는 의미

 

r = remote(sys.argv[1], int(sys.argv[2])) //remote(서버주소, 포트번호)
  • 인자로 받은 주소와 포트번호를 통해서 서버에 연결

 

r.recvuntil(b"There are 50 rounds.\n")
  • 서버 측에서 There are 50 rounds.라는 말을 할 때까지 기다린다.

for round in range(50):
    r.recvline()
    response = 0
    for i in range(10):
        if b"flag" in r.recvline():
            response = i
            break
    r.sendlineafter(b"> ", str(response).encode())
  • 50번 반복하는 반복문
  • r.recvline() - 한 줄 읽어오기 ⇒ 소스코드의 print() 때문에 실행
  • 0번부터 9번까지 줄을 읽고 만약 “flag”라는 문자열을 찾으면 response라는 변수에 인덱스를 저장하고 반복문 탈출

 

r.sendlineafter(b"> ", str(response).encode())

  • 서버가 > 라고 물어볼 때까지 기다림
  • 그리고 response를 문자열로 변환 후 바이트 형태로 서버에 보냄



'Cryptography > Cryptography CTF' 카테고리의 다른 글

[Dreamhack] No shift please!  (0) 2025.11.07
[Dreamhack] No sub please!  (0) 2025.11.06
[Dreamhack] chinese what?  (0) 2025.10.09
[Dreamhack] Exploit Tech: Meet-in-the-middle Attack  (0) 2025.10.09
[Dreamhack] addition-quiz  (0) 2025.10.09