Tag Archive

#gdb

이 태그가 포함된 글을 최신순으로 모아봤어요.

44
posts
BLOG2026-08-19
[🥈 Silver 1] MixColumns 하나가 빠지면 AES 는 XOR 표로 무너진다 — DreamHack locked present 풀이
blog

[🥈 Silver 1] MixColumns 하나가 빠지면 AES 는 XOR 표로 무너진다 — DreamHack locked present 풀이

25바이트 비밀번호를 검사하는 stripped ELF 안에 5x5 블록 AES 변형이 통째로 들어 있다. S-box 도 Rcon 도 진짜 AES 인데 MixColumns 만 없다. 그 하나가 빠지자 확산이 사라져 평문 바이트 하나가 암호문 바이트 하나로 그대로 대응했고, 라운드가 10 이라 열 회전마저 상쇄돼 자리 순열까지 항등이 됐다. 재구현으로 되감아 비밀번호를 복구하고, 키를 전혀 모르는 상태에서도 같은 값이 나오는 두 가지 경로를 따로 실증했다.
#dreamhack#ctf#reversing+7
 
BLOG2026-08-19
[🥉 Bronze 2] .rodata 247바이트가 스택 VM 바이트코드였다 — DreamHack SelfStatus 풀이
blog

[🥉 Bronze 2] .rodata 247바이트가 스택 VM 바이트코드였다 — DreamHack SelfStatus 풀이

프로그램이 자기 /proc/self/status 를 읽어 TracerPid 로 디버거를 알아채고 조용히 죽는다. 진짜 검사는 .rodata 에 박힌 247바이트를 도는 스택 VM 이 맡는데, 그 VM 은 사용자 입력을 아예 쳐다보지 않고 정답 문자열을 스스로 조립한다. 그래서 역산할 것이 없다 — VM 만 옮겨 적으면 끝난다.
#dreamhack#ctf#reversing+6
 
BLOG2026-08-19
[🥈 Silver 3] 2MB 바이너리에서 코드는 509바이트뿐이었다 — DreamHack Branches and Leaves 풀이
blog

[🥈 Silver 3] 2MB 바이너리에서 코드는 509바이트뿐이었다 — DreamHack Branches and Leaves 풀이

문제 설명이 시 네 줄뿐인 리버싱. 2.1MB짜리 stripped ELF를 열어 보면 코드는 509바이트고 나머지 전부가 배열로 접은 깊이 16 이진트리다. 입력 4글자가 16비트로 펴져 트리를 16번 내려가고, 그 리프 65536개가 서로 겹치지 않아서 기대값마다 역상이 정확히 하나로 정해진다.
#dreamhack#ctf#reversing+5
 
BLOG2026-08-18
[💠 Platinum 4] 한 프로세스에서 32비트와 64비트가 번갈아 돈다 — DreamHack conquergent 풀이
blog

[💠 Platinum 4] 한 프로세스에서 32비트와 64비트가 번갈아 돈다 — DreamHack conquergent 풀이

배포 파일은 17KB짜리 stripped ELF 하나. 32비트 i386 바이너리인데 .text 안에 retf 가 32개 박혀 있다. CS 셀렉터를 0x33 으로 밀어 넣고 far return 하는 Heaven's Gate 로, 같은 프로세스 안에서 64비트 가젯 14종을 굴려 입력 64바이트를 qword 8개 단위로 변환한다. objdump 가 dec eax 로 보여 주는 0x48 은 REX.W 접두사였다. 가젯 규약과 상수 테이블을 도구로 뽑아 세 단계 파이프라인을 복원하고, 곱셈 상수가 전부 홀수라는 점을 이용해 mod 2^64 역원으로 되감아 플래그를 복원했다.
#dreamhack#ctf#reversing+6
 
BLOG2026-08-18
[💠 Platinum 4] 0의 런렝스를 감마 코드로 되감기 — DreamHack Run 풀이
blog

[💠 Platinum 4] 0의 런렝스를 감마 코드로 되감기 — DreamHack Run 풀이

