핵심 부분만 확인해보려고 한다.

분석할 파일은 Input으로 값을 받고, Serial까지 입력 받는 프로그램이다.

이 때, Serial은 Text 파일에 정해져 있고, 그 Serial에 맞는 Input 값을 구하라는 것이 이 문제의 내용이다.

 

그러다면 Serial은 정해져있고, Input 값은 사용자가 맞추는 것이므로 Input 값에 대한 어떤 뭐시기, 거시기가 있은 뒤에 Serial 값과 같은지 아닌지 비교를 하는 루틴이 있을 것이라 예상해볼 수 있다.

 

그렇다면 Input 값을 어떻게 조작하는지 살펴보는 것이 제일 중요한 루틴이라고 할 수 있겠다.

아래 그림을 살펴보자.

 

 

 

일단 왼쪽 옆구리를 보면 시커먼 선이 있는 것으로 봐서 루프를 돌고 있는 것이 확인된다.

그리고 CMP 명령어를 뭔지 모르지만 보면 3번 주기 혹은 반복하는 루틴일 것이다.

 

위에서 XOR 연산에 대해서 주목할 필요가 있다.

XOR EAX, EAX 와 같이 쓰이는 경우와 XOR EAX, 43 혹은 XOR EAX, key value 등의 형식으로 표현되어 자주 사용되는 XOR은 후자의 경우 특정 값에 대해 간단히 암/복호화 할 때 사용되곤 한다.

 

이때, 원파일은 Input이고, Key는 10, 20, 30 로 input 값이 1byte 씩 바뀔 때마다 바뀐다.

그렇다면 Serial 또한 똑같이 첫번째 byte는 10로, 두번째 byte는 20로, 세번째 byte는 30로 xor 해보자

 

주어진 Serail = 5B 13 49 77 13 5E 7D 13

 

XOR 5B, 10 = 4B 'K'

XOR 13, 20 = 33 '3'

XOR 49, 30 = 79 'y'

XOR 77, 10 = 67 'g'

XOR 13, 20 =  33 '3'

XOR 5E, 30 = 6E 'n'

XOR 7D, 10 = 6D 'm'

XOR 13, 20 =  33 '3'

 

결과 : K3yg3nm3

 

 

 

 

 

 

 

 

 

Reversing.kr의 Challenge의 Easy Crack 문제를 풀어보았다.

우선, 실행 화면을 살펴보면, 아래와 같이 무언가를 입력하도록 새로운 윈도우 창이 생성된다.


[그림1. exe 파일 실행화면]


무언가 제대로 된 값을 넣어야됨을 알 수가 있다.

우선 소스를 상상해보면 값을 입력하였고, 그 입력 값과 Key 값을 비교할 것이라는 흐름이 떠오를 수 있다.

그럼 비교를 위해서 할 수 있는 흐름은? 단순 string 문자열 끼리 비교할 수도 있고.. (이런 흐름이라면 때땡큐)

아니면 입력한 값과 Key 값을 1byte 씩 값 비교할 수도 있을 것이라 생각할 수 있다.


한 번 OllyDbg로 살펴보자. 

처음부터 흐름을 A -> B -> C -> D ..... 로 끌고갈 실력도 안되거니와 복잡하기 때문에 Referenced String을 확인하여 우리가 체크해야할 Routine 영역으로 바로 넘어가도록 한다.


[그림2. Reference String 확인 결과]


위 [그림2]와 같이 왠지 느낌이 확 오는 문자열들을 확인해 볼 수 있다. 여기 중에 Congratulation !!을 클릭하여 해당 위치로 한 번 가보자.


[그림3. Contratulation 문자열을 따라 해당 영역으로 이동 후, 해당 영역의 시작 지점에 Break Point Set]


위와 같이 Break Point를 걸어 놓고, F9를 통해 Running을 하면, Key 입력받는 창이 생기며, 그 Key 창에 임의의 값을 입력 하고 Enter를 누르면 우리가 Break Point 설정한 위 지점에서 멈추게 된다.


그리고 천천히 밑으로 내리다보면 (F8로) GetDlgItemTextA라는 API를 만날 수 있다. GetDlgItmeTextA를 통해 메시지 박스에서 입력한 값을 API 인자에 포함된 Buffer 주소 값에 Input 할 수 있다.


[그림4. GetDlgItemTextA API를 이용하여 MessageBox 입력 값을 받아온다.]



[그림5. GetDlgItemTextA를 통해 얻어온 값]


이후 이 값의 2번째 위치한 o와 'a' (61h)를 비교하게 된다. 이를 통해 2번째 위치한 문자열은 왠지 'a' 일 것 같은 느낌이 팍 든다. 그리고 입력 값의 2번째 위치한 문자가 'a'와 다르다면 'Incorrect Password'를 띄우는 루틴을 태우도록 JNZ 분기가 들어가 있다. (왜 첫번 째 문자열 먼저 비교하지 않을까 의심해볼 필요가 있다.) 그리고 그 밑에 5y 문자열을 집어넣고 call 401150을 호출하는데 그냥 추측컨데 왠지 a 뒤에 오는 문자열은 5y가 되어야할 것 같은 느낌이다.


[그림6. 입력 값의 2번째 문자열이 a 인지 체크 이후, JNZ 분기, a일 경우 5y 비교]


한번 step into (F7) 로 401150 함수 안을 들여다 보자.


[그림7. 401150 함수 안, a와 비교 이후 5y 문자열 비교]


이후의 문자열은 R3versing 문자열을 비교하는 루틴이다. R3versing 문자열 비교를 위해 1byte 씩 이동해가면서 1byte 비교를 하고 있으며, CMP BYTE PTR SS:[ESP+4], 45를 보면 45h는 E를 의미하며 ESP+4는 입력 값의 첫 번째 byte를 의미한다. 제일 처음에 2번째 byte를 a로 비교하면서 첫번째 바이트 비교를 왜 먼저 안했는지 의문이 든다고 했는데, 뒤에서 첫번째 byte를 비교함을 확인할 수 있다.


[그림8. 5y 문자열 비교 이후에 R3versing 비교]


이렇게 비교해본 문자열을 종합해보면 Ea5yR3versing 이라는 문자열을 확인할 수가 있다.




# REPE는 ECX 값 만큼 SCAS (EAX와 SCAS 이후 나오는 주소 값과 비교), STOS (EAX/AH/AL을 STOS 이후 

   나오는 주소 값에 저장) 할 수  있는데 같을 경우, 그 비교를 멈추고 나온다.


# REPNE는 ECX 값 만큼 비교 및 저장하고, 같지 않을 경우, 비교를 멈추고 나온다.


















+ Recent posts