CodeEngn Basic 20

Kail-KM
|2015. 6. 4. 00:35

문제 확인


이번 문제는 정말 오래 걸렸다. 알고리즘 분석에서 XOR 연산으로 인하여 정말 난감해서 다른 블로그를 여러개 찾다가도 이해가 되지 않아 고민하다가 갑자기 문득 떠오른 생각에 풀 수가 있었다. 이제부터 풀이를 시작해보자.



풀이


우선 CreateFileA에 Mode = OPEN_EXISTING에 의하여 해당 이름의 파일이 존재하는지 여부를 확인하는 부분이다. 존재하지 않을 경우 바로 종료되거나 실패구문으로 가게 될 것이므로 해당 파일의 이름을 만들어주어야 한다.


해당 파일의 존재 여부를 확인하고 그 뒤에는 ReadFile에 의하여 파일의 크기를 읽어 들인 다음 0x12(18)과 크기를 비교한다. 따라서 파일에 18자리의 문자를 채워주어야 한다는 것을 쉽게 알 수가 있다.


이 부분은 실패에 해당하는 알고리즘으로 CrackMe라는 문자열 뒤에 -Uncracked 라는 문자를 추가해주는 부분이다. 이 부분으로 가지 않기 위해 얼마나 노력한지를 모르겠다. 비중이 없는 부분이니 생략하겠다.



알고리즘 분석


이제부터 본격적인 알고리즘을 분석할 것이다. 사진에 직접 달아 놓는 것이 설명에 편할 것 같기에 같이 설명을 하겠다. 우선 위에서부터 key 파일에 입력 된 내용을 ESI에 복사를 하고 EBX 또한 같은 값이 지만 MOV BL,41로 인하여 EBX의 맨 뒷값이 41로 설정이 된다.

여기서 EBX의 41은 중요한 것이다. 바로 붉은 상자에 표시한 XOR AL,BL을 위해서 우리는 이해를 해야한다. 주석에 달아 놓긴 했지만 Key파일의 첫 문자가 "A"(41)일 경우에 바로 XOR 연산에 의해서 AL에 0이 반환이 된다. 

이 0은 붉은 상자의 5번쨰 밑에 명령어인 CMP AL, 0의 비교문에 의하여 알고리즘이 더이상 진행 되지 않고 덤프 창에 표시 된곳에 값을 저장하고 빠져나오게 된다. 하지만 여기서 우리는 XOR AL, BL에 의하여 덤프에 저장될 값이 0 이므로 변화가 없다(이 부분이 중요한 말이다.)

이런식으로 알고리즘은 진행이 된다. 만약 첫 문자가 A가 아닐 경우 XOR에 의한 값을 저 부분에 저장을 하고 BL=42의 값으로 바뀌게 되고 이제 두번쨰 문자와의 XOR 연산을 한 후 다시 저 부분에 값을 더해주는 식으로 진행이 된다.


풀이_2


이와 같이 나는 첫 문자에 A를 입력하므로 바로 알고리즘에서 빠져나오도록 유도하였다. 이유는 밑에 부분에 가다보면 충분히 이해 할 수가 있다. 아직은 호기심을 그냥 품은채 계속 글을 읽어주길 바란다.


이제 알고리즘 부분을 빠져나와서 XOR DS, 12345678을 진행하는데 DS의 값이 0이기에 결국 12345678이 그대로 덤프에 저장이 된다. 만약 여기서 DS 값이 0 이 아니라면 12345678의 값은 변하게 되고 결국 나중에 Key 값 비교에 있어서 복잡해지므로 나는 저 숫자들이 그대로 얌전히 올 수 있도록 일부러 첫문자에 A를 넣어주었다.


이렇게 위의 과정을 거치고 온 다음에 드디어 가장 중요한 비교문이 나타났다. CMP EAX, DS를 비교하는 것이다. 내가 KEY파일에 뒷 부분 4글자에 일부러 해당 값을 갖는 ASCII 문자를 넣어 주었다. 결국 이렇게 두개의 비교될 값들이 안전하게 유지되므로 인하여 같아 질 수가 있다.