배포 파일은 10KB 짜리 stripped ELF 와 160KB 짜리 flag.enc 두 개뿐이다. 바이너리는 복호기가 아니라 인코더였고, 0 의 런렝스를 Elias 감마 유사 코드로 바꿔 쓰는 1810바이트짜리 루틴 하나가 전부였다. 분기 하나를 반대로 읽으면 복원본이 통째로 비트 반전된다. objdump 로 인코더를 읽고 gdb 로 못 박은 뒤 역함수를 써서 10000x10000 PNG 를 되살렸고, 복원본을 문제 바이너리에 재투입해 sha256 일치로 검증했다.
#dreamhack#ctf#reversing+6
 
BLOG2026-08-17
[🥈 Silver 1] 키스트림 1비트로 되돌린 SNOW 3G — DreamHack snow 풀이
blog

[🥈 Silver 1] 키스트림 1비트로 되돌린 SNOW 3G — DreamHack snow 풀이

20KB 짜리 스트립트 ELF 안에 3GPP 표준 스트림 암호 SNOW 3G 가 통째로 들어 있었다. 키는 "Merry-Christmas!" 로 고정이고 IV 는 우리가 넣는 입력의 앞 16바이트 — 즉 복원해야 할 값이 자기 자신을 암호화한다. 워드마다 필요한 정보가 키스트림의 최하위 1비트뿐이라는 점을 이용해 256가지만 확인하고 32글자를 되돌렸다.
#dreamhack#ctf#reversing+6
 
BLOG2026-08-17
[🥇 Gold 4] 파일 커서를 656번 흩뿌린 검증기 되감기 — DreamHack fverify 풀이
blog

[🥇 Gold 4] 파일 커서를 656번 흩뿌린 검증기 되감기 — DreamHack fverify 풀이

fverify 는 fseek(SEEK_CUR) 4949번과 1바이트 fread 656번으로만 이루어진 직선 코드다. 파일 오프셋이 코드 어디에도 안 적혀 있어 objdump 출력만으로는 무엇을 검사하는지 알 수 없다. 커서 이동을 그대로 재생해 슬롯과 파일 오프셋을 다시 이어 붙이면 656바이트 정답 파일이 통째로 복원된다.
#dreamhack#ctf#reversing+5
 
BLOG2026-08-17
[🥇 Gold 4] 5바이트 스텁 97개로 부순 건 코드가 아니라 디스어셈블러였다 — DreamHack Vernichtet 풀이
blog

[🥇 Gold 4] 5바이트 스텁 97개로 부순 건 코드가 아니라 디스어셈블러였다 — DreamHack Vernichtet 풀이

.text 전체에 `eb ff c1 ff c9` 가 97개 박혀 있다. jmp 가 자기 오퍼랜드로 뛰어드는 겹침 명령이라 선형 스윕 디스어셈블러는 실행되지도 않는 유령 명령을 보여 준다. 길이를 유지한 채 NOP 으로 덮어 코드를 되살리고, 그 안에 숨어 있던 15×15 Hidato 퍼즐을 풀어 답안 파일의 sha256 을 플래그로 받아냈다.
#dreamhack#ctf#reversing+7
 
BLOG2026-08-16
[🥇 Gold 1] 함수 125개짜리 4진 트라이를 되감다 — DreamHack Function Network 풀이
blog

[🥇 Gold 1] 함수 125개짜리 4진 트라이를 되감다 — DreamHack Function Network 풀이

stripped 바이너리가 64바이트 입력을 10000번 변형해 고정된 목표값과 비교한다. 변형의 종류는 .data 에 박힌 64비트 key 가 정하는데, 그 key 는 함수 포인터가 아니라 디스패처 125개로 짜인 4진 트라이를 2비트씩 32번 타고 내려가는 경로였다. 도착지인 리프 4개가 전부 전단사라 목표값에서 10000스텝을 거꾸로 감으면 입력이 그대로 나온다.
#dreamhack#ctf#reversing+6
 
BLOG2026-08-12
[🥉 Bronze 2] 쓴 값이 다음 쓰기 주소가 된다 — DreamHack p_rho 풀이
blog

