이번 대회에서 유일한 C++ 코드이다. 개인적으로 C++을 정말 좋아하지만, 바이너리를 디컴파일해서 나오는 모습은 정말 징그럽더라
flag.txt, flag.txt.enc 두 개의 fd를 생성하고 TEA 알고리즘을 이용해 FLAG를 암호화한 내용을 ~.enc 파일에 작성해 저장한다. 그렇다면 우리는 위의 코드를 그대로 역연산해서 복호화하면 끝난다. 사실 이런 간단한 단순 연산 작업은 GPT한테 맡겨도 잘 나오지만...
디컴파일한 main 함수를 조금 더 자세히 살펴보면, FLAG 문자열을 8바이트씩 끊어 하나의 블록으로 처리하고 있다. 각 블록은 sub_2778 함수로 넘겨 암호화 작업을 수행한다. 또한 암호화 과정에 사용되는 키 역시 main 함수에서 정의하고 있는데 자세한 키 값을 아래와 같다.
v9[0] = 305419896;
v9[1] = -559038737;
v9[2] = -1159799057;
v9[3] = -1091576147;
sub_2778은 위의 키 값과 평문 블록을 전달받아서 sub_253F와 sub_2468에 전달하여 암호화 작업을 수행한다. 그 중 sub_2468의 경우 jumpout 명령을 통해 특정 위치의 주소로 점프하는데, 해당 주소로 가보면 TEA 암호화 알고리즘의 일부임을 확인할 수 있다. (사실 잘 모르겠는데 GPT한테 코드 스니펫만 던져모니 TEA 암호화 코드라고 해주길래 그런가보다 하고 넘어갔다.)
이제 바이너리의 핵심적인 파트인 암호화 알고리즘의 작동방식에 대해 파악했으니, 동일한 과정에 대해 역연산을 수행하는 코드를 작성해주면 된다. 사실 어셈블리 코드를 보고 그대로 순서만 바꿔서 진행해도 거의 맞지만, 나중에 혼자 공부할 때 진행해보도록 하고 지금은 빠른 시간 내에 해결해야하므로 만만한 파이썬으로 작성해보자.
def decrypt(v, k):
y, z = v[0], v[1]
delta = 0x9E3779B9
s = delta << 5
for _ in range(32):
z -= ((y << 4) + k[2]) ^ (y + s) ^ ((y >> 5) + k[3])
z &= 0xFFFFFFFF
y -= ((z << 4) + k[0]) ^ (z + s) ^ ((z >> 5) + k[1])
y &= 0xFFFFFFFF
s -= delta
s &= 0xFFFFFFFF
return y, z
encrypted_data = [...]
key = [305419896, 3767076783, 3134989796, 3198238759] # Adjusted for 32 bits
decrypted_data = []
for i in range(0, len(encrypted_data), 2):
decrypted_block = decrypt([encrypted_data[i], encrypted_data[i + 1]], key)
decrypted_data.extend(list(decrypted_block))
decrypted_text = ''.join([chr(d & 0xFF) for d in decrypted_data])
print(decrypted_text)
bob{lets_have_a_TEAtime!!}\n\x00\x00\x00\x00\x00
'BoB > write-up' 카테고리의 다른 글
[BoB CTF] web) 02_old_python_interpreter (0) | 2023.08.24 |
---|---|
[BoB CTF] web) 01_flying_chicken (0) | 2023.08.24 |
[BoB CTF] misc) 03_I'm_Happy (0) | 2023.08.24 |
[BoB CTF] misc) 02_bob_secret_note (0) | 2023.08.24 |
[BoB CTF] misc) 01_find me if you can (0) | 2023.08.24 |