ZeroZero's MiraclE
from : http://www.crackmes.de/users/zerozero/miracle/
==================================================
오늘 함께 할 크랙미는 저번보다 한 단계 발전한 방식이다.
(아마 그럴 것이다. 나도 지금 글쓰면서 처음 해보는지라...)
이번에도 아무거나 쳐보자.
흠 fuck you 하려던 건 아니지만... 쉽다니까 믿어 보자.
디버거로 열어 보자.
newbie를 위한 크랙미라는 것을 단박에 알 수 있다. 코드가 얼마 안 된다.
굳이 디버거로 찾기나 trace를 쓸 필요가 없다. 오늘은 그냥 보기로 한다.
보시기 쉬우라고 기계어 부분은 안 보이게 하였다. 양해바란다.
저 위의 부분은 알 필요 없고 Getdlgitem부터 보면 된다.
Getdlgitemtext는 API함수의 하나로서 텍스트박스 내용물을 가져오는 함수이다.
박스가 2개이니까 두 번 써야 한다.
중간은 뭐냐고? 이름을 4글자 이하로 입력하면 메시지 박스를 띄우는 부분이다.
004010E0 |.>OR EAX,EAX
004010E2 |.>JE SHORT MiraclE.004010E9
004010E4 |.>CMP EAX,4
004010E7 |.>JNB SHORT MiraclE.004010FE
아무리 쉬운 매뉴얼을 봐도 이런 것까지는 안 씌여 있지만 나는 개뉴비이므로 적도록 하겠다.
OR EAX,EAX 하는 것은 이 값이 공백인가? 하는 것을 찾기 위함이다.
Getdlgitemtext 하면서 EAX로 문자열 길이가 들어간다.
OR 0,0 하면 0 나오므로 메시지 박스로 점프, 아니면 통과하고
다시 4와 비교하여 4보다 작지 않으면 004010FE로 점프하여 입력한 Serial 값을 불러온다.
설명하고 나니 굉장히 찌질하므로 나머지는 자세한건 알거 없고 GetDlgItemTextA 부분에서 입력값을
각각 004030E8과 004032E8에 저장한다는 것만 알아두고 밑으로 내려가자.
입력값을 다 받자마자 40112E로 점프하는 것을 볼 수 있다.
아마 여기서 검사를 하겠지?라고 생각할 수 있다.
여기부터는 그림을 보면서 하기가 어려우므로 구문을 복사해서 붙여넣도록 하겠다.
0040112E $>PUSH EBP
0040112F .>MOV EBP,ESP
00401131 .>PUSH EBP
00401132 .>MOV EBP,ESP
00401134 .>LEA ESI,DWORD PTR DS:[4032E8] 아까 시리얼을 저장했던 주소를 ESI에 넣고 있다.
0040113A .>LEA EDI,DWORD PTR DS:[4034E8] 첨보는 주소다. 적어넣을 공백이라고 보면 되겠다.
00401140 .>MOV DWORD PTR DS:[EAX+EDI],0
00401147 .>MOV ECX,EAX EAX(=시리얼 길이)를 ECX로 넣고
00401149 .>OR ECX,ECX 0인지 확인하여
0040114B .>JE MiraclE.0040120B 0이면 훡유
00401151 .>MOV EBX,0 EBX에 0을 넣었다.
00401156 >>MOV AL,BYTE PTR DS:[EBX+4030BF]
여기에서 AL에 EBX+4030BF에 있는 뭔가를 넣고 있다.
EBX는 방금 0이라고 했으니 4030BF에 뭐가 있는지 보자.
해당 주소에는 ZeroZero라고 적혀 있지만 방금 읽은 것은 Z뿐이다. (BYTE라고 했응게)
일단 계속 보자.
0040115C .>MOV AH,BYTE PTR DS:[ESI] 입력한 시리얼에서도 1바이트 읽어 AH에 저장하였다.
0040115E .>XOR AH,AL 두 글자를 XOR 하여 결과는 AH로 간다.
00401160 .>MOV BYTE PTR DS:[EDI],AH AH를 EDI에 저장하였다.
00401162 .>INC ESI 여기부터 401173까지는 약간 상세히 볼 필요가 있다. ESI 주소를 +1하고
00401163 .>INC EDI 저장할 주소 +1하고
00401164 .>INC EBX EBX=0이었는데 1늘리고
00401165 .>DEC ECX ECX=시리얼 길이었는데 1줄이고
00401166 .>CMP EBX,8 EBX와 8을 비교해서
00401169 .>JNZ SHORT MiraclE.00401170 0이 아니면(여기선 JNE나 다름없다.) 401170으로 가고
0040116B .>MOV EBX,0 0이면(같으면) EBX=0 한다. 즉 8글자 읽은 후 다시 처음으로 간다.
00401170 >>CMP ECX,0
00401173 .>JNZ SHORT MiraclE.00401156 ECX가 0이 아니면 00401156으로 돌아가서 반복한다.
...해서 입력한 시리얼과 "ZeroZero" 8바이트를 XOR한 것이 지금 EDI 주소로 다 들어갔다.
"ZeroZero" 를 시리얼 길이만큼 돌리므로,
만약 5글자를 시리얼로 입력했다면 "ZeroZ"만큼만 XOR 하게 되고
10글자를 입력했다면 "ZeroZeroZe"만큼 하게 된다.
이럴거면 왜 Zero로 4바이트씩 안했냐는 생각이 들지만 그건 내 알 바 아니고 다음으로 넘어가자.
생각보다 길지 않은가? 그래도 참고 보도록 하자. 타자 치고있는 사람이 더 힘들다.
그러고 보니 처음에 VERY easy 라고 했던 것 같은데... 어쨌든...
00401175 .>LEA ESI,DWORD PTR DS:[4034E8] EDI였던 주소를 ESI에 넣었다. XOR한게 들어있다.
0040117B .>LEA EDI,DWORD PTR DS:[4036E8] 또 다른 주소가 등장하였다. EDI가 가리키게 된다.
00401181 .>PUSH MiraclE.004032E8 ; /String = "" 입력한 시리얼 주소를 넣고
00401186 .>CALL <JMP.&KERNEL32.lstrlenA> ; \lstrlenA 함수로 문자열 길이를 얻었다.
0040118B .>MOV DWORD PTR DS:[EAX+EDI],0
00401192 .>MOV ECX,EAX
00401194 .>MOV EBX,0
00401199 >>MOV AL,BYTE PTR DS:[EBX+4030C8] 4030C8에는 "00 \~5.)" 이렇게 써있다.
0040119F .>MOV AH,BYTE PTR DS:[ESI] 좀전의 XOR 결과물을 1글자 AH에 넣은 뒤
004011A1 .>XOR AH,AL XOR 하고... 나머지 설명은 생략한다.
004011A3 .>MOV BYTE PTR DS:[EDI],AH
004011A5 .>INC ESI
004011A6 .>INC EDI
004011A7 .>INC EBX
004011A8 .>DEC ECX
004011A9 .>CMP EBX,6 이번에는 4030C8로부터 6글자만 사용하고 있다. 즉 "00 \~5"만 사용한다.
004011AC .>JNZ SHORT MiraclE.004011B3 * 주의 : 암호화하는 글자에 공백이 포함되어 있다.
004011AE .>MOV EBX,0
004011B3 >>CMP ECX,0
004011B6 .>JNZ SHORT MiraclE.00401199
불행히도 아까 했던 짓을 다시 하고 있다. 시리얼 길이에 따라
00 \~500 \~500 \~500 \~500 \~500 \~5 뭐 이런 글자들을 XOR시킬 것이다.
주의할 점은 아까 XOR 시킨 것을 또 XOR 시켰다는 것이다..
설마 또 하진 않겠지? 계속 보자.
004011B8 .>PUSH MiraclE.004036E8 ; /String2 = "" XOR한 결과물이다.
004011BD .>PUSH MiraclE.004030CF ; |String1 = ")4<]E2+," 괴상한 글자를 또 읽었다.
004011C2 .>CALL <JMP.&KERNEL32.lstrcmpA> ; \lstrcmpA 글자가 같은가?검사한다.
004011C7 .>OR EAX,EAX 같다면 0(=equal)이 나올 것이고 이걸 OR시키면 또 0(=equal)이다.
004011C9 .>JNZ SHORT MiraclE.004011F6 같지 않다면 훡유.
004011CB .>PUSH MiraclE.004030E8 여기부터는 맞다고 메시지 창 띄우는 곳.
004011D0 .>PUSH MiraclE.0040307D ; ASCII "Great, Now write a tut and send to crackmes.de .: Registered to: "
004011D5 .>CALL MiraclE.00401270
004011DA .>PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004011DC .>PUSH MiraclE.00403017 ; |Title = "Good boy"
004011E1 .>PUSH MiraclE.0040307D ; |Text = "Great, Now write a tut and send to crackmes.de .: Registered to: "
004011E6 .>PUSH 0 ; |hOwner = NULL
004011E8 .>CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
004011ED .>PUSH 0 ; /ExitCode = 0
004011EF .>CALL <JMP.&KERNEL32.ExitProcess> ; \ExitProcess
004011F4 .>JMP SHORT MiraclE.00401209
004011F6 >>PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004011F8 .>PUSH MiraclE.00403004 ; |Title = "Error, Bad Cracker"
004011FD .>PUSH MiraclE.0040303E ; |Text = "Hey!, Dont fuck Me!, its very easy"
00401202 .>PUSH 0 ; |hOwner = NULL
00401204 .>CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401209 >>JMP SHORT MiraclE.0040121E
0040120B >>PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0040120D .>PUSH MiraclE.00403004 ; |Title = "Error, Bad Cracker"
00401212 .>PUSH MiraclE.00403061 ; |Text = "You have lost the serial :P"
00401217 .>PUSH 0 ; |hOwner = NULL
00401219 .>CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
0040121E >>MOV ESP,EBP
00401220 .>POP EBP
00401221 .>LEAVE
00401222 .>RETN 4
결국 요약하자면 : 이름은 4글자 이상 아무렇게나 쓰면 되고 ,
"Zero" 와 "00 \~5" 를 XOR시킨 것이 ")4<]E2+," 가 되는 글자를 입력하면 된다.
이건 코딩하든지 XOR을 다 해보든지 알아서 하면 된다. 난 귀찮으므로 답을 찾아보겠다...
"Cannabis"라고 한다.
약간 허무한 크랙미를 소개해서 죄송한 마음 금할 수 없으며
다음부터는 미리 한번 크랙해보고 올릴것을 다짐하는 바이다.
이것으로 이번 크랙미 설명을 종료하겠다.
난 답 찾는 것보다 이런 게 좋더라.

Prev
Rss Feed