[🥉 Bronze 2] 쓴 값이 다음 쓰기 주소가 된다 — DreamHack p_rho 풀이

숫자를 하나 넣으면 배열에 저장하고, 그 값을 그대로 다음 인덱스로 삼는 무한 루프. 임의 주소 쓰기인데 주소를 직접 못 고르고 "직전에 쓴 값"이 정한다는 제약이 붙는다. buf 를 원점으로 보면 GOT 가 음수 인덱스에 있고, Partial RELRO 라 잠겨 있지도 않다. 정수 두 개로 printf@got 를 win 으로 덮어 셸을 잡았다.
#dreamhack#ctf#pwnable+6
 
BLOG2026-08-11
[🥉 Bronze 2] XOR 0x42 뒤에 숨은 명령 한 개 — DreamHack flag printer 풀이
blog

[🥉 Bronze 2] XOR 0x42 뒤에 숨은 명령 한 개 — DreamHack flag printer 풀이

print/id/help 세 개만 받는다던 프로그램이, 사실은 네 번째 명령을 몰래 받고 있었다. 모르는 토큰을 strdup 해서 XOR 0x42 한 뒤 스택에 조립해 둔 네 바이트와 비교하는 코드가 있고, 그걸 통과하면 print 가 art 대신 flag 를 연다. objdump 로 비교값을 읽고 gdb 로 런타임까지 확인해 한 줄로 flag 를 뽑았다.
#dreamhack#ctf#reversing+5
 
BLOG2026-08-10
[🥇 Gold 4] 하루 넘게 걸리는 정렬을 0.2초로 건너뛰기 — DreamHack Slooooow 풀이
blog

[🥇 Gold 4] 하루 넘게 걸리는 정렬을 0.2초로 건너뛰기 — DreamHack Slooooow 풀이

배포본은 stripped PIE 하나뿐이고 코드는 1,136바이트, 데이터는 400KB다. main 이 하는 일은 그 400KB를 Stooge sort 로 정렬하고 SHA-256 을 찍는 것뿐인데, 마스터 정리를 세워 보면 10만 원소에 하루가 넘게 걸린다. 정렬 알고리즘을 실행할 필요는 없다. 비교 함수가 쓰는 비트 순열만 그대로 복원하면 결과는 파이썬 한 줄로 나온다.
#dreamhack#ctf#reversing+7
 
BLOG2026-08-09
[🥉 Bronze 3] ARM32 스택 오버플로로 pc 를 직접 갈아끼우기 — DreamHack Arm Training-v1 풀이
blog

[🥉 Bronze 3] ARM32 스택 오버플로로 pc 를 직접 갈아끼우기 — DreamHack Arm Training-v1 풀이

x86 의 ret 이 없는 ARM32에서는 함수 에필로그가 pop 으로 fp 와 pc 를 한꺼번에 복원한다. 저장된 lr 을 덮으면 그 값이 검사 없이 그대로 pc 가 된다. 24바이트 뒤 반환주소를 shell() 로 바꿔 system("/bin/sh") 를 호출하고, read(0, buf, 200) 가 셸 명령까지 삼켜버리는 함정은 payload 를 정확히 200바이트로 맞춰 넘긴다.
#dreamhack#ctf#pwnable+6
 
BLOG2026-08-04
[💠 Platinum 3] 니블 교환·AES S-box·std::sort 로 짠 로그인 검사 되돌리기 — DreamHack rev-login 풀이
blog

[💠 Platinum 3] 니블 교환·AES S-box·std::sort 로 짠 로그인 검사 되돌리기 — DreamHack rev-login 풀이

아이디와 비밀번호를 세 단계로 검사하는 C++ 바이너리. 아이디 검사는 글자를 니블 단위로 뒤집어 옆 글자와 엮은 뒤 AES S-box 를 통과시키고, 비밀번호 검사는 S-box 를 한 번 더 누산한 다음 std::sort 로 자리 정보를 지워 버린다. 플래그는 어디에도 없고 정답 문자열의 SHA-1 이 곧 키다.
#dreamhack#ctf#reversing+6
 
