环境
Windows xp sp3
工具
1.exeinfo PE
2.ollydbg
查壳
OD加载就知道有壳了,可以esp定律直接脱掉
exeinfoPE查壳:
测试
点击LOCKED图片会弹出消息框,Register注册按钮无法点击!
猜测Register按钮会在输入正确的name和key变成可以注册。
OD载入,传统的字符串查找。
能找到”check”
00401372 $ BF 00204000 mov edi,123.00402000
00401377 . BE 00104000 mov esi,123.<ModuleEntryPoint>
0040137C . B9 20030000 mov ecx,0x320
00401381 . 33DB xor ebx,ebx
00401383 > 33C0 xor eax,eax
00401385 . 8A040F mov al,byte ptr ds:[edi+ecx]
00401388 . 03D8 add ebx,eax
0040138A . D1CB ror ebx,1
0040138C . 33D9 xor ebx,ecx
0040138E . 49 dec ecx
0040138F .^ 75 F2 jnz X123.00401383
00401391 . B9 B2030000 mov ecx,0x3B2 ; 这里是将401000到4013B2范围内的值加起来
00401396 . 33D2 xor edx,edx
00401398 > 33C0 xor eax,eax
0040139A . 8A040E mov al,byte ptr ds:[esi+ecx]
0040139D . 03D0 add edx,eax
0040139F . D1CA ror edx,1
004013A1 . 33D1 xor edx,ecx
004013A3 . 49 dec ecx
004013A4 .^ 75 F2 jnz X123.00401398
004013A6 . 33DA xor ebx,edx
004013A8 . C1C3 03 rol ebx,0x3
004013AB . 03D3 add edx,ebx
004013AD . 81E2 55555555 and edx,0x55555555
004013B3 . 90 nop
004013B4 . 81F2 45541411 xor edx,0x11145445 ; 如果没有改变就正常显示
004013BA . 74 08 je X123.004013C4 ; 如果发生改变就将edx置1
004013BC . 33D2 xor edx,edx
004013BE . 42 inc edx
004013BF .- E9 580C0000 jmp 123.0040201C
004013C4 >- E9 370C0000 jmp 123.004020000040201C 8915 13234000 mov dword ptr ds:[0x402313],edx ; 这里将edx存起来,影响后面的"Cracked"004012A9 |> \A1 13234000 mov eax,dword ptr ds:[0x402313] ; 如果Eax为0就显示"Lock"
004012AE |. 85C0 test eax,eax ; 如果为1就显示"Cracked"
004012B0 |. 74 08 je X123.004012BA
004012B2 |. 48 dec eax
004012B3 |. 74 05 je X123.004012BA
004012B5 |. E8 29000000 call 123.004012E3
004012BA |> BF 99224000 mov edi,123.00402299
004012BF |. A1 13234000 mov eax,dword ptr ds:[0x402313]
004012C4 |. 03C0 add eax,eax
004012C6 |. 03C0 add eax,eax
004012C8 |. 03F8 add edi,eax
004012CA |. 8B07 mov eax,dword ptr ds:[edi]
004012CC |. 6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
004012CE |. 68 8B224000 push 123.0040228B ; |Title = "-=[ CHECK ]=-"
004012D3 |. 50 push eax ; |Text
004012D4 |. FF75 08 push [arg.1] ; |hOwner
004012D7 |. E8 3B010000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004012DC |. 5E pop esi
004012DD |. 5F pop edi
004012DE |. 5B pop ebx
004012DF |. C9 leave
004012E0 \. C2 1000 retn 0x10
上面是每段代码的执行顺序,具体是通过判断401000到4013B2范围内的值有无发生改变,有的话就会使得程序加载的图片不同,随便找个不影响的地方改。
00401035 20 db 20 ; CHAR ' '
改为:
00401035 21 db 21 ; CHAR '!'
就可以了:
接下来是Register按钮。
对GetDigItemTextA下断点可以来到这里:
00401147 |> \6A 22 push 0x22 ; /Count = 22 (34.)
00401149 |. 68 21234000 push Cracked.00402321 ; |Buffer = Cracked.00402321
0040114E |. 68 EC030000 push 0x3EC ; |ControlID = 3EC (1004.)
00401153 |. FF35 91234000 push dword ptr ds:[0x402391] ; |hWnd = NULL
00401159 |. E8 A1020000 call <jmp.&user32.GetDlgItemTextA> ; \GetDlgItemTextA
0040115E |. A3 8D234000 mov dword ptr ds:[0x40238D],eax
00401163 |. E8 8B010000 call Cracked.004012F3 ; 算法地方,当返回值为1时使得按钮可用
00401168 |. 50 push eax ; /Enable
00401169 |. FF35 85234000 push dword ptr ds:[0x402385] ; |hWnd = NULL
0040116F |. E8 79020000 call <jmp.&user32.EnableWindow> ; \EnableWindow
跟进去:
004012F4 |. 8B0D 89234000 mov ecx,dword ptr ds:[0x402389] ; name的长度
004012FA |. 85C9 test ecx,ecx ; 为空就返回0
004012FC |. 74 71 je XCracked.0040136F
004012FE |. 49 dec ecx
004012FF |. 8BF1 mov esi,ecx
00401301 |. BF 53234000 mov edi,Cracked.00402353 ; ASCII " "
00401306 |. BB 4E4D4144 mov ebx,0x44414D4E
0040130B |. 33D2 xor edx,edx
0040130D |. 8BCA mov ecx,edx
0040130F |> 33C0 /xor eax,eax
00401311 |. 8A040F |mov al,byte ptr ds:[edi+ecx]
00401314 |. 03D0 |add edx,eax
00401316 |. D1CB |ror ebx,1
00401318 |. D3CB |ror ebx,cl
0040131A |. 33DA |xor ebx,edx
0040131C |. 3BCE |cmp ecx,esi
0040131E |. 74 03 |je XCracked.00401323
00401320 |. 41 |inc ecx
00401321 |.^ EB EC \jmp XCracked.0040130F
00401323 |> 81CB 10101010 or ebx,0x10101010
00401329 |. 87DA xchg edx,ebx
0040132B |. BF 21234000 mov edi,Cracked.00402321 ; ASCII " "
00401330 |. 8B0D 8D234000 mov ecx,dword ptr ds:[0x40238D]
00401336 |. 83F9 08 cmp ecx,0x8 ; key要8位
00401339 |. 75 34 jnz XCracked.0040136F
0040133B |. 33C9 xor ecx,ecx
0040133D |> 33C0 /xor eax,eax
0040133F |. C1C2 08 |rol edx,0x8
00401342 |. 8AC2 |mov al,dl
00401344 |. 8AD8 |mov bl,al
00401346 |. 24 0F |and al,0xF
00401348 |. C0EB 04 |shr bl,0x4
0040134B |. 80E3 0F |and bl,0xF
0040134E |. 3C 0A |cmp al,0xA
00401350 |. 1C 69 |sbb al,0x69
00401352 |. 2F |das
00401353 |. 38444F 01 |cmp byte ptr ds:[edi+ecx*2+0x1],al
00401357 |. 75 16 |jnz XCracked.0040136F ; 如果跳了就返回0
00401359 |. 8AC3 |mov al,bl
0040135B |. 3C 0A |cmp al,0xA
0040135D |. 1C 69 |sbb al,0x69
0040135F |. 2F |das
00401360 |. 38044F |cmp byte ptr ds:[edi+ecx*2],al
00401363 |. 75 0A |jnz XCracked.0040136F ; 如果跳了就返回0
00401365 |. 41 |inc ecx
00401366 |. 83F9 04 |cmp ecx,0x4
00401369 |.^ 75 D2 \jnz XCracked.0040133D
0040136B |. 33C0 xor eax,eax
0040136D |. 40 inc eax ; 使得返回值为1
0040136E |. C3 retn
0040136F |> 33C0 xor eax,eax
00401371 \. C3 retn
动态跟踪一下就知道,每次跳出循环的判断都是与输入的key里不同位置的字符比较,所以可以动态跟踪完这个第二个循环就可以得知key了。
至于注册机的话可以直接照抄算法。把比较的代码去掉就好了。
要注意das指令的作用。
当CF==1 或 AF==1 都会改变eax的值