이 문제도 여타 다른 문제와 마찬가지로 입력값을 넣고 일련의 연산을 취한다음 이것이 특정한 값과 일치하는지를 비교하여 Correct / Wrong을 출력하는 문제이다. 역시나 Correct가 나올 수 있는 입력값을 찾아야 한다.
아래는 프로그램의 main 코드이다. 이중 일부 부분의 직접 변수명이나 타입을 바꾸어준 상태이다.
보면 uVar1의 값을 가지고 Correct / Wrong 결과를 가르는데 이 값을 결정짓는게 FUN_140001000 함수이다. 이 함수의 인자로 입력값이 들어가는걸 보면 이 함수가 핵심인게 분명하다.
아래 코드는 FUN_140001000 함수의 decompile 결과이며, 미리 각 변수의 이름을 해석하기 편리하도록 고쳐둔 상태이다.
코드를 보면 20개의 문자를 하나씩 비교하는데, 이 때 입력값에 대해 일련의 연산을 취한 후 이 값이 문제 속 데이터와 일치하는지 검사한다.
DAT_140003000 위치를 가보면 정확히 20개의 16진수 데이터가 위치해있음을 알 수 있다.
그러나 위 코드에서 입력값에 -5가 곱해지는 것도 그렇고 좀 더 자세한 분석이 필요할 것으로 보여 어셈 코드로 다시 살펴보았다.
입력값에 대한 연산은 140001031과 140001037 이렇게 두 부분이 핵심이다.
- 14000102d: 입력값에 대해 byte 단위로 가져온 후
- 140001031: 이에 대해 FB를 곱하고
- 140001037: 그 결과에서 하위 1바이트만 남기고 지운다.
여기서 연산 결과에 대해 하위 1바이트만 남기고 지우기 때문에, 곱셈 결과가 어떻게 나오든 문제 속 하드코딩되어 있는 각각의 바이트와 하나씩 비교가 가능한 것으로 보인다.
이 문제를 풀기 위해 처음에는 곱셈의 반대인 나눗셈으로 시도해보려고 했지만, 아무래도 AND 연산으로 하위 바이트를 자르고 비교하는 형태이기 때문에 역연산으로 정답인 입력값을 찾기 어려울 것 같았다. 그래서 결국 가능한 입력 범위 안에서 브루트포스 코드를 작성하였다.
answer = [0xAC, 0xF3, 0x0C, 0x25, 0xA3, 0x10, 0xB7, 0x25, 0x16, 0xC6, 0xB7, 0xBC, 0x07, 0x25, 0x02, 0xD5, 0xC6, 0x11, 0x07, 0xC5]
input_data = []
for i in range(20):
for num in range(0x20, 0x7E):
if (num * -5) & 0xFF == answer[i]:
print(chr(num), end='')
break
이를 실행하면 플래그를 얻을 수 있으며, 뜨끔하는 문장을 얻을 수 있다.ㅋㅋ
'Wargame' 카테고리의 다른 글
[Dreamhack] Inject Me!! write-up (0) | 2023.10.26 |
---|---|
[Dreamhack] patch write-up (0) | 2023.10.15 |
[Reversing.kr] Easy Crack (0) | 2023.07.06 |
[DigitalForensic with CTF] Multimedia - 제 친구의 개가 바다에서... (0) | 2022.02.03 |
[DigitalForensic with CTF] Network - Sans Network Forensic [Puzzle 4] #2 (0) | 2022.02.01 |