[🥉 Bronze 2] 400개 난수 파일 더미에서 플래그 한 줄 찾기 — DreamHack Random String 풀이

2026-10-11·1분 읽기·

[🥉 Bronze 2] 400개 난수 파일 더미에서 플래그 한 줄 찾기 — DreamHack Random String 풀이

1024글자짜리 base62 난수 문자열 파일이 400개 쏟아진다. "이 많은 파일 속에서 플래그를 찾을 수 있겠냐"는 도발이 곧 풀이다. 통계로 파일 더미가 균등 난수임을 확인하고 쪼개져 있지 않다는 걸 검증한 뒤, 플래그 포맷을 재귀 grep 한 방으로 뽑는다. 포맷을 몰라도 base62에 없는 글자가 박힌 파일을 역추적하면 같은 파일이 나온다.

문제: DreamHack — Random String 분류: Misc 난이도: 🥉 Bronze 2 FLAG: WaRP{4ll_7x7_c7rl4?}

출제자가 붙인 설명은 한 줄이다. "Can you find the flag in this enormous bunch of files?" 압축을 풀면 output_aa부터 시작하는 파일이 끝도 없이 이어진다. 전부 똑같이 생긴 난수 문자열이라 하나씩 열어 봐서는 답이 없다. 이 문제는 "눈"이 아니라 "도구"로 푸는 문제라는 걸 알아채면 1분이면 끝나지만, 그 전에 데이터가 어떻게 생겼는지부터 제대로 보는 습관을 연습하기에 좋은 입문용 포렌식이다.

먼저 압축을 풀고 디렉토리가 어떻게 생겼는지 훑는다. 파일이 몇 개인지, 타입은 무엇인지, 한 파일의 앞부분은 어떤 모양인지 한 번에 본다.

echo "파일 개수:"; ls output_* | wc -l; echo "샘플:"; ls | sed -n "1,4p"; echo "타입/크기:"; file output_og; wc -c output_og; echo "앞 110글자:"; head -c 110 output_og; echo
output_* 파일 더미 정찰 — 파일 400개, 각 1024바이트 ASCII 텍스트 한 줄, 줄바꿈 없음. 샘플 파일명은 output_aa output_ab 식으로 두 글자 접미어가 붙고, output_og의 앞 110글자 미리보기에는 난수 사이에 WaRP 중괄호 플래그 문자열이 섞여 있는 게 보인다
output_* 파일 더미 정찰 — 파일 400개, 각 1024바이트 ASCII 텍스트 한 줄, 줄바꿈 없음. 샘플 파일명은 output_aa output_ab 식으로 두 글자 접미어가 붙고, output_og의 앞 110글자 미리보기에는 난수 사이에 WaRP 중괄호 플래그 문자열이 섞여 있는 게 보인다

파일은 400개, 전부 1024바이트짜리 한 줄 ASCII 텍스트다. 파일명은 output_aa, output_ab, … 처럼 알파벳 두 글자가 붙어 순서대로 늘어선다. 이 aa, ab, ac … 접미어는 리눅스 split 명령이 큰 파일을 조각낼 때 붙이는 바로 그 형식이다. 즉 출제자는 40만 글자짜리 난수 블롭 하나를 만들어 플래그를 끼워 넣고 split -b 1024로 1024바이트씩 잘라 400개 파일로 흩뿌렸을 가능성이 높다(400 × 1024 = 409,600바이트로 딱 떨어진다). 그렇다면 플래그는 조각 경계에 걸려 두 파일에 나뉘어 있을 수도 있다는 뜻이기도 하다 — 이 점은 뒤에서 다시 확인한다.

미리보기로 띄운 output_og는 공교롭게도 답이 들어 있는 파일이라 앞부분에서 플래그가 걸렸지만, 정찰 시점에는 400개 중 어느 파일이 그 파일인지 알 수 없다. 사람 눈으로 전부 확인하는 건 애초에 전제가 틀린 접근이다.


문제 개요

