본문 바로가기

[+] Hacking/[-] Challenge Report

Simples Crackme 시즌 1 일부분 풀이.

제목은 말 그대로 일부분 풀이입니다.

이유인 즉슨! 키젠 소스는 공개하지 않기 때문입니다.

코드도 허접하고 최적화도 되어있지 않고 해서 창피합니다.

그렇기에 공개하지 않겠습니다.(실행 화면은 공개합니다 ^^)

아주 오랜만에 풀이를 포스팅하는 것 같은데요.

저번에 풀었던 심플스 크랙미 시즌1 에서 제가 재미있게 풀었던 문제를 골라 풀이를 하겠습니다 ㅎ

이번에 풀건 키젠미 인데요.


Key 값이 154C-6505-D2ADD0F3-A223-2870 일때 Name은 무엇인가
힌트 : Name은 두자리인데.. 알파벳일수도 있고 숫자일수도 있고..


이것이 심플스의 문제 입니다.

주어진 키값을 가지고 Name을 찾는 문제인데요.

의외로 간단하니 한번 분석을 해보죠!!



위 사진은 문제 키젠미의 사진인데요.

심플스 문제를 보면 Name은 두글자라 하였으니 두글자를 입력해보겠습니다.


앗!!!!

길이가 짧다는건가요?? ㅡㅡ;;

일단 이것부터 우회를 해야 문제를 풀 수 있을거 같으니 올리로 분석해보도록 하겠습니다.

일단은 key 폼에 출력된 문자열을 상대로 추적해보겠습니다.




해당 부분으로 이동한 사진입니다.

보니 위에 CMP구문이 있네요. EAX의 값과 셋팅되어있는 3이란 값과 비교한 후 밑에 보이는 JGE 분기문을 통해 분기하는군요.

EAX값에는 사용자가 입력한 Name의 길이가 저장됩니다.

CMP구문의 3을 2로 바꾸시거나 분기문을 수정하시면 글자제한은 쉽게 우회 됩니다.

그리고 나서는 아래와 EDX에 키값이 생성되어 저장 됩니다.



이제 성공메시지로 가봅시다.


성공메시지가 딱 봐도 Good Boy!! 같죠?

성공메시지 위로 보니 콜문이 두개군요.

0045BB98 의 콜문은 키값을 생성하는 콜문이고, 0045BBA4는 키값과 입력받은 키값을 비교해 아래에 있는 JNZ의 Zerobit를 1로 만들어 줄것인가 0으로 만들어줄것인가를 결정해 줍니다.

우리가 알아내야 할것은 주어진 시리얼이 어떠한 Name으로 만들어졌는지 알아내는 것이기 때문에 키값을 생성하는 콜문을 분석해 봐야겠습니다.



키값 생성 콜문에 들어가면 위와 같은 루틴이 보입니다.

키값을 생성하는 루틴인데요. 한줄한줄 분석을 해보겠습니다.


MOV EBX,[LOCAL.1]
LOCAL.1 에 들어있는 값을 EBX에 이동시키는군요!(LOCAL.1 은 EBP-4와 동일합니다.)

MOVZX ESI,BYTE PTR DS:[EBX+ECX-1]
EBX+ECX-1가 가리키는 1바이트를 ESI에 이동시키네요. (현재 EBX+ECX-1가 가리키는 값은 사용자가 입력한 Name 입니다.)

ADD ESI,EDX
ESI에 EDX를 더합니다.(현재 ESI에는 사용자가 입력한 Name이 들어가 있고 EDX에는 0x00이 들어있습니다. 결국 0x00을 더했으니 값은 그대로 겠네요 ^^)

IMUL ESI,ESI,772
ESI와 772를 곱한후 ESI에 저장하고 있습니다.

MOV EDX,ESI
ESI의 값을 EDX에 이동 시킵니다.

IMUL EDX,ESI
EDX와 ESI를 곱한후 EDX에 저장하는군요.

ADD ESI,EDX
ESI값에 EDX값을 더합니다.

OR ESI,ESI
ESI와 ESI를 OR 연산을 시킵니다. (트레이싱 해보시면서 레지스터 값을 보시면 아시겠지만 값은 변동되지 않습니다.)

IMUL ESI,ESI,474
ESI에 값과 474를 곱한후 ESI에 저장합니다.

ADD ESI,ESI
ESI값에 ESI를 더해줍니다.(결국 *2)

MOV EDX,ESI
ESI의 값을 EDX로 이동 시켜 줍니다.

INC ECX
ECX값을 하나 증가 시킵니다.

DEC EAX
EAX의 값을 하나 감소시킵니다.(EAX의 값은 사용자가 입력한 Name의 길이인데 두글자를 입력했으면 이 구문이 실행된 후에는 1이 되는 것 입니다.)

JNZ SHORT C4C65C9B.0045B89D
EAX의 값을 참조하여 0이 되지 않으면 다시 처음으로 돌아가 계산을 수행토록 합니다.

결국 두글자 입력하면 2번 반복 하는 것 입니다.

이걸 우리가 익숙한 수학 공식으로 바꿔본다면

첫번째 과정은 이렇게 됩니다.

(((입력한 문자열의 첫글자 * 0x772)*2)+(입력한 문자열의 첫글자 * 0x772))*0x474*2

두번째 과정은 또 이렇게 되구요.

(((첫번째 결과값+입력한 문자열의 두번째 글자)*0x772)*2 + ((첫번째 결과값+입력한 문자열의 두번째 글자)*0x772))*0x474*2

이렇게 정리해도 복잡하네요 ㅜㅜ..

트레이싱 하면서 레지스터 보시면 금방 이해가 가실거에요 ㅎㅎ

무튼 위 계산식을 프로그램으로 만드시고 생성된 시리얼의 값이 제시된 시리얼의 값과 맞아 떨어질때 연산하던 입력 값들을 출력해주면 됩니다.

전 아래와 같이 돌려 나왔습니다.


Name값은 지웠습니당.

루틴을 다 설명드렸으니 그대로 코딩만 하시면 되요 ㅎㅎ

일부분 풀이가 끝났네요.

틀렸거나 조금 더 보충할 부분이 있다면 댓글 남겨주세요 ^^

수고하셨습니다. ㅎ