BLOG2026-07-28
[🥉 Bronze 3] 리크도 셸도 없이 strcmp 하나를 오라클로 바꾸기 — DreamHack checkflag 풀이
blog

[🥉 Bronze 3] 리크도 셸도 없이 strcmp 하나를 오라클로 바꾸기 — DreamHack checkflag 풀이

플래그를 맞히면 Correct 를, 틀리면 Failed 를 돌려주는 것이 전부인 바이너리다. 리크할 포인터도 덮을 리턴 주소도 없다. 그런데 main 이 flag 를 담는 버퍼와 우리가 입력하는 버퍼를 같은 스택 영역에 0x40 간격으로 나란히 놓고, read 는 그보다 훨씬 긴 0xc8 바이트를 받는다. 0x40+d 바이트를 보내면 flag 앞 d 글자가 내 바이트로 덮이고, 그 상태의 strcmp 는 "flag 의 남은 뒷부분이 이거 맞아?" 라는 접미사 오라클이 된다. 뒤에서부터 한 글자씩 물어보면 16글자가 16초 만에 나온다.
#dreamhack#ctf#pwnable+7
 
BLOG2026-07-26
[🥈 Silver 2] Rust 크랙미의 비트 치환을 거꾸로 돌려 64글자 입력 복원 — DreamHack CrabME 풀이
blog

[🥈 Silver 2] Rust 크랙미의 비트 치환을 거꾸로 돌려 64글자 입력 복원 — DreamHack CrabME 풀이

Rust 로 빌드된 크랙미. 입력은 64글자 소문자 hex 로 고정돼 있고, 두 글자씩 묶은 32바이트를 flagchecker 가 "비트 치환 → XOR 0x63 → +0x22" 세 단계로 바꿔 .rodata 에 박힌 상수 32개와 비교한다. 세 단계가 전부 바이트 단위 전단사라 브루트포스 없이 그대로 역산되고, 나온 64글자가 곧 플래그 본문이다. objdump 로 치환표를 유도하고 gdb 로 런타임에서 같은 값이 나오는지 확인했다.
#dreamhack#ctf#reversing+6
 
BLOG2026-07-25
[🥈 Silver 1] main 이라는 이름의 거짓말 — DreamHack Honest 풀이
blog

[🥈 Silver 1] main 이라는 이름의 거짓말 — DreamHack Honest 풀이

바이너리 하나만 주는 리버싱 문제. 64개 함수가 전역 counter 를 하나씩 올리며 입력을 한 글자씩 검사하는 단순한 구조인데, 그대로 역산하면 Wrong! 이 나온다. ELF 진입점을 따라가 보면 _start 가 __libc_start_main 에 넘기는 함수가 main 심볼이 아니라 verify_func_28 이다. 시작 칸이 55칸 어긋나 정답 문자열이 통째로 회전해 있었다.
#dreamhack#ctf#reversing+5
 
BLOG2026-07-25
[🥈 Silver 2] 해킹당한 VM 이미지에서 채굴기가 삼킨 플래그 되찾기 — DreamHack Infested Terran 풀이
blog

[🥈 Silver 2] 해킹당한 VM 이미지에서 채굴기가 삼킨 플래그 되찾기 — DreamHack Infested Terran 풀이

bzImage + rootfs.ext2 두 파일만 주는 문제. 이미지를 마운트하지 않고 열어보면 buildroot 바이너리들 사이에 glibc로 빌드된 두 개가 섞여 있다. /home/ubuntu/.helper는 표준입력으로 받은 값을 argv[0]="[kworker]"로 위장해 /usr/bin/sl에 넘기고, sl은 입력 36글자를 힙에 흩뿌린 뒤 누적합을 하드코딩된 값과 비교한다. 검증식이 삼각행렬이라 이웃한 두 항을 빼는 것만으로 한 글자씩 그대로 복원된다.
#dreamhack#ctf#reversing+7
 