항목내용
문제명Random String
난이도🥉 Bronze 2
분류Misc
제공 파일 / 서버random_string/output_aa … output_* 400개 (서버 없음, 오프라인)
핵심 기법재귀 grep으로 플래그 포맷 검색 — 건초더미에서 바늘 한 개

풀이 흐름은 세 걸음이다. ① 파일 더미가 무엇인지 통계로 파악하고 ② 플래그가 한 파일에 통째로 들어 있는지 여러 파일에 쪼개져 있는지 가린 다음 ③ 그 한 파일을 grep으로 찾는다. 바로 grep부터 때려도 풀리지만, 데이터의 성질을 먼저 정의해 두면 포맷을 모를 때도 길이 열린다.



🔬 정찰 — 이 더미는 무엇인가

눈으로 못 읽는 데이터를 만났을 때 가장 먼저 할 일은 "정상이 무엇인지"를 수치로 정의하는 것이다. 파일 수와 크기가 고른지, 어떤 문자들이 쓰였는지, 글자 분포가 치우쳤는지를 보면 숨은 구조가 있는지 없는지가 드러난다. 아래 profile.py가 그걸 한 번에 뽑는다.

#!/usr/bin/env python3
# profile.py — 나눠진 파일 더미가 "진짜 랜덤 문자열"인지 통계로 확인한다.
import collections, math, os, glob
 
D = "../extracted/random_string"
files = sorted(glob.glob(os.path.join(D, "output_*")))
print(f"[files]  총 {len(files)}개")
 
sizes = collections.Counter(os.path.getsize(f) for f in files)
print(f"[size]   파일 크기 분포 = {dict(sizes)}  (모두 동일하면 1종류)")
 
data = "".join(open(f).read() for f in files)
charset = sorted(set(data))
print(f"[charset] 사용 문자 {len(charset)}종 = {''.join(charset)}")
 
freq = collections.Counter(data)
total = len(data)
H = -sum((c/total) * math.log2(c/total) for c in freq.values())
print(f"[entropy] 글자당 {H:.4f} bits (62종 균등이면 이론상 {math.log2(62):.4f})")
 
top = freq.most_common(3)
bot = freq.most_common()[-3:]
print(f"[bias]   최빈 {top}  /  최소 {bot}")
print(f"[total]  전체 {total:,} 글자 — 눈으로 플래그를 찾는 건 사실상 불가능")
python3 profile.py
profile.py 실행 결과 — 파일 400개가 모두 1024바이트로 크기 한 종류, 사용 문자 66종, 글자당 엔트로피 5.9543비트로 62종 균등 난수의 이론값 5.9542와 소수 셋째 자리까지 일치, 최빈 글자는 6775회로 특정 글자 쏠림이 없고 최소 글자 셋은 각 1회 등장
profile.py 실행 결과 — 파일 400개가 모두 1024바이트로 크기 한 종류, 사용 문자 66종, 글자당 엔트로피 5.9543비트로 62종 균등 난수의 이론값 5.9542와 소수 셋째 자리까지 일치, 최빈 글자는 6775회로 특정 글자 쏠림이 없고 최소 글자 셋은 각 1회 등장

출력이 많은 걸 알려 준다.

  • 400개 파일이 전부 1024바이트다. 크기가 한 종류뿐이라는 건, 파일마다 길이가 다른 "조각"을 담았을 가능성이 낮다는 신호다.
  • 글자당 엔트로피가 5.9543비트로, 62종을 균등하게 뽑았을 때의 이론값 log2(62) ≈ 5.9542비트와 소수 셋째 자리까지 겹친다. 어떤 글자도 특별히 자주 나오지 않는, 말 그대로 균등 난수라는 뜻이다. 패턴이 없으니 "재조합하면 플래그가 된다" 같은 접근은 성립하기 어렵다.
  • 그런데 사용 문자가 62종이 아니라 66종이다. base62(0-9, A-Z, a-z)에 없는 {, }, ?, _가 섞여 있고, 빈도를 보면 {·?·}가 딱 1번씩만 등장한다. 난수에는 나올 수 없는 글자들 — 플래그가 흘린 흔적이다.

