14. 크랙미 다섯 번째
본문 바로가기
Reversing & Cheat Engine

14. 크랙미 다섯 번째

by boosting 2024. 2. 27.
728x90

어느 정도 익숙해진 크랙미

 
몇 가지 문제를 보시면서 어느 정도는 감을 잡으셨을 거 같습니다.
크랙미 대부분의 문제가 이러한 형태로 진행이 되거든요. 어려운 거라 하더라도
기본적인 틀을 벗어나지 않는다는 점은 똑같습니다.
 

이번 건 뭔데

 
이번 거도 파도콘 출처라고는 하는데 정확하지는 않습니다.
저도 파일을 구글링이나 네이버 출처로 얻어와서 직접 분석해 보고 글을 올리는 거라
오래된 파일들은 출처가 좀 미비한 경우도 있습니다.
 

크랙미

 
아무런 단어랑 숫자를 넣고 확인을 눌렀더니 틀렸다고 하네요.
확인을 누르면 프로그램이 꺼집니다.
프로그램을 꺼지게 만드는 함수를 생각해 봅시다.
간단하게 생각해 볼 건 ExitProcess와 TerminateProcess 정도가 있겠습니다.
한 번 두 곳에다가 디버깅을 걸어봅시다.
 

크랙미

 
걸린 거 확인했고 +1700 쪽을 한 번 봅시다.
 

162C7B044B68C15349.exe+16B1 - 55                    - push ebp
162C7B044B68C15349.exe+16B2 - 8B EC                 - mov ebp,esp
162C7B044B68C15349.exe+16B4 - 8B 45 08              - mov eax,[ebp+08]
162C7B044B68C15349.exe+16B7 - 05 CDAB0000           - add eax,0000ABCD { 43981 }
162C7B044B68C15349.exe+16BC - 89 45 08              - mov [ebp+08],eax
162C7B044B68C15349.exe+16BF - 8B 4D 08              - mov ecx,[ebp+08]
162C7B044B68C15349.exe+16C2 - 81 E9 45230100        - sub ecx,00012345 { (0) }
162C7B044B68C15349.exe+16C8 - 89 4D 08              - mov [ebp+08],ecx
162C7B044B68C15349.exe+16CB - C7 45 08 56341200     - mov [ebp+08],00123456 { 1193046 }
162C7B044B68C15349.exe+16D2 - 8B 55 08              - mov edx,[ebp+08]
162C7B044B68C15349.exe+16D5 - 52                    - push edx
162C7B044B68C15349.exe+16D6 - E8 4D000000           - call 162C7B044B68C15349.exe+1728
162C7B044B68C15349.exe+16DB - 83 C4 04              - add esp,04 { 4 }
162C7B044B68C15349.exe+16DE - 89 45 08              - mov [ebp+08],eax
162C7B044B68C15349.exe+16E1 - 81 7D 08 23816705     - cmp [ebp+08],05678123 { 90669347 }
162C7B044B68C15349.exe+16E8 - 75 0E                 - jne 162C7B044B68C15349.exe+16F8
162C7B044B68C15349.exe+16EA - 6A 00                 - push 00 { 0 }
162C7B044B68C15349.exe+16EC - 6A 00                 - push 00 { 0 }
162C7B044B68C15349.exe+16EE - 68 38404000           - push 162C7B044B68C15349.exe+4038 { (" Sorry You are wrong ") } < 실패했을 때 뜨던 문구
162C7B044B68C15349.exe+16F3 - E8 A8060000           - call 162C7B044B68C15349.exe+1DA0 { ->->MFC42.Ordinal1200 }
162C7B044B68C15349.exe+16F8 - 6A 00                 - push 00 { 0 }
162C7B044B68C15349.exe+16FA - FF 15 B4314000        - call dword ptr [162C7B044B68C15349.exe+31B4] { ->MSVCRT.exit } < 종료 함수 호출
162C7B044B68C15349.exe+1700 - 5D                    - pop ebp
162C7B044B68C15349.exe+1701 - C3                    - ret 

 
일단 여기가 메시지박스를 띄우는 곳이네요.
그러면 그 밑 Return Address 인 +1682 쪽을 보도록 합시다.
 