BLOG2026-07-24
[🥈 Silver 2] 리버싱 대신 메모리를 읽는다 — DreamHack just read memory 풀이
blog

[🥈 Silver 2] 리버싱 대신 메모리를 읽는다 — DreamHack just read memory 풀이

입력을 한 글자씩 연결리스트 노드와 비교하고, 다 맞으면 플래그를 뱉는 바이너리. 노드 값은 루프 인덱스가 아니라 세 헬퍼 함수가 공유하는 초기화 안 된 스택 슬롯과 전역 cnt 로 만든 숨은 점화식(cnt = 27*cnt + 103)에서 나온다. 그 점화식을 파이썬으로 접어 정답 입력을 복원할 수도 있지만, 문제 이름대로 gdb 로 리스트 생성 직후에 멈춰 힙을 그대로 읽어내는 게 더 빠르다.
#dreamhack#ctf#reversing+5
 
BLOG2026-07-21
[🥈 Silver 4] ctype 비트 하나를 잘못 짚으면 퍼뮤테이션 전체가 어긋난다 — DreamHack Permpkin 풀이
blog

[🥈 Silver 4] ctype 비트 하나를 잘못 짚으면 퍼뮤테이션 전체가 어긋난다 — DreamHack Permpkin 풀이

chall 바이너리는 입력을 받지 않는다. 대신 미리 정해둔 sample 문자열을 스스로 뒤섞어 rev1.txt/rev2.txt로 보여줄 뿐이다. 진짜 풀어야 할 대상은 같은 방식으로 미리 변환돼 주어진 flag1.txt/flag2.txt. 바이너리 안의 23자리 hex 문자열을 ctype 기반으로 숫자 배열(퍼뮤테이션+XOR 키)로 바꾸는데, 그 변환 도중 하필 값이 0이 되는 지점이 있어서 이후 strlen()이 배열 길이를 23에서 13으로 끊어버린다. 이 함정을 처음엔 못 보고 엉뚱한 ctype 비트를 가정해 틀렸다가, gdb로 실제 프로세스의 중간 메모리 상태를 직접 찍어보고 나서야 알고리즘을 100% 검증하고 뒤집을 수 있었다.
#dreamhack#ctf#reversing+4
 
BLOG2026-07-21
[🥈 Silver 4] 화면에 아무것도 안 뜨는 바이너리에서 flag 뽑아내기 — DreamHack fake 풀이
blog

[🥈 Silver 4] 화면에 아무것도 안 뜨는 바이너리에서 flag 뽑아내기 — DreamHack fake 풀이

실행해도 아무것도 출력하지 않는 ELF 바이너리 하나. strace로 확인해보니 read/write 계열 syscall이 단 한 번도 없다 — 임포트된 함수조차 malloc/free뿐이다. objdump로 뜯어보니 main()은 스택에 movabs 즉시값으로 23바이트 시드 버퍼를 조립해 malloc한 뒤, reverse → 인접 바이트 교환 → XOR라는 세 단계 변환만 거쳐 곧바로 free해버린다. 화면에 찍히는 건 없지만, 그 변환 결과를 파이썬으로 그대로 재현하고 gdb로 free() 직전 힙 버퍼를 직접 들여다보는 것으로 flag를 확인했다.
#dreamhack#ctf#reversing+4
 
BLOG2026-07-21
[🥈 Silver 4] srand() 없는 rand()는 이미 예언된 미래다 — DreamHack randzzz 풀이
blog

[🥈 Silver 4] srand() 없는 rand()는 이미 예언된 미래다 — DreamHack randzzz 풀이

"난수를 맞혀보라"는 리버싱 문제. 그런데 바이너리를 뜯어보면 어디에도 srand()가 없다 — glibc의 rand()는 시드를 명시적으로 주지 않으면 항상 똑같은 순서로 값을 뱉는 결정론적 함수이므로, 이 프로그램이 뭘 물어볼지는 실행하기도 전에 전부 계산할 수 있다. 문제는 그 다음이다. 두 번의 검증이 서로 다른 정답을 요구하는데 입력은 한 번뿐이라, 한 번의 정상 실행으로는 절대 flag 전체를 볼 수 없다. GDB로 실행 중인 프로세스의 스택 메모리를 직접 고쳐써서 두 검증을 동시에 통과시킨 끝에야 완전한 flag가 나왔다.
#dreamhack#ctf#reversing+5
 