엔트로피 숫자 하나로는 감이 잘 안 오니 글자별 등장 횟수를 그림으로 그려 둔다. 균등하다는 말이 눈에 보이게 된다.

#!/usr/bin/env python3
# freq_chart.py — 전체 40만 글자의 글자별 등장 횟수를 막대그래프로 그린다.
import collections, glob
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
 
files = sorted(glob.glob("../extracted/random_string/output_*"))
data = "".join(open(f).read() for f in files)
freq = collections.Counter(data)
 
base62 = "0123456789" + "".join(chr(c) for c in range(65, 91)) + "".join(chr(c) for c in range(97, 123))
special = "{}_?"
chars = list(base62) + list(special)
counts = [freq.get(c, 0) for c in chars]
colors = ["#4e79a7"] * len(base62) + ["#e15759"] * len(special)
 
plt.figure(figsize=(14, 4.2))
plt.bar(range(len(chars)), counts, color=colors, width=0.9)
plt.xticks(range(len(chars)), chars, fontsize=7, family="monospace")
exp = len(data) / 62
plt.axhline(exp, color="#59a14f", ls="--", lw=1, label=f"uniform-over-62 expectation = {exp:.0f}")
plt.title("Character frequency across all 400 output_* files  (base62 = blue, flag-only chars = red)", fontsize=11)
plt.ylabel("count")
plt.legend(fontsize=9, loc="upper right")
plt.tight_layout()
OUT = "/home/jinho/homepage/public/images/blog/dreamhack-random-string-writeup/03_freq.png"
plt.savefig(OUT, dpi=120, facecolor="white")
print("saved", OUT)
python3 freq_chart.py
전체 40만 글자의 글자별 등장 횟수 막대그래프 — base62 62종(파란 막대)이 전부 균등 기대값 6606 근처에 수평선처럼 늘어서 치우침이 없고, 오른쪽 끝의 플래그 전용 글자 중괄호와 물음표 밑줄(빨간 막대)만 사실상 0에 가깝게 각 1회라 거의 보이지 않는다
전체 40만 글자의 글자별 등장 횟수 막대그래프 — base62 62종(파란 막대)이 전부 균등 기대값 6606 근처에 수평선처럼 늘어서 치우침이 없고, 오른쪽 끝의 플래그 전용 글자 중괄호와 물음표 밑줄(빨간 막대)만 사실상 0에 가깝게 각 1회라 거의 보이지 않는다

파란 막대 62개가 기대값 선(약 6606회) 언저리에서 고르게 춤춘다. 오른쪽 끝에 붙은 빨간 막대 넷({, }, _, ?)은 전부 1회라 눈금에서는 바닥에 깔려 거의 보이지도 않는다. "균등 난수 + 플래그가 흘린 특수문자 몇 개"라는 그림이 한눈에 들어온다.


🧪 플래그는 쪼개져 있나 — 가설 걷어내기

"파일이 엄청 많다"는 설명을 보면 흔히 떠올리는 접근이 있다. 파일마다 한 글자씩 담아 두고, 같은 위치의 글자를 파일 순서대로 이어 붙이면 플래그가 나오는 식의 세로 읽기다. 엔트로피가 이미 균등이라 가능성은 낮지만, 입문 단계에서는 직접 확인해 보는 게 낫다. 각 파일의 같은 열(column)을 파일명 순서로 모아 봤다.

#!/usr/bin/env python3
# columns.py — "파일마다 한 글자씩 담아 세로로 읽는다"는 가설을 검증한다.
import glob
files = sorted(glob.glob("../extracted/random_string/output_*"))
rows = [open(f).read() for f in files]
print(f"[files]   {len(files)}개 · 각 {len(rows[0])}글자")
for col in (0, 45, 100):
    s = "".join(r[col] for r in rows)
    print(f"[col {col:>3}] {s[:48]}…")
