环境
Windows xp sp3
工具
upx
exeinfope
ollydbg
查壳
发现是upx壳,手脱的话会不干净,影响OD分析。
所以就直接用 upx -d 脱了
手脱:
upx -d:
用upx -d 脱的版本进行分析。
第一次运行时显示这个:
缺少Reg.dat,所以无法打开。那就新建一个Reg.dat。
找到注册窗口:
估计是要serial正确的时候OK按钮才能点击。
OD载入:
直接搜字符串看看有没有什么有价值的
00437B33 00 db 00
00437B34 FC7D4300 dd crackme_.00437DFC
00437B38 . 0C db 0C
00437B39 . 42 75 74 74 6>ascii "Button2Click"
00437B45 12 db 12
00437B46 00 db 00
00437B47 707E4300 dd crackme_.00437E70 ; 这里是处理Edit1Change事件的函数,下面的也是同一个道理
00437B4B . 0B db 0B
00437B4C . 45 64 69 74 3>ascii "Edit1Change"
00437B57 12 db 12
00437B58 00 db 00
00437B59 7C7E4300 dd crackme_.00437E7C
00437B5D . 0B db 0B
00437B5E . 45 64 69 74 3>ascii "Edit2Change"
00437B69 12 db 12
00437B6A 00 db 00
00437B6B 887E4300 dd crackme_.00437E88
00437B6F . 0B db 0B
00437B70 . 45 64 69 74 3>ascii "Edit3Change"
00437B7B 12 db 12
00437B7C 00 db 00
00437B7D 947E4300 dd crackme_.00437E94
00437B81 . 0B db 0B
00437B82 . 45 64 69 74 3>ascii "Edit4Change"
00437B8D 13 db 13
00437B8E 00 db 00
00437B8F A07E4300 dd crackme_.00437EA0
00437B93 . 0C db 0C
00437B94 . 42 75 74 74 6>ascii "Button1Click"
00437BA0 . 06 db 06
00437BA1 . 54 46 6F 72 6>ascii "TForm2"
至于为什么会找到这里,可以查看Button1Click的函数。
00437E70 . B8 01000000 mov eax,0x1 ; 这里是Edit1Change的函数
00437E75 . E8 A2FEFFFF call crackme_.00437D1C
00437E7A . C3 retn
00437E7B 90 nop
00437E7C . B8 02000000 mov eax,0x2
00437E81 . E8 96FEFFFF call crackme_.00437D1C
00437E86 . C3 retn
00437E87 90 nop
00437E88 . B8 03000000 mov eax,0x3
00437E8D . E8 8AFEFFFF call crackme_.00437D1C
00437E92 . C3 retn
00437E93 90 nop
00437E94 . B8 04000000 mov eax,0x4
00437E99 . E8 7EFEFFFF call crackme_.00437D1C
00437E9E . C3 retn
00437E9F 90 nop ; 下面开始是Button1Click的函数
00437EA0 . 6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
00437EA2 . 68 B47E4300 push crackme_.00437EB4 ; |Title = "Success!"
00437EA7 . 68 C07E4300 push crackme_.00437EC0 ; |Text = "Hey, Man, you did it!
You cracked my little proggie.
AAAAH! :("
00437EAC . 6A 00 push 0x0 ; |hOwner = NULL
00437EAE . E8 31DBFCFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00437EB3 . C3 retn
在[00437E70][00437E7C][00437E88][00437E94]都下个断点,改变serial的时候发现断了下来
在下面的call跟进去
00437D1C /$ 55 push ebp
00437D1D |. 8BEC mov ebp,esp
00437D1F |. 6A 00 push 0x0
00437D21 |. 53 push ebx
00437D22 |. 8BD8 mov ebx,eax
00437D24 |. 33C0 xor eax,eax
00437D26 |. 55 push ebp
00437D27 |. 68 EE7D4300 push crackme_.00437DEE
00437D2C |. 64:FF30 push dword ptr fs:[eax]
00437D2F |. 64:8920 mov dword ptr fs:[eax],esp
00437D32 |. 8BC3 mov eax,ebx
00437D34 |. 48 dec eax ; Switch (cases 1..4)
00437D35 |. 74 0E je Xcrackme_.00437D45
00437D37 |. 48 dec eax
00437D38 |. 74 2F je Xcrackme_.00437D69
00437D3A |. 48 dec eax
00437D3B |. 74 50 je Xcrackme_.00437D8D
00437D3D |. 48 dec eax
00437D3E |. 74 71 je Xcrackme_.00437DB1
00437D40 |. E9 8E000000 jmp crackme_.00437DD3
00437D45 |> 8D55 FC lea edx,[local.1] ; Case 1 of switch 00437D34
00437D48 |. A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437D4D |. 8B80 E8010000 mov eax,dword ptr ds:[eax+0x1E8]
00437D53 |. E8 6854FEFF call crackme_.0041D1C0
00437D58 |. 8B45 FC mov eax,[local.1]
00437D5B |. E8 D0EBFCFF call crackme_.00406930
00437D60 |. 89049D 38A743>mov dword ptr ds:[ebx*4+0x43A738],eax
00437D67 |. EB 6A jmp Xcrackme_.00437DD3
00437D69 |> 8D55 FC lea edx,[local.1] ; Case 2 of switch 00437D34
00437D6C |. A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437D71 |. 8B80 EC010000 mov eax,dword ptr ds:[eax+0x1EC]
00437D77 |. E8 4454FEFF call crackme_.0041D1C0
00437D7C |. 8B45 FC mov eax,[local.1]
00437D7F |. E8 ACEBFCFF call crackme_.00406930
00437D84 |. 89049D 38A743>mov dword ptr ds:[ebx*4+0x43A738],eax
00437D8B |. EB 46 jmp Xcrackme_.00437DD3
00437D8D |> 8D55 FC lea edx,[local.1] ; Case 3 of switch 00437D34
00437D90 |. A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437D95 |. 8B80 F0010000 mov eax,dword ptr ds:[eax+0x1F0]
00437D9B |. E8 2054FEFF call crackme_.0041D1C0
00437DA0 |. 8B45 FC mov eax,[local.1]
00437DA3 |. E8 88EBFCFF call crackme_.00406930
00437DA8 |. 89049D 38A743>mov dword ptr ds:[ebx*4+0x43A738],eax
00437DAF |. EB 22 jmp Xcrackme_.00437DD3
00437DB1 |> 8D55 FC lea edx,[local.1] ; Case 4 of switch 00437D34
00437DB4 |. A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437DB9 |. 8B80 F4010000 mov eax,dword ptr ds:[eax+0x1F4]
00437DBF |. E8 FC53FEFF call crackme_.0041D1C0
00437DC4 |. 8B45 FC mov eax,[local.1]
00437DC7 |. E8 64EBFCFF call crackme_.00406930
00437DCC |. 89049D 38A743>mov dword ptr ds:[ebx*4+0x43A738],eax
00437DD3 |> E8 00FEFFFF call crackme_.00437BD8 ; Default case of switch 00437D34
00437DD8 |. 33C0 xor eax,eax
00437DDA |. 5A pop edx
00437DDB |. 59 pop ecx
00437DDC |. 59 pop ecx
00437DDD |. 64:8910 mov dword ptr fs:[eax],edx
00437DE0 |. 68 F57D4300 push crackme_.00437DF5
00437DE5 |> 8D45 FC lea eax,[local.1]
00437DE8 |. E8 0FB9FCFF call crackme_.004036FC
00437DED \. C3 retn
在[00437DD3]位置的call再跟进去,发现是这里比较。
00437BD8 /$ 55 push ebp
00437BD9 |. 8BEC mov ebp,esp
00437BDB |. 6A 00 push 0x0
00437BDD |. 6A 00 push 0x0
00437BDF |. 53 push ebx
00437BE0 |. 56 push esi
00437BE1 |. 33C0 xor eax,eax
00437BE3 |. 55 push ebp
00437BE4 |. 68 0C7D4300 push crackme_.00437D0C
00437BE9 |. 64:FF30 push dword ptr fs:[eax]
00437BEC |. 64:8920 mov dword ptr fs:[eax],esp
00437BEF |. 8D55 FC lea edx,[local.1]
00437BF2 |. A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437BF7 |. 8B80 0C020000 mov eax,dword ptr ds:[eax+0x20C]
00437BFD |. E8 BE55FEFF call crackme_.0041D1C0
00437C02 |. 8B45 FC mov eax,[local.1]
00437C05 |. E8 6EBDFCFF call crackme_.00403978
00437C0A |. 83F8 05 cmp eax,0x5 ; 这里是比较输入的name的长度
00437C0D |. 0F8C AF000000 jl crackme_.00437CC2
00437C13 |. 8B45 FC mov eax,[local.1] ; 下面是取name特定位置上的字符进行运算
00437C16 |. 0FB600 movzx eax,byte ptr ds:[eax]
00437C19 |. B9 0A000000 mov ecx,0xA
00437C1E |. 99 cdq
00437C1F |. F7F9 idiv ecx ; 第一个字符 / 0xA
00437C21 |. A3 2CA74300 mov dword ptr ds:[0x43A72C],eax
00437C26 |. 8B45 FC mov eax,[local.1]
00437C29 |. 0FB640 02 movzx eax,byte ptr ds:[eax+0x2]
00437C2D |. B9 0A000000 mov ecx,0xA
00437C32 |. 99 cdq
00437C33 |. F7F9 idiv ecx ; 第三个字符 / 0xA
00437C35 |. A3 30A74300 mov dword ptr ds:[0x43A730],eax
00437C3A |. 8B45 FC mov eax,[local.1]
00437C3D |. 0FB640 03 movzx eax,byte ptr ds:[eax+0x3]
00437C41 |. B9 0A000000 mov ecx,0xA
00437C46 |. 99 cdq
00437C47 |. F7F9 idiv ecx ; 第四个字符 / 0xA
00437C49 |. A3 34A74300 mov dword ptr ds:[0x43A734],eax
00437C4E |. 8B45 FC mov eax,[local.1]
00437C51 |. 0FB640 04 movzx eax,byte ptr ds:[eax+0x4]
00437C55 |. B9 0A000000 mov ecx,0xA
00437C5A |. 99 cdq
00437C5B |. F7F9 idiv ecx ; 第五个字符 / 0xA
00437C5D |. A3 38A74300 mov dword ptr ds:[0x43A738],eax
00437C62 |. BE 01000000 mov esi,0x1
00437C67 |. BB 2CA74300 mov ebx,crackme_.0043A72C
00437C6C |> 8D55 F8 /lea edx,[local.2] ; 这里是将上面的商的结果取出来,如果大于等于10的都要再除0xA
00437C6F |. 8B03 |mov eax,dword ptr ds:[ebx]
00437C71 |. E8 8AECFCFF |call crackme_.00406900
00437C76 |. 8B45 F8 |mov eax,[local.2]
00437C79 |. E8 FABCFCFF |call crackme_.00403978
00437C7E |. 48 |dec eax
00437C7F |. 74 0C |je Xcrackme_.00437C8D
00437C81 |. 8B03 |mov eax,dword ptr ds:[ebx]
00437C83 |. B9 0A000000 |mov ecx,0xA
00437C88 |. 99 |cdq
00437C89 |. F7F9 |idiv ecx
00437C8B |. 8903 |mov dword ptr ds:[ebx],eax
00437C8D |> 46 |inc esi
00437C8E |. 83C3 04 |add ebx,0x4
00437C91 |. 83FE 05 |cmp esi,0x5
00437C94 |.^ 75 D6 \jnz Xcrackme_.00437C6C
00437C96 |. BE 01000000 mov esi,0x1
00437C9B |. B8 2CA74300 mov eax,crackme_.0043A72C
00437CA0 |. BA 3CA74300 mov edx,crackme_.0043A73C
00437CA5 |> 8B0A /mov ecx,dword ptr ds:[edx] ; 这里是将输入的serial与上面的计算结果比较
00437CA7 |. 3B08 |cmp ecx,dword ptr ds:[eax]
00437CA9 |. 74 07 |je Xcrackme_.00437CB2 ; 如果比较结果不同,就会跳出循环
00437CAB |. B9 01000000 |mov ecx,0x1
00437CB0 |. EB 15 |jmp Xcrackme_.00437CC7
00437CB2 |> 33C9 |xor ecx,ecx
00437CB4 |. 46 |inc esi
00437CB5 |. 83C2 04 |add edx,0x4
00437CB8 |. 83C0 04 |add eax,0x4
00437CBB |. 83FE 05 |cmp esi,0x5
00437CBE |.^ 75 E5 \jnz Xcrackme_.00437CA5
00437CC0 |. EB 05 jmp Xcrackme_.00437CC7 ; 如果比较内容完全一样,就会来到这里
00437CC2 |> B9 01000000 mov ecx,0x1
00437CC7 |> 85C9 test ecx,ecx
00437CC9 |. 75 14 jnz Xcrackme_.00437CDF
00437CCB |. A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437CD0 |. 8B80 E0010000 mov eax,dword ptr ds:[eax+0x1E0]
00437CD6 |. B2 01 mov dl,0x1
00437CD8 |. E8 7B54FEFF call crackme_.0041D158 ; 猜测这个是用来使得OK按钮Enable的,前提是调用前dl为1
00437CDD |. EB 12 jmp Xcrackme_.00437CF1 ; 否则还是disable
00437CDF |> A1 28A74300 mov eax,dword ptr ds:[0x43A728]
00437CE4 |. 8B80 E0010000 mov eax,dword ptr ds:[eax+0x1E0]
00437CEA |. 33D2 xor edx,edx
00437CEC |. E8 6754FEFF call crackme_.0041D158
00437CF1 |> 33C0 xor eax,eax
00437CF3 |. 5A pop edx
00437CF4 |. 59 pop ecx
00437CF5 |. 59 pop ecx
00437CF6 |. 64:8910 mov dword ptr fs:[eax],edx
00437CF9 |. 68 137D4300 push crackme_.00437D13
00437CFE |> 8D45 F8 lea eax,[local.2]
00437D01 |. BA 02000000 mov edx,0x2
00437D06 |. E8 15BAFCFF call crackme_.00403720
00437D0B \. C3 retn
通过上面的分析,可以简单了解到,程序只是简单的将输入的name的第1、3、4、5 共4个位置上的ascii的值的第一位取出来(10进制上的),即最大的位上的值。所以12345的对应的ascii的值为
name:12345
ascii:49 50 51 52 53
serial:4 5 5 5 5