BLOG2026-07-20
[🥉 Bronze 1] 두 번의 XOR은 상쇄되지 않았다 — DreamHack ez_rev 풀이
blog

[🥉 Bronze 1] 두 번의 XOR은 상쇄되지 않았다 — DreamHack ez_rev 풀이

"함수가 너무 많아요"라는 문제 설명과 달리 실제로 입력을 건드리는 함수는 셋뿐이다. 회전 두 번과 XOR 두 번이 교차로 걸려 있는데, 같은 키로 XOR을 두 번 하니 그냥 상쇄될 거라 생각하고 지름길을 탔다가 완전히 다른 문자열이 나왔다. 원인은 두 XOR 사이에 낀 회전 하나가 인덱스 정렬 자체를 바꿔버린다는 점이었다.
#dreamhack#ctf#reversing+2
 
BLOG2026-07-20
[🥉 Bronze 1] 키는 GOT 뒤에 숨어 있었다 — DreamHack basic_CrackMe 풀이
blog

[🥉 Bronze 1] 키는 GOT 뒤에 숨어 있었다 — DreamHack basic_CrackMe 풀이

32비트 PIE ELF와 Windows PE가 세트로 나오는 리버싱 문제. 겉보기엔 흔한 XOR 크랙미인데 막상 열어보면 XOR 한 번이 아니라 자릿수마다 제곱·뺄셈·덧셈이 섞인 int64 배열 연산이라 손으로 따라가면 금방 헷갈린다. 진짜 함정은 알고리즘이 아니라 키 위치 — 키 문자열은 코드 어디에도 안 보이고 GOT 슬롯에 꽂힌 포인터 하나가 .rodata를 가리키고 있었다.
#dreamhack#ctf#reversing+3
 
BLOG2026-07-19
[🥈 Bronze 2] 미끼인 줄 알았던 디코드가 사실 정답이었다 — DreamHack 아 문제 이름 뭘로하지 풀이
blog

[🥈 Bronze 2] 미끼인 줄 알았던 디코드가 사실 정답이었다 — DreamHack 아 문제 이름 뭘로하지 풀이

39바이트 암호문을 XOR 0xAA로 풀면 그럴듯한 DH{} 문자열이 바로 나온다. 너무 쉬워서 미끼라고 판단하고, 사용자 입력을 변형하는 복잡한 커스텀 인코딩 함수를 통째로 역산했다. GDB로 대조하다 32비트 시프트 카운트 마스킹 때문에 특정 자리가 항상 0이 되는 버그를 발견했고, 그 버그를 쫓아가다 결국 처음 봤던 그 디코드 문자열이 진짜 정답이었다는 걸 알게 됐다.
#dreamhack#ctf#reversing+4
 
BLOG2026-07-19
[🥈 Bronze 2] 난독화된 전역 변수를 GDB로 그대로 읽어내기 — DreamHack Stop before stops! 풀이
blog

[🥈 Bronze 2] 난독화된 전역 변수를 GDB로 그대로 읽어내기 — DreamHack Stop before stops! 풀이

C++ 바이너리인데 함수·전역변수 이름이 전부 무작위 문자열로 바뀌어 있다. 정적 분석으로 로직은 다 읽히는데(24자 비밀번호를 비교해 맞으면 flag를 출력), 실제 비교 대상 문자열은 실행 시점에 조용히 채워지는 전역 std::string이라 정적 디스어셈블리만으론 값을 알 수 없다. GDB로 static initializer가 끝난 직후 raw 메모리를 읽어 값을 그대로 꺼냈다.
#dreamhack#ctf#reversing+5
 
BLOG2026-07-19
[🥉 Bronze 4] 가짜 함수 199개 속에서 flag 찾기 — DreamHack please, please, please 풀이
blog