print("[verdict] 세로로 읽어도 난수 — 플래그는 쪼개져 있지 않다")
python3 columns.py
columns.py 실행 결과 — 400개 파일에서 0번째, 45번째, 100번째 열의 글자를 파일명 순서로 모아 이어 붙였지만 세 경우 모두 의미 없는 난수 문자열이 나와, 파일마다 한 글자씩 담아 세로로 읽는다는 가설이 틀렸고 플래그는 한 파일 안에 통째로 들어 있음을 확인
columns.py 실행 결과 — 400개 파일에서 0번째, 45번째, 100번째 열의 글자를 파일명 순서로 모아 이어 붙였지만 세 경우 모두 의미 없는 난수 문자열이 나와, 파일마다 한 글자씩 담아 세로로 읽는다는 가설이 틀렸고 플래그는 한 파일 안에 통째로 들어 있음을 확인

0번·45번·100번 열 어디를 세로로 읽어도 또 다른 난수가 나온다. 세로 읽기·재조합 가설은 여기서 접는다. 결론은 분명하다. 플래그는 쪼개져 있지 않고, 한 파일 안에 통째로 들어 있다. 남은 일은 400개 중 그 한 파일을 찾는 것뿐이다.



🎯 풀이 — 두 가지 길, 같은 파일

길 1 — 플래그 포맷을 그대로 검색

플래그 형식 WaRP{...}를 알고 있으니 디렉토리 전체에서 그 패턴을 재귀로 찾으면 된다. grep -r에 -o(매칭한 부분만 출력), -H(파일명 표시)를 붙인다. WaRP{[^}]*}는 "WaRP{로 열고 }가 아닌 글자가 이어지다 }로 닫히는" 부분을 잡는 정규식이다.

길 2 — 포맷을 몰랐다면

정찰에서 base62에 없는 {, }, ?, _가 플래그에서만 나온다는 걸 봤다. 플래그 포맷을 모른다 해도 "난수답지 않은 글자가 박힌 파일" 을 찾으면 같은 결론에 닿는다. grep -l '[{}?]'는 대괄호 안 글자 중 하나라도 품은 파일의 이름만 출력한다.

아래 solve.sh가 두 길을 나란히 돌린다.

#!/usr/bin/env bash
# solve.sh — 400개 파일 더미에서 플래그를 뽑는 두 가지 길.
D=../extracted/random_string
 
echo "[1] 플래그 포맷(WaRP{...})을 그대로 grep — 가장 곧장"
grep -rHo 'WaRP{[^}]*}' "$D"
 
echo
echo "[2] 포맷을 몰라도: base62에 없는 글자({ } ?)가 박힌 파일을 역추적"
grep -rl '[{}?]' "$D"
./solve.sh
solve.sh 실행 결과 — 길1의 grep -rHo WaRP 패턴 검색이 output_og 파일에서 WaRP 중괄호 플래그 문자열을 그대로 뽑아내고, 길2의 grep -rl 특수문자 검색도 똑같이 output_og 한 파일만 지목해 포맷을 알든 모르든 같은 결론에 도달함을 보여줌
solve.sh 실행 결과 — 길1의 grep -rHo WaRP 패턴 검색이 output_og 파일에서 WaRP 중괄호 플래그 문자열을 그대로 뽑아내고, 길2의 grep -rl 특수문자 검색도 똑같이 output_og 한 파일만 지목해 포맷을 알든 모르든 같은 결론에 도달함을 보여줌

두 길 모두 output_og 하나를 가리킨다. 400개 중 플래그를 품은 파일은 이것뿐이다. 앞서 "split로 잘렸다면 플래그가 두 파일 경계에 걸쳐 있을 수도 있다"고 적어 뒀는데, 길 1의 파일별 grep이 WaRP{부터 }까지 완전한 플래그를 한 파일에서 그대로 뽑아냈다는 건 경계에 걸리지 않았다는 뜻이다. 만약 쪼개졌다면 cat output_* | grep 처럼 전부 이어 붙여 검색해야 했을 것이다.

길 2가 정말 "운 좋게 하나만 걸린 것"이 아니라 구조적으로 하나뿐임을 확인해 둔다. 특수문자별로 그 글자를 품은 파일 수를 세어 보면 넷 다 1이어야 한다.