크랙미

 
일단 조건이 2가지가 있네요.
eax와 [edx+60]을 비교했을 때 다르다면 프로그램을 끄라는 함수로 이동하고 있고
[ebp-98]과 01을 비교했을 때 같다면 프로그램을 끄라는 함수로 이동하고 있습니다.
그러면 우선 프로그램을 다시 켜서 이 부분을 점프해서 프로그램 꺼지는 걸 막아둡시다.
 

크랙미

 
음.. 끄는 부분 조건만 막으려 했는데
시리얼 번호가 맞다 하고 끝나버렸네요.
우선 그러면 cmp eax, [edx+60]부터 비교를 해봐야 할 듯합니다.
 

크랙미

 
[edx+60]은 보시면 4D2가 들어가 있는데 4D2를 10진수로 변환하면 1234
즉 제가 써둔 시리얼 번호를 담아 옵니다.
그러면 이 eax가 뭔지를 알아야 비교를 하든가 하겠네요.
명령어 어셈을 보시면 [ebp-04]에서 eax로 옮겨오고 있습니다.
그러면 이 [ebp-04]에 저 1D6DB5A3이라는 값을 옮겨다 주는 곳이 있을 거예요.
조금만 위로 올려보면 바로 있습니다.
 

162C7B044B68C15349.exe+1623 - 8B 45 F8              - mov eax,[ebp-08]
162C7B044B68C15349.exe+1626 - 99                    - cdq 
162C7B044B68C15349.exe+1627 - B9 00CA9A3B           - mov ecx,3B9ACA00 { 0.00 }
162C7B044B68C15349.exe+162C - F7 F9                 - idiv ecx
162C7B044B68C15349.exe+162E - 89 55 FC              - mov [ebp-04],edx
162C7B044B68C15349.exe+1631 - 6A 01                 - push 01 { 1 }
162C7B044B68C15349.exe+1633 - 8B 8D 44FFFFFF        - mov ecx,[ebp-000000BC]

 
이 부분에서 edx에 담기는 게 [ebp-04]로 옮겨주네요.
그러면 어떤 계산으로 edx가 나오는지를 알아내면 되겠죠.
idiv 같은 경우 저번 글에서 설명을 한 적 있습니다.
idiv ecx => eax를 ecx로 나눈 후 몫은 eax에는 몫, edx에는 나머지를 저장한다 했죠.
 
본 적 없으시다면 밑의 글을 간단하게 참고해 주시면 되겠습니다.
 

6. 어셈 명령어

1. 명령어의 구성 이전 글을 쭉 봐오셨다면 add와 sub, mov 등의 명령어들을 보셨을 겁니다. 못 보셨다면 이 글을 한 번 쭉 읽어보시면 명령어들을 간략하게나마 볼 수 있을 것입니다. 4. 치엔 튜토리

poppintip.co.kr

 

크랙미

 
eax가 59087FA3이고 ecx가 3B9ACA00 입니다.
나누기를 하게 되면 몫은 1이 될 거고 나머지는 그냥 59087FA3-3B9ACA00을 진행하면
아까 [ebp-04]에서 봤던 1D6DB5A3가 나머지가 됩니다.
즉 1D6DB5A3가 edx에 담기는 게 맞죠.
 
그러면 아까 위로 다시 돌아가서
cmp eax, [edx+60] // edx+60은 내가 썼던 숫자, eax는 나눗셈 이후 나머지 값
이거 2개가 똑같아야 조건이 성립한다는 얘기겠죠.
 
일단 어느 정도는 파악했지만 결국 59087FA3 이게 어떻게 만들어지는 건지
과정을 모르면 답이 없으므로 계속 역분석을 진행해야겠죠..
나누기하는 eax는 [ebp-08]에서 가져오고 있습니다.
 

크랙미

 
call MSVCRT.labs 이 함수를 통과한 이후 eax에 리턴값이 담길 텐데 이걸 옮겨주는 모습입니다.
 

