CTF & Wargame(REVERSING)

[dreamhack] level2 ez_rev

KWAKBUMJUN 2025. 3. 11. 21:42

문제 파일 실행 화면

해당 파일을  실행하면 특정 값을 입력할수 있고, 입력을 마치면 KKKK라는 문자열이 출력된다. 

 

IDA 분석

main 함수 디컴파일

main 함수를 디컴파일 하면 위와 같은 코드를 확인할수 있다.

 

1. 사용자에게 입력을 받고 입력받은 값을 _0에 저장

2. 사용자의 입력값을 특정 연산을 통해 변환함

3. v12의 문자열과 비교

4. (!v8 && !v9) == v8  조건을 만족하면 Correct 출력

 

ida에서 off_4E50F0의 값을 확인하면 "qksrkqs"가 저장되어 있는 것을 확인할수 있다.

 

사용자가 입력한 값을 변환한 값이 "|l|GHyRrsfwxmsIrietznhIhj"와 일치해야 한다.

따라서 변환된 값이 |l|GHyRrsfwxmsIrietznhIhj가 되려면 어떤 값을 입력해야하는지 알아내야한다.

 

따라서 flag를 알고싶으면 입력값을 변환하는 함수들을 역연산하면 된다.

 

1. shift_right --> shift_left

2. shift_left --> shift_right

3. xor_with_key 그대로

 

위와 같이 역연산을 진행하면 flag를 알아낼수 있을 것이다.

 

exploit 코드

def shift_left(data, count):
    """문자열을 왼쪽으로 count회 회전"""
    result = bytearray(data)
    for _ in range(count):
        first = result[0]
        result = result[1:] + bytearray([first])
    return bytes(result)

def shift_right(data, count):
    """문자열을 오른쪽으로 count회 회전"""
    result = bytearray(data)
    for _ in range(count):
        last = result[-1]
        result = bytearray([last]) + result[:-1]
    return bytes(result)

def xor_with_key(data, key):
    """문자열을 키와 XOR 연산"""
    result = bytearray(len(data))
    for i in range(len(data)):
        result[i] = data[i] ^ key[i % len(key)]
    return bytes(result)

# 목표 문자열
target = "|l|GHyRrsfwxmsIrietznhIhj".encode()

# 키
key = "qksrkqs".encode()

# 역연산 순서:
# 5. shift_right(3)의 역연산 -> shift_left(3)
result = shift_left(target, 3)

# 4. xor_with_key의 역연산 -> 다시 xor_with_key (XOR은 자기 자신이 역연산)
result = xor_with_key(result, key)

# 3. shift_left(3)의 역연산 -> shift_right(3)
result = shift_right(result, 3)

# 2. xor_with_key의 역연산 -> 다시 xor_with_key
result = xor_with_key(result, key)

# 1. shift_right(3)의 역연산 -> shift_left(3)
result = shift_left(result, 3)

print("정답:", result.decode())

<결과>

정답: DH{ShiftxorShiftxorShift}