#!/usr/bin/env bash
# crosscheck.sh — base62에 없는 글자별로 그 글자를 품은 파일 수를 센다.
D=../extracted/random_string
for ch in '{' '}' '?' '_'; do
  printf "글자 %s 를 품은 파일 수: " "$ch"
  grep -lF "$ch" "$D"/* | wc -l
done
echo "→ 넷 다 같은 파일 하나(output_og)에만 몰려 있다"
./crosscheck.sh
crosscheck.sh 실행 결과 — 중괄호 열기 닫기와 물음표, 밑줄 네 글자 각각에 대해 그 글자를 품은 파일 수를 세었더니 모두 1개로 나와, base62 난수에는 없는 글자가 전부 한 파일에만 몰려 있음을 수치로 확인
crosscheck.sh 실행 결과 — 중괄호 열기 닫기와 물음표, 밑줄 네 글자 각각에 대해 그 글자를 품은 파일 수를 세었더니 모두 1개로 나와, base62 난수에는 없는 글자가 전부 한 파일에만 몰려 있음을 수치로 확인

{, }, ?, _ 네 글자 모두 파일 1개에만 존재한다. base62 난수 40만 글자 어디에도 이 글자들은 섞여 들어가지 않았으니, 특수문자가 보이는 순간 그 파일이 답이다.


🔎 플래그는 파일 어디에 숨어 있었나

찾은 파일 안에서 플래그가 어느 위치에 박혔는지 확인한다. locate.py가 바이트 오프셋과 앞뒤 난수 문맥을 보여 준다.

#!/usr/bin/env python3
# locate.py — output_og 안에서 플래그가 박힌 위치와 앞뒤 문맥을 보여준다.
s = open("../extracted/random_string/output_og").read()
i = s.find("WaRP{")
j = s.find("}", i) + 1
print(f"[len]     output_og = {len(s)} 글자")
print(f"[offset]  플래그는 {i}~{j}번째 바이트")
print(f"[before]  …{s[i-20:i]}")
print(f"[FLAG]    {s[i:j]}")
print(f"[after]   {s[j:j+20]}…")
python3 locate.py
locate.py 실행 결과 — output_og는 1024글자이고 플래그는 45번째부터 65번째 바이트에 위치, 앞쪽 난수 20글자와 뒤쪽 난수 20글자 사이에 WaRP 중괄호 플래그가 끼워져 있어 사람 눈에는 또 하나의 난수로 보이지만 grep에는 또렷한 패턴임을 보여줌
locate.py 실행 결과 — output_og는 1024글자이고 플래그는 45번째부터 65번째 바이트에 위치, 앞쪽 난수 20글자와 뒤쪽 난수 20글자 사이에 WaRP 중괄호 플래그가 끼워져 있어 사람 눈에는 또 하나의 난수로 보이지만 grep에는 또렷한 패턴임을 보여줌

플래그는 1024글자 중 45번째 바이트에서 시작한다. 앞뒤가 모두 난수라 사람 눈에는 그냥 또 하나의 난수 조각처럼 보이지만, grep에게는 {로 열고 }로 닫히는 또렷한 경계다. 바이트 단위로 한 번 더 확인하면 더 분명하다.

xxd -s 45 -l 32 output_og
xxd 헥스덤프 — output_og의 45번째 바이트부터 32바이트를 16진수와 ASCII로 나란히 표시, 왼쪽 16진수 57 61 52 50 7b는 오른쪽 ASCII에서 WaRP 중괄호로 대응되어 플래그 문자열이 파일 중간에 날것 그대로 저장돼 있음을 바이트 수준에서 확인
xxd 헥스덤프 — output_og의 45번째 바이트부터 32바이트를 16진수와 ASCII로 나란히 표시, 왼쪽 16진수 57 61 52 50 7b는 오른쪽 ASCII에서 WaRP 중괄호로 대응되어 플래그 문자열이 파일 중간에 날것 그대로 저장돼 있음을 바이트 수준에서 확인

57 61 52 50 7b가 그대로 WaRP{다. 인코딩도 압축도 없이 날것 그대로 끼워 넣은 것이라, 패턴만 알면 grep이 단숨에 집어낸다.


✅ 플래그 제출

찾은 플래그를 그대로 제출한다.

python3 dreamhack.py wg 1838 --flag "WaRP{4ll_7x7_c7rl4?}"
드림핵 제출 결과 — Random String 문제에 플래그를 제출하자 RESULT 정답 해결 처리됨 메시지가 출력되어 WaRP 중괄호 플래그가 정답으로 확인되고 문제가 해결 처리됨
드림핵 제출 결과 — Random String 문제에 플래그를 제출하자 RESULT 정답 해결 처리됨 메시지가 출력되어 WaRP 중괄호 플래그가 정답으로 확인되고 문제가 해결 처리됨

플래그 WaRP{4ll_7x7_c7rl4?}를 leet로 읽으면 4는 a, 7은 t이니 "all txt ctrl" 쯤 된다. 수많은 텍스트(all txt)를 Ctrl로 뒤지라는, 풀이법 자체를 담은 말장난이다. 파일을 하나씩 여는 대신 전체 텍스트를 한 번에 검색하라는 힌트가 플래그에 박혀 있었던 셈이다.


🧰 같은 답을 내는 다른 한 줄들

grep -rHo 'WaRP{[^}]*}' . 말고도 길은 여럿이다. 상황에 맞게 고르면 된다.

  • grep -rl 'WaRP{' . — 플래그를 품은 파일 이름만 뽑는다. 먼저 어느 파일인지 특정하고 따로 열어 보고 싶을 때.
  • grep -rho 'WaRP{[^}]*}' . — 플래그 문자열만, 파일명 없이 출력한다(-h가 파일명을 뗀다). 바로 복사해서 제출하기 좋다.
  • cat output_* | grep -o 'WaRP{[^}]*}' — 400개를 한 스트림으로 이어 붙여 한 번에 검색한다. 파일이 한 폴더에 평평하게 있을 때.
  • strings output_* | grep WaRP — 중간에 텍스트가 아닌 파일이 섞여 있어도 출력 가능한 문자열만 걸러서 본다. 바이너리 더미를 뒤질 때 특히 유용하다.

재귀 옵션 -r은 하위 폴더까지 훑으니 폴더 구조를 모를 때 안전한 기본값이다. 이번처럼 파일이 한 폴더에 평평하게 있으면 grep ... output_*처럼 글롭만으로도 충분하다. -o는 긴 난수 한 줄에서 매칭한 부분만 잘라 주므로, 1024글자 전체가 화면을 덮는 걸 막아 준다.

한 가지 함정은 찾은 플래그를 셸에 다시 넘길 때다. WaRP{4ll_7x7_c7rl4?}에는 ?와 {, }가 들어 있는데, 따옴표 없이 그대로 치면 zsh·bash가 ?를 "한 글자 와일드카드"로, {, }를 "중괄호 확장"으로 해석해 전혀 다른 값으로 바뀌어 버린다. 제출 명령에서 플래그를 "WaRP{...}"처럼 따옴표로 감싼 건 셸이 손대지 못하게 막기 위해서다. 플래그에 특수문자가 섞인 문제에서 "분명히 맞는데 오답" 이 나오면 이 인용부호부터 의심하면 된다.


📝 정리

Bronze 2 난이도답게 기법은 단순하지만, "많은 데이터 속에서 한 조각을 찾는다"는 포렌식의 기본기를 그대로 보여 주는 문제다. 세 가지를 남겨 둔다.

데이터가 많을수록 사람 눈을 믿지 말고 도구에 맡긴다. 40만 글자를 훑는 건 사람에게 불가능하지만 grep -r에게는 한순간이다. 로그·메모리 덤프·디스크 이미지처럼 파일이 수백·수천 개로 쏟아지는 상황은 실무에서 흔하고, "무엇을 찾을지"를 패턴으로 정의할 수 있으면 규모 자체는 더 이상 장벽이 아니다. 실제 침해 대응에서도 흐름은 똑같다. 수 기가바이트짜리 메모리 덤프에서 플래그 대신 특정 문자열·URL·악성 지표(IOC)를 찾을 때 grep·strings·yara를 쓰고, "찾을 대상을 정규식 한 줄로 어떻게 표현하느냐"가 곧 분석 속도를 가른다. 이 문제는 그 사고 과정을 가장 작은 규모로 압축해 둔 연습이다.

찾을 패턴이 애매하면 데이터의 '정상'을 먼저 정의한다. 플래그 포맷을 몰랐더라도, 이 더미가 base62 균등 난수라는 걸 통계로 확인해 두면 "난수답지 않은 것"이 곧 단서가 된다. 엔트로피와 문자 집합은 "여기서 뭐가 튀는가"를 수치로 짚어 주는, 포렌식에서 가장 먼저 꺼내는 자다.

가설은 머리로 접지 말고 한 줄 코드로 검증한다. 세로 읽기 가설은 엔트로피만 봐도 가능성이 낮았지만, columns.py 한 번으로 확실히 닫으면 이후 방향을 자신 있게 정할 수 있다. 입문 단계일수록 "아마 아닐 거야"를 실제로 돌려 확인하는 습관이 길게 남는다. 반대로 상위 난이도에서는 이 "정상 정의 → 튀는 값 찾기 → 가설 검증"의 사이클이 더 길고 정교해질 뿐, 뼈대는 변하지 않는다. Bronze 2짜리 grep 한 줄 안에 포렌식의 작업 순서가 통째로 들어 있는 셈이다.

이 글이 도움이 됐나요?

Comments

댓글

0개

댓글을 남기려면 로그인이 필요해요. (네이버 · 구글 계정)

댓글 불러오는 중…

Related

관련 글

3개
[🥉 Bronze 4] 반투명 덧칠은 지우개가 아니다 — DreamHack QR Code 풀이
blog

[🥉 Bronze 4] 반투명 덧칠은 지우개가 아니다 — DreamHack QR Code 풀이

QR 코드 위에 검은 낙서가 덮여 있다. 그런데 픽셀값이 열 종류밖에 없고 255, 63, 16, 4, 1 이라는 등비 사슬을 이룬다. 알파 75% 검정을 겹칠 때마다 밑의 밝기가 1/4 씩만 남은 흔적이다. "픽셀값이 0보다 크면 흰 모듈" 한 줄로 29x29 격자를 되살리고, 재인코딩본과 841칸 전수 대조까지 했다.
#dreamhack#ctf#misc+5
2026-08-22#dreamhack +4
[🥉 Bronze 2] 6523개 CAN 프레임 중 튀는 하나 — DreamHack Read My Car 풀이
blog

[🥉 Bronze 2] 6523개 CAN 프레임 중 튀는 하나 — DreamHack Read My Car 풀이

정비소에서 받아온 차량 주행 로그라며 candump 파일 하나만 준다. 열어 보면 1953가지 CAN ID가 뒤섞인 난수 덩어리인데, 등장 횟수를 세면 딱 하나만 다른 ID들보다 4배 넘게 튄다. 그 ID의 페이로드를 ASCII로 읽으면 flag가 나온다.
#dreamhack#ctf#misc+5
2026-07-24#dreamhack +4
[🥉 Bronze 1] LSB엔 없다, 주파수에 있다 — DreamHack Audio Steganography 풀이
blog

[🥉 Bronze 1] LSB엔 없다, 주파수에 있다 — DreamHack Audio Steganography 풀이

6초짜리 WAV 파일 하나가 전부인 포렌식 문제. 오디오 스테가노그래피라고 하면 반사적으로 LSB(최하위 비트)부터 뽑아보게 되는데, 그렇게 나온 결과는 그냥 잡음이다. "이상한 소리가 나요"라는 문제 설명을 다시 읽고 스펙트로그램을 찍어보면, 주파수 영역에 flag 문자열이 글자 모양 그대로 그려져 있다. 데이터를 비트에 숨긴 게 아니라 진폭을 붓 삼아 그림을 그린, Aphex Twin류 스펙트로그램 아트다.
#dreamhack#ctf#forensics+4
2026-07-20#dreamhack +4