chon

[Dreamhack] rev-basic-4 Write up 본문

Reversing/Dreamhack Write up

[Dreamhack] rev-basic-4 Write up

chon29 2025. 11. 18. 18:49

[ 문제 링크 | https://dreamhack.io/wargame/challenges/18 ]

 

rev-basic-4

Reversing Basic Challenge #4이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출

dreamhack.io

 

[ 문제 설명 ]

드림핵 워게임 revering LEVEL 1

 

[ 문제 풀이 ]

먼저 chall4.exe 파일을 직접 실행해보면, 콘솔 창에서 Input : 이라는 문구와 함께 입력값을 요구하는 걸 볼 수 있다.
즉, 사용자가 입력한 값이 내부에서 검증되어 맞으면 “Correct”, 틀리면 “Wrong” 이 출력되는 구조임을 알 수 있다.

이제 실제 검증 로직이 어떻게 동작하는지 확인하기 위해 IDA를 이용해 바이너리를 분석해보자.

 

IDA 구조

 

IDA로 디컴파일한 결과, main 함수 내부는 입력값을 받고 이를 특정 함수로 넘겨 검증하는 구조임을 확인할 수 있다.
상단에서는 스택 초기화 및  보안 쿠키 설정( __security_cookie )이 수행되고, 하단의 박스로 표시한 부분에서 핵심 로직이 실행된다.

 

흐름을 따라가 보면 다음과 같다. 

  • "Input : " 문자열이 출력되며, 사용자 입력을 받을 준비를 한다.
  • 입력값은 버퍼에 저장된 뒤, sub_140001000 함수의 인자로 전달된다.
  • 해당 함수는 입력값이 올바른지 검증하는 역할을 수행한다.
  • 함수의 반환값은 eax 레지스터에 저장되며, 바로 아래의 test eax, eax 명령어를 통해 반환값이 0인지 여부가 확인된다.
  • 반환값이 0이면 jz 분기를 따라 "Wrong"이 출력되고,
    0이 아니면 "Correct"가 출력된다.

 

main 함수 분석

main

IDA의 함수 목록에서 main을 더블클릭해 들어가면 다음과 같은 C 형태의 코드로 디컴파일된 내용을 볼 수 있다.

 

해당 함수에서는 v4라는 256바이트 크기의 버퍼를 초기화하고(memset), "Input : " 문자열을 출력한 뒤 사용자 입력을 v4에 저장한다. 그 후 sub_140001000(v4) 함수를 호출하여 입력값을 검증한다.

 

 

이 함수의 반환값이 0이 아닐 경우 "Correct", 그 외에는 "Wrong"을 출력하는 구조이다.

즉, 프로그램의 핵심은 sub_140001000 함수 내부의 연산 로직에 있으며, 이를 분석함으로써 어떤 입력값이 올바른 flag인지 유추할 수 있다. 따라서 다음 단계에서는 해당 함수로 진입하여, 입력값이 어떻게 처리되고 어떤 연산을 거치는지 분석한다.

 

sub_140001000

main에서 넘겨받은 입력값(v4)은 sub_140001000 함수(의 인자 a1)로 들어온다. 여기가 진짜 'Correct'를 결정하는 핵심 로직이다.

코드를 보면 for 반복문이 나오는데, 이걸 분석해보면 i가 0부터 0X1C전까지, 즉 0부터 27번까지 28번을 반복한다.

입력값의 길이가 28이라는 걸 알 수 있다.

 

비교 로직을 보면 if 문 안에서 한 연산의 결과랑 byte_140003000[i]을 비교한다.

만약 두 값이 다르다면 함수가 종료되고, 28의 비교를 모두 통과하면 return 1;을 만나서 "Correct"가 출력된다.

 

sub_140003000

byte_140003000에 있는 28개의 바이트 값을 역으로 니블 스왑하면 원래의 입력값인 flag가 나온다.

dup는 'duplicate'의 약자니까 2 dup(0C6h)는 0xC6, 0xC6을 의미하고, 마지막 28번째 값은 5dup()의 첫 번째 0x00이다. C언어 문자열의 끝을 알려주는 NULL값까지 검사하는 것이다.

 

역연산 시 필요한 28개의 바이트를 순서대로 나열하면 다음과 같다.

[ 0x24, 0x27, 0x13, 0xC6, 0xC6, 0x13, 0x16, 0xE6, 0x47, 0xF5, 
  0x26, 0x96, 0x47, 0xF5, 0x46, 0x27, 0x13, 0x26, 0x26, 0xC6, 
  0x56, 0xF5, 0xC3, 0xC3, 0xF5, 0xE3, 0xE3, 0x00 ]

 

 

 

역연산 코드

# byte_140003000에 저장된 데이터
answer_key = [
    0x24, 0x27, 0x13, 0xC6, 0xC6, 0x13, 0x16, 0xE6, 0x47, 0xF5, 
    0x26, 0x96, 0x47, 0xF5, 0x46, 0x27, 0x13, 0x26, 0x26, 0xC6, 
    0x56, 0xF5, 0xC3, 0xC3, 0xF5, 0xE3, 0xE3, 0x00
]

flag = ""

# 각 바이트를 순회하며 니블 스왑(Nibble Swap) 수행
for b in answer_key:
    swapped_byte = ((b << 4) & 0xFF) | (b >> 4)
    flag += chr(swapped_byte)

print(f"[*] Flag: {flag}")

 

[ Flag ]

위에서 찾은 Flag를 입력하면 된다.

Br1ll1ant_bit_dr1bble_<<_>>  

 

[ 문제 해결 ]

 

'Reversing > Dreamhack Write up' 카테고리의 다른 글

[Dreamhack] Recover  (0) 2026.01.16
[Dreamhack] Happy New Year!  (0) 2026.01.14
[Dreamhack] Simple Crack Me Write up  (0) 2025.12.14
[Dreamhack] randzzz Write up  (0) 2025.11.20
[Dreamhack] rev-basic-3 Write up  (0) 2025.11.02