[🥉 Bronze 4] 가짜 함수 199개 속에서 flag 찾기 — DreamHack please, please, please 풀이

stripped PIE 바이너리 안에 거의 동일한 함수가 199개 박혀 있다. 전부 "please~"만 출력하는 죽은 코드고, 실제 main도 puts 한 줄만 부르고 끝난다. objdump로 199개 중 유일하게 다른 함수를 찾아내면 "Hhu,"라는 또 다른 미끼가 나오는데, 정작 flag는 strings 한 번이면 바로 보이는 DH{NOGADA}였다.
#dreamhack#ctf#reversing+5
 
BLOG2026-07-16
[🥉 Bronze 3] stripped Rust 바이너리에서 스택 key 를 뽑아 XOR 역산 — DreamHack Rusty Gyul 풀이
blog

[🥉 Bronze 3] stripped Rust 바이너리에서 스택 key 를 뽑아 XOR 역산 — DreamHack Rusty Gyul 풀이

심볼을 모두 걷어낸 Rust ELF 하나가 "플래그를 맞춰봐"라고 한다. ltrace 에는 strcmp 하나 안 잡히고 main 은 껍데기뿐이다. 진짜 검사 루틴을 어셈블리에서 찾아 들어가 보면, 입력을 trim 한 뒤 스택에 실어둔 32바이트 key 와 한 바이트씩 XOR 해서 전부 0x55 인지만 본다. key 를 그대로 뽑아 0x55 로 되XOR 하면 플래그가 나온다.
#dreamhack#ctf#reversing+5
 
BLOG2026-07-13
[🥉 브론즈 3] 출력되지 않는 flag를 함수 인자에서 훔치다 — DreamHack Check Function Argument 풀이
blog

[🥉 브론즈 3] 출력되지 않는 flag를 함수 인자에서 훔치다 — DreamHack Check Function Argument 풀이

main이 어떤 함수를 flag 문자열 주소를 인자로 넘겨 호출하지만, 그 함수는 flag를 출력하지 않는다. 게다가 flag는 바이너리에 평문으로 없고 생성자가 런타임에 조립한다. x86-64 호출 규약상 첫 인자는 rdi이므로, 그 함수 호출 지점에 GDB 브레이크를 걸고 rdi를 읽어 flag를 그대로 가로챘다.
#dreamhack#ctf#reversing+4
 
BLOG2026-07-13
[🥉 브론즈 3] 세 단계 변환을 거꾸로 되돌리다 — DreamHack r-xor-t 풀이
blog

[🥉 브론즈 3] 세 단계 변환을 거꾸로 되돌리다 — DreamHack r-xor-t 풀이

입력 64자를 add·배열 뒤집기·xor 세 단계로 변환해 고정된 target과 strncmp하는 리버싱 문제. 세 연산이 모두 가역이라, target에서 xor 3을 풀고 배열을 다시 뒤집고 add 13을 되돌리면 올바른 입력이 그대로 복원된다. 그 입력이 곧 플래그 본문이고, 바이너리에 넣어 Nice!로 확인했다.
#dreamhack#ctf#reversing+4
 
BLOG2026-07-13
[🥉 Bronze 1] 죽은 코드 속 Caesar 복호기를 되살리다 — DreamHack Small Counter 풀이
blog

[🥉 Bronze 1] 죽은 코드 속 Caesar 복호기를 되살리다 — DreamHack Small Counter 풀이

바이너리는 실행해도 카운터만 세고 끝난다. flag를 만드는 flag_gen은 counter==5일 때만 불리는데 루프가 0에서 끝나 절대 도달하지 않는 죽은 코드다. flag_gen이 알파벳 테이블로 Caesar 복호를 한다는 걸 읽어내고, 암호문 IM 접두가 DH 로 풀리는 shift=5를 확정한 뒤 그 로직을 재현해 flag를 복원했다. GDB로 실제 flag_gen을 직접 호출해 결과가 정확히 일치함을 확인했다.
#dreamhack#ctf#reversing+4