그리고 이러한 CMP문에서 두 개의 값이 같기에 Zero Plag에 1이 셋팅이 되며 이러한 ZP = 1은 SETE 명령어를 작동하도록 하므로 인하여 AL에 1의 값을 씌워준다.


위에서 쓰인 SETE AL에 의하여 AL에는 1이 쓰였고, 최종 성공 분기점에서 CMP AL, 1에 의하여 결국 성공문으로 갈 수 있게 된다.


아래는 성공화면이다. 정말 오래걸려서 얼마나 기쁜지 모르겠다. 여기서 하나 알아야할 것은 ASCII(0~Z) 뿐만 아니라 해당 지정 값들을 복사해서 위의 문제와 같이 인식하게 할 수가 있다. 당연히 인식이 되지 않을 줄 알고 XOR 연산에 바뀌는 값을 맞추기 위해 얼마나 개고생을 한지 모르겠다.

 

이제 CodeEngn!를 출력하기 위해 마지막 풀이를 해보자.


최종 풀이


우선 알고리즘을 거치고 나서 CodeEngn!가 출력 되도록 XOR 연산을 하나하나 직접(계산기가)해서 구한 값을 Key 파일에 써주면 된다. 그렇게 나온 값을 통해 끝의 뒷 4자리에 어떤 값을 입력 할지 확인을 하면 된다.  

참고로 키 파일에 값을 입력할떄 00을 넣어야하는 경우가 있는데 이는 메모장을 통해서는 절대로 불가능하다. 그럴 때 필요한 것이 바로 Hex Editor이다. HxD를 통해 키 파일을 열면 우리가 원하는 값을 넣을 수가 있다.

하지만 위와 같이 할 경우에는 NULL 문자가 포함 되지 않아서 CodeEngn!!%#@!의 값이 모두 출력이 되버린다. 따라서 우리는 이제 !의 뒤에 NULL을 추가해보면 된다.


밑의 사진 2장은 ! 뒤에 NULL 문자를 추가해 주는 과정이다. 위에서 구하는 방법은 설명하였기에 NULL문자가 인식 되도록 4n의 값을 ! 뒤에 넣어주면된다.

하지만 여기서 또 문제가 있다. 이렇게 하고 출력을 할 경우 CodeEngn!!로 출력이 된다는 것. 즉 문자열의 끝에 자동으로 !가 추가 되는 것으로 우리가 !를 추가해서는 안되는 것이 였다. 멍청하게도... 그럼 다시 "!"를 지우고 그 부분에 NULL을 추가해주자.


이제 마지막 과정이 끝났다. 아래와 같이 알고리즘을 지난후에 이루어지도록 키 값을 입력해주어야 한다.




드디어 성공 화면이 출력 되었다. 정말 힘들었다. 여기서 알아야 할 것은 HxD를 통해서도 값을 입력 할 수 있다는 것을 잊어서는 안될 것 같다. 이렇게 리버싱은 툴에 대한 이해도도 필요한 것 같다. 처음엔 00을 어떻게 입려할지 정말 고민했다. 하지만 이렇게도 쉽게 입력할 수 있는 방법이 있었다니...

마지막 문제인 만큼 헤이해 질뻔 했지만 이렇게 고생스러운 문제가 나와서 정말 참신했다. 리버싱을 하면서 이처럼 한가지 의문을 갖고 그것을 해보면 되는 일이 종종 있는 것 같다. 참신한 생각이 필요한 이유인것 같다. 여기까지 부족한 풀이 읽어주셔서 감사합니다. 모두들 열공하세요. 

P.S 질문하지마요..나도 모르니까...그냥 직접해보는게 답 @Google



'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 03  (0) 2015.06.28
CodeEngn Advance 01  (0) 2015.06.27
CodeEngn Basci 19  (0) 2015.06.03
CodeEngn Basic 18  (0) 2015.06.03
CodeEngn Basic 17  (0) 2015.06.02