162C7B044B68C15349.exe+1547 - 8B 8D 78FFFFFF        - mov ecx,[ebp-00000088]
162C7B044B68C15349.exe+154D - 3B 8D 7CFFFFFF        - cmp ecx,[ebp-00000084]
162C7B044B68C15349.exe+15AF - 73 56                 - jae 162C7B044B68C15349.exe+1607 < 조건
162C7B044B68C15349.exe+15B1 - 8B 85 78FFFFFF        - mov eax,[ebp-00000088]
162C7B044B68C15349.exe+15B7 - 8B 4C 85 80           - mov ecx,[ebp+eax*4--80]
162C7B044B68C15349.exe+15BB - 0FBE 94 0D 48FFFFFF   - movsx edx,byte ptr [ebp+ecx-000000B8]
162C7B044B68C15349.exe+15C3 - 8B 85 78FFFFFF        - mov eax,[ebp-00000088]
162C7B044B68C15349.exe+15C9 - BE 01000000           - mov esi,00000001 { 1 }
162C7B044B68C15349.exe+15CE - 8B 4C 85 80           - mov ecx,[ebp+eax*4--80]
162C7B044B68C15349.exe+15D2 - D3 E6                 - shl esi,cl
162C7B044B68C15349.exe+15D4 - 0FAF D6               - imul edx,esi
162C7B044B68C15349.exe+15D7 - 8B 8D 78FFFFFF        - mov ecx,[ebp-00000088]
162C7B044B68C15349.exe+15DD - 83 C1 01              - add ecx,01 { 1 }
162C7B044B68C15349.exe+15E0 - 0FAF D1               - imul edx,ecx
162C7B044B68C15349.exe+15E3 - 69 D2 2D224900        - imul edx,edx,0049222D { 4792877 }
162C7B044B68C15349.exe+15E9 - 8B 85 78FFFFFF        - mov eax,[ebp-00000088]
162C7B044B68C15349.exe+15EF - 8B 4C 85 80           - mov ecx,[ebp+eax*4--80]
162C7B044B68C15349.exe+15F3 - 0FBE 84 0D 48FFFFFF   - movsx eax,byte ptr [ebp+ecx-000000B8]
162C7B044B68C15349.exe+15FB - 0B D0                 - or edx,eax
162C7B044B68C15349.exe+15FD - 8B 4D F8              - mov ecx,[ebp-08]
162C7B044B68C15349.exe+1600 - 03 CA                 - add ecx,edx
162C7B044B68C15349.exe+1602 - 89 4D F8              - mov [ebp-08],ecx
162C7B044B68C15349.exe+1605 - EB 8D                 - jmp 162C7B044B68C15349.exe+1594
162C7B044B68C15349.exe+1607 - 8B 55 F8              - mov edx,[ebp-08]
162C7B044B68C15349.exe+160A - 52                    - push edx
162C7B044B68C15349.exe+160B - E8 00080000           - call 162C7B044B68C15349.exe+1E10 { ->->MSVCRT.labs }

 
살짝 위를 더 복사해 보면 이런 모습인데 for문이 있는 거 봐선 또 문자 암호화 때리는 거 같네요.
우선 암호화를 풀기 이전에 어떤 조건이 되어야 이 for문을 빠져나가는지를 알아야겠죠.
ecx와 [ebp-84]를 비교해서 Above or Equal, 같거나 크면 점프로 돼있습니다.
현재 [ebp-84]에 4가 담겨있는 걸로 봐선 Name 수를 체크하는 걸로 보입니다.
 
이와 비슷하게 생긴 명령어 집합이 2개가 있는데, 1개는 Name을 검사하는 거 같고
1개는 Serial을 검사하는 걸로 추측이 됩니다.
 
그러면 닉네임 읽는 부분부터 정리를 해보겠습니다.
 

mov edx,[ebp-00000088]
movsx eax,byte ptr [ebp+edx-000000B8]
imul eax,eax,0049222D
add eax,[ebp-00000088]
and eax,0000FFFF
xor edx,edx
div [ebp-00000084]
mov eax,[ebp-00000088]
mov [ebp+eax*4--80],edx
 

계산 과정

 
이 부분이 닉네임 쪽 연산입니다. 대충 써보자면 // 이곳은 문자가 qwer로 4개이기에 4번 돔
[ebp-88] // 글자 순서, 1번째는 0이 들어가고 순차적으로 1 증가 qwer 이므로 0~3
[ebp+edx-b8] // 쓴 문자가 들어감, 1번째는 Q가 들어가고 마지막으로는 R, 대문자로 표기
 

