rev-basic-8

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

dreamhack.io

 

이 문제도 여타 다른 문제와 마찬가지로 입력값을 넣고 일련의 연산을 취한다음 이것이 특정한 값과 일치하는지를 비교하여 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

 

이를 실행하면 플래그를 얻을 수 있으며, 뜨끔하는 문장을 얻을 수 있다.ㅋㅋ

+ Recent posts