新手破解练习Crackme160之132 - Pusillus
这个程序也是汇编写的代码量也是很少, 直接看:
00401000 >/$ 6A 00 push 0x0 ; /pModule = NULL
00401002 |. E8 93010000 call <jmp.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401007 |. A3 50304000 mov dword ptr ds:[0x403050],eax
0040100C |. 6A 0A push 0xA
0040100E |. 6A 00 push 0x0
00401010 |. 6A 00 push 0x0
00401012 |. FF35 50304000 push dword ptr ds:[0x403050]
00401018 |. E8 06000000 call Pusillus.00401023
0040101D |. 50 push eax ; /ExitCode = 0x19FFCC
0040101E |. E8 71010000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
00401023 |$ 55 push ebp
00401024 |. 8BEC mov ebp,esp
00401026 |. B8 41104000 mov eax,Pusillus.00401041
0040102B |. 6A 00 push 0x0 ; /lParam = NULL
0040102D |. 50 push eax ; |DlgProc = 0019FFCC
0040102E |. 6A 00 push 0x0 ; |hOwner = NULL
00401030 |. 68 00304000 push Pusillus.00403000 ; |pTemplate = "dialog1"
00401035 |. FF75 08 push [arg.1] ; |hInst = 002D7000
00401038 |. E8 33010000 call <jmp.&USER32.DialogBoxParamA> ; \DialogBoxParamA
0040103D |. C9 leave
0040103E \. C2 1000 retn 0x10
00401041 /. 55 push ebp
00401042 |. 8BEC mov ebp,esp
00401044 |. 8B45 08 mov eax,[arg.1]
00401047 |. A3 54304000 mov dword ptr ds:[0x403054],eax
0040104C |. 8B45 0C mov eax,[arg.2]
0040104F |. 3D 10010000 cmp eax,0x110 ; Switch (cases 10..111)
00401054 |. 75 1A jnz short Pusillus.00401070
00401056 |. 68 B80B0000 push 0xBB8 ; /ControlID = BB8 (3000.); Case 110 (WM_INITDIALOG) of switch 0040104F
0040105B |. FF75 08 push [arg.1] ; |hWnd = 002D7000
0040105E |. E8 19010000 call <jmp.&USER32.GetDlgItem> ; \GetDlgItem
00401063 |. A3 58304000 mov dword ptr ds:[0x403058],eax
00401068 |. 50 push eax ; /hWnd = 0019FFCC
00401069 |. E8 1A010000 call <jmp.&USER32.SetFocus> ; \SetFocus
0040106E |. EB 50 jmp short Pusillus.004010C0
00401070 |> 83F8 10 cmp eax,0x10
00401073 |. 75 0C jnz short Pusillus.00401081
00401075 |. 6A 00 push 0x0 ; /Result = 0x0; Case 10 (WM_CLOSE) of switch 0040104F
00401077 |. FF75 08 push [arg.1] ; |hWnd = 002D7000
0040107A |. E8 F7000000 call <jmp.&USER32.EndDialog> ; \EndDialog
0040107F |. EB 3F jmp short Pusillus.004010C0
00401081 |> 3D 11010000 cmp eax,0x111
00401086 |. 75 2F jnz short Pusillus.004010B7
00401088 |. 8B45 10 mov eax,[arg.3] ; Case 111 (WM_COMMAND) of switch 0040104F
0040108B |. 66:3D B90B cmp ax,0xBB9
0040108F |. 75 2F jnz short Pusillus.004010C0
00401091 |. C1E8 10 shr eax,0x10
00401094 |. 66:0BC0 or ax,ax
00401097 |. 75 1C jnz short Pusillus.004010B5
00401099 |. 6A 0A push 0xA ; /Count = A (10.)
0040109B |. 68 44304000 push Pusillus.00403044 ; |Buffer = Pusillus.00403044
004010A0 |. 68 B80B0000 push 0xBB8 ; |ControlID = BB8 (3000.)
004010A5 |. FF35 54304000 push dword ptr ds:[0x403054] ; |hWnd = NULL
004010AB |. E8 D2000000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA ;;;;;;;;;;;;;;;;;; 获取输入数据
004010B0 |. E8 14000000 call Pusillus.004010C9 ;;;;;;;;;;;;;;;;;; 算法处
004010B5 |> EB 09 jmp short Pusillus.004010C0
004010B7 |> B8 00000000 mov eax,0x0 ; Default case of switch 0040104F
004010BC |. C9 leave
004010BD |. C2 1000 retn 0x10
004010C0 |> B8 01000000 mov eax,0x1
004010C5 |. C9 leave
004010C6 \. C2 1000 retn 0x10
004010C9 /$ 56 push esi ; Pusillus.<ModuleEntryPoint>
004010CA |. 57 push edi ; Pusillus.<ModuleEntryPoint>
004010CB |. 51 push ecx ; Pusillus.<ModuleEntryPoint>
004010CC |. 33F6 xor esi,esi ; Pusillus.<ModuleEntryPoint>
004010CE |. 33FF xor edi,edi ; Pusillus.<ModuleEntryPoint>
004010D0 |. B9 08000000 mov ecx,0x8
004010D5 |. BE 44304000 mov esi,Pusillus.00403044
004010DA |> 8036 32 /xor byte ptr ds:[esi],0x32
004010DD |. 46 |inc esi ; Pusillus.<ModuleEntryPoint>
004010DE |.^ E2 FA \loopd short Pusillus.004010DA
004010E0 |. BE 44304000 mov esi,Pusillus.00403044
004010E5 |. B9 04000000 mov ecx,0x4
004010EA |> 8A06 /mov al,byte ptr ds:[esi]
004010EC |. 8A5E 01 |mov bl,byte ptr ds:[esi+0x1]
004010EF |. 32C3 |xor al,bl
004010F1 |. 8887 4C304000 |mov byte ptr ds:[edi+0x40304C],al
004010F7 |. 83C6 02 |add esi,0x2
004010FA |. 47 |inc edi ; Pusillus.<ModuleEntryPoint>
004010FB |.^ E2 ED \loopd short Pusillus.004010EA
004010FD |. BE 4C304000 mov esi,Pusillus.0040304C
00401102 |. 8A06 mov al,byte ptr ds:[esi]
00401104 |. 8A5E 01 mov bl,byte ptr ds:[esi+0x1]
00401107 |. 32C3 xor al,bl
00401109 |. 8A5E 02 mov bl,byte ptr ds:[esi+0x2]
0040110C |. 8A4E 03 mov cl,byte ptr ds:[esi+0x3]
0040110F |. 32D9 xor bl,cl
00401111 |. 32C3 xor al,bl
00401113 |. B9 08000000 mov ecx,0x8
00401118 |. BE 44304000 mov esi,Pusillus.00403044
0040111D |> 3006 /xor byte ptr ds:[esi],al
0040111F |. 46 |inc esi ; Pusillus.<ModuleEntryPoint>
00401120 |.^ E2 FB \loopd short Pusillus.0040111D
00401122 |. B9 08000000 mov ecx,0x8
00401127 |. BE 44304000 mov esi,Pusillus.00403044
0040112C |. BF 08304000 mov edi,Pusillus.00403008
00401131 |> 8A06 /mov al,byte ptr ds:[esi]
00401133 |. 3A07 |cmp al,byte ptr ds:[edi]
00401135 |. 75 1D |jnz short Pusillus.00401154
00401137 |. 46 |inc esi ; Pusillus.<ModuleEntryPoint>
00401138 |. 47 |inc edi ; Pusillus.<ModuleEntryPoint>
00401139 |.^ E2 F6 \loopd short Pusillus.00401131
0040113B |. 6A 40 push 0x40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040113D |. 68 35304000 push Pusillus.00403035 ; |Title = "Crackme 1.0"
00401142 |. 68 10304000 push Pusillus.00403010 ; |Text = "Good Work Cracker"
00401147 |. FF35 54304000 push dword ptr ds:[0x403054] ; |hOwner = NULL
0040114D |. E8 3C000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401152 |. EB 17 jmp short Pusillus.0040116B
00401154 |> 6A 30 push 0x30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401156 |. 68 35304000 push Pusillus.00403035 ; |Title = "Crackme 1.0"
0040115B |. 68 22304000 push Pusillus.00403022 ; |Text = "Bad Serial, Sorry!"
00401160 |. FF35 54304000 push dword ptr ds:[0x403054] ; |hOwner = NULL
00401166 |. E8 23000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
0040116B |> 5F pop edi ; kernel32.7724FCC9
0040116C |. 5E pop esi ; kernel32.7724FCC9
0040116D |. 59 pop ecx ; kernel32.7724FCC9
0040116E \. C3 retn
0040116F CC int3
00401170 $- FF25 10204000 jmp dword ptr ds:[<&USER32.DialogBoxParamA>] ; user32.DialogBoxParamA
00401176 $- FF25 18204000 jmp dword ptr ds:[<&USER32.EndDialog>] ; user32.EndDialog
0040117C $- FF25 14204000 jmp dword ptr ds:[<&USER32.GetDlgItem>] ; user32.GetDlgItem
00401182 $- FF25 0C204000 jmp dword ptr ds:[<&USER32.GetDlgItemTextA>] ; user32.GetDlgItemTextA
00401188 $- FF25 1C204000 jmp dword ptr ds:[<&USER32.SetFocus>] ; user32.SetFocus
0040118E $- FF25 20204000 jmp dword ptr ds:[<&USER32.MessageBoxA>] ; user32.MessageBoxA
00401194 $- FF25 00204000 jmp dword ptr ds:[<&KERNEL32.ExitProcess>] ; DTFRAME3.580AA800
0040119A $- FF25 04204000 jmp dword ptr ds:[<&KERNEL32.GetModuleHandleA>] ; kernel32.GetModuleHandleA
004011A0 00 db 00
算法分析, 循环8次将输入与0x32异或, 再两两异或得到4位, 再两两异或得2位, 再异或得1位, 再与开始的8位结果异或得到最终结果与正确的71 18 59 1B 79 42 45 4C这8位固定串对比, 所以我们输入也为8位, 与0x32异或后的结果设为12345678(仅为代号不是真实值)
12345678=> 1 ^ 2, 3 ^ 4, 5 ^ 6, 7 ^ 8(4位) => (1 ^ 2) ^ (3 ^ 4), (5 ^ 6) ^ (7 ^ 8)(2位) => ((1 ^ 2) ^ (3 ^ 4)) ^ (5 ^ 6) ^ (7 ^ 8))(1位) = 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8, 那么就有(8个式子)
(1). 1 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8 = 71
(2). 2 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8 = 18
(3). 3 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 2 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8 = 59
(4). 4 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 2 ^ 3 ^ 5 ^ 6 ^ 7 ^ 8 = 1B
(5). 5 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 2 ^ 3 ^ 4 ^ 6 ^ 7 ^ 8 = 79
(6). 6 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 7 ^ 8 = 42
(7). 7 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 8 = 45
(8). 8 ^ (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8) = 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 = 4C
每两个异或一下:
(1) ^ (2) = 1 ^ 2 = 71 ^ 18 = 69
(2) ^ (3) = 2 ^ 3 = 18 ^ 59 = 41
(3) ^ (4) = 3 ^ 4 = 59 ^ 1B = 42
(4) ^ (5) = 4 ^ 5 = 1B ^ 79 = 62
(5) ^ (6) = 5 ^ 6 = 79 ^ 42 = 3B
(6) ^ (7) = 6 ^ 7 = 42 ^ 45 = 7
(7) ^ (8) = 7 ^ 8 = 45 ^ 4C = 9
(1) ^ (8) = 1 ^ 8 = 71 ^ 4C = 3D
从上面的规律看, 我们可以得到
1 = 71
2 = 18
3 = 59
4 = 1B
5 = 79
6 = 42
7 = 45
8 = 4C
分别再^0x32得到输入串为: 43 2A 6B 29 4B 70 77 7E => Ck)Kpw~ 输入验证失败, 竟然是失败的, 哪步分析出问题了? 从规律看确实数字对应的很工整~, 但程序中1 ^ (x)=71, 除非x=0, 才有可能, 问题应该就出现在这里了, 果然没那么简单就解决了 ^ _ ^, 现在是不是只能暴破了呢?
Ck)Kpw~这个值在验证时, 看到最后一步的al是0x19, 前面调试过程中乱输入的值得到的也是19, 是不是19是相对固定的? 我们反过来验证一下,
1 ^ 0x19 ^ 0x32 = 71 => 1 = 5A, 2 ^ 0x19 ^ 0x32 = 18 => 2 = 33, 同理得到 5A 33 72 30 52 69 6E 67 (Z3r0Ring), 这个值验证通过~ , 下面用暴破程序验证一下:
#include <stdio.h>
#include <string.h>
int main() {
int rlt[9] = {0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C,0};
char code[9] = {0};
int s = 0;
for(int i=0x0;i<0xFF;i++){ //al
s = 1;
for(int j=0;j<8;j++){
code[j] = rlt[j] ^ i ^ 0x32;
if((code[j] < 0x20) || (code[j]>0x7E)){ s=0; break; } //只考虑使用可见字符
}
if(s == 1){
s = 0;
for(int j=0; j<8; j++){ s ^= code[j]; }
if(s == i) printf("al=0x%02X, Code: %s\n", i, code);
}
}
printf("End");
getchar();getchar();
return 0;
}
运行结果也只有这一个, 说明确实是al=0x19时才是正确的
al=0x19, Code: Z3r0Ring
后记, 由于xor操作的可逆性, 输入系列号(8位):1, 2, 3, 4, 5, 6, 7, 8 经过计算得到对应的8位结果为:11, 22, 33, 44, 55, 66, 77, 88, 即:
1 ^ 0x32 ^ (1 ^ 0x32 ^ 2 ^ 0x32 ^ 3 ^ 0x32 ^ 4 ^ 0x32 ^ 5 ^ 0x32 ^ 6 ^ 0x32 ^ 7 ^ 0x32 ^ 8 ^ 0x32) = 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8 ^ 0x32 = 11
反过来可得
22 ^ 33 ^ 44 ^ 55 ^ 66 ^ 77 ^ 88 ^ 0x32 = 1
由于11~88都已知(0x71, 0x18, ..., 0x4C), 代入可得1 = 5A, 同理可得1~8为: 5A 33 72 30 52 69 6E 67 (Z3r0Ring)
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号