크랙미

 
Q=51인걸 잡고 계산
51x49222D=>1723D03D
1723D03D+0 => Q에 해당하는 글자이므로 순서가 1번째고 0
1723D03D and FFFF => 계산하면 앞의 1723을 갖다 버림, D03D만 남음
D03D를 [ebp-84] 수치만큼으로 나눔 => [ebp-84]는 글자수인 4로 추정 / 나누면 몫은 340F , 나머지는 1
나머지가 1이므로 [ebp+eax*4--80] 에다가 1을 집어넣음 // 여기서 eax는 0
 
W=57인걸 잡고 계산
57x49222D => 18DA9D4B
18DA9D4B+1 => W에 해당하는 글자이므로 순서가 2번째고 1
18DA9D4C and FFFF => 9D4C
9D4C 나누기 4 => 나누면 몫은 2753 , 나머지는 0
나머지가 0이므로 [ebp+eax*4--80] 에다가 0을 집어넣음 // 여기서 eax는 1
 
E=45인걸 잡고 계산
45x49222D => 13B63621
13B636231+2 => 순서가 3번째고 2
13B63623 and FFFF => 3623
3623 나누기 4 => 나누면 몫은 D88, 나머지는 3
나머지가 3이므로 [ebp+eax*4--80] 에다가 3을 집어넣음 // 여기서 eax는 2 
 
R=52인걸 잡고 계산
52x49222D => 176CF26A
176CF26A+3 => 순서가 4번째고 3
176CF26D and FFFF => F26D
F26D 나누기 4 => 나누면 몫은 3C9B 나머지는 1
나머지가 1이므로 [ebp+eax*4--80] 에다가 1을 집어넣음 // 여기서 eax는 3
 
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
 
조금 쉽게 설명을 하자면 0~4번째 문자를 1개씩 가져와서
그것과 49222D를 곱한 수치에 몇 번째에 해당하는지 확인 후 그 번째를 더하고
FFFF와 and 연산을 한 후 나온 값을 문자열 개수로 나눕니다.
이를 4바이트씩 끊어서 차례대로 넣어주는 식입니다.
 
다음 시리얼 번호 쪽의 연산은 이렇습니다.
2^(두 번째 나머지) x (문자열 첫 번째 나머지) x 1번째 수 x 49222D 한 결괏값을
(문자열의 첫 번째 나머지)와 or 연산 후 나온 값을 A라 하면
이 A를 [ebp-8]에 넣음
 
2^(두 번째 나머지) x (문자열 두 번째 나머지) x 2번째 수 x 49222D 한 결괏값을
(문자열 두 번째 나머지)와 or 연산 후 나온 값을 B라 하면
이 B를 아까 A+B 한 후 [ebp-8]에 넣음
 
아 이게 쓰다 보니까 너무 길어져서 일단 정리만 써놨습니다.
결국 문자를 저런 계산식에 넣어서 나온 나머지값 = 시리얼넘버
이 조건이 해당하면 통과가 되는 거라 볼 수 있겠죠.
 

162C7B044B68C15349.exe+1627 - B9 00CA9A3B           - mov ecx,3B9ACA00 { 0.00 }
162C7B044B68C15349.exe+162C - F7 F9                 - idiv ecx
162C7B044B68C15349.exe+162E - 89 55 FC              - mov [ebp-04],edx
162C7B044B68C15349.exe+1631 - 6A 01                 - push 01 { 1 }
162C7B044B68C15349.exe+1633 - 8B 8D 44FFFFFF        - mov ecx,[ebp-000000BC]

 
결국 마지막 조건은 여기에요.
저 조건에 맞게 계산한 게 3B9ACA00 + 내가 입력한 숫자가 되면
3B9ACA00으로 나눠도 딱 나머지가 내가 입력한 수가 되겠죠.
 
이게 정확하게 키젠을 만들라는 조건인 건지는 모르겠어서 수식만 계산해보고
넘겼습니다. 키젠 만드는 게 은근 노가다의 영역이라 하기 싫음도 한몫...
이제 슬 크랙미만 하기 질리는 느낌도 있어서 다른 거 할만한 게 있는지
생각 좀 해봐야 할 듯합니다.

728x90