coolfire1983 发表于 2009-3-4 20:05:29

上几楼的高手真厉害啊 学习了 呵呵

jzyjd 发表于 2009-3-10 23:10:34

答案:
破文标题】 CrackMe之chap203 破解分析

【使用工具】 peid,olldbg

【破解平台】 Win2000/XP

【软件名称】 chap203

【软件大小】 12KB

【编程语言】 MASM32/TASM32

【软件简介】 加密和解密第一版第二章第三个CrackMe。

【破解目的】 从头学起,打好基础。


【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)

------------------------------------------------------------

首先 Peid 检测程序编程语言是MASM32 / TASM32,运行程序。

没输入或错误注册码提示

"Your registration info is invalid... Note that most of the special chars may raise registration problems!"
这次W32Dasm败下阵来了,看不到任何字符参考。
这次OD直接披挂上阵。
载入程序,点右键-搜索-字符参考。

004010E1   push chap203.00402061                     ASCII "Congratulations! Please send your keygen (working one) to [email protected]!"

00401224   push chap203.004020AE                     ASCII "Your registration info is invalid... Note that most of the special chars may raise registration problems!"

//先双击00401224 到失败处代码段看看。

这两句让我们感兴趣。

0040121A   > \68 00200000   push 2000//这句有个>箭头表示从某处跳转过来,根据OD的红线向上找。

0040121F   .68 01204000   push chap203.00402001                  ; |Title = "Duelist's Crackme #4"

00401224   .68 AE204000   push chap203.004020AE                  ; |Text = "Your registration info is invalid... Note that most of the special chars may raise registration problems!"

00401229   .6A 00         push 0                                 ; |hOwner = NULL

0040122B   .E8 36010000   call <jmp.&USER32.MessageBoxA>         ; \MessageBoxA

...........................................................................

于是截取了一段关键代码。

填入用户

Mr.David
注册码
123456789

这个程序不是用 GetDlgItemTextA 或 GetWindowTextA 获取字符,而是用消息函数SendDlgItemMessageA 获取字符信息,我们把断点下在00401127处,点Check按钮立即中断。注意用Alt+F5前台显示切换便于调试。

004010D7   > /68 00200000   push 2000                              ; /Style = MB_OK|MB_TASKMODAL

004010DC   . |68 01204000   push chap203.00402001                  ; |Title = "Duelist's Crackme #4"

004010E1   . |68 61204000   push chap203.00402061                  ; |Text = "Congratulations! Please send your keygen (working one) to [email protected]!"

004010E6   . |6A 00         push 0                                 ; |hOwner = NULL

004010E8   . |E8 79020000   call <jmp.&USER32.MessageBoxA>         ; \MessageBoxA

004010ED   . |B8 01000000   mov eax, 1

004010F2   . |EB 25         jmp short chap203.00401119

004010F4   > |817D 0C 11010>cmp dword ptr ss:, 111

004010FB   . |0F84 FA000000 je chap203.004011FB

00401101   . |817D 0C 10010>cmp dword ptr ss:, 110

00401108   . |74 16         je short chap203.00401120

0040110A   . |837D 0C 10    cmp dword ptr ss:, 10

0040110E   . |0F84 F7000000 je chap203.0040120B

00401114   . |B8 00000000   mov eax, 0

00401119   > |5F            pop edi

0040111A   . |5E            pop esi

0040111B   . |5B            pop ebx

0040111C   . |C9            leave

0040111D   . |C2 1000       retn 10

00401120   > |B8 01000000   mov eax, 1

00401125   .^|EB F2         jmp short chap203.00401119

00401127   > |6A 00         push 0                                 ; /lParam = 0

00401129   . |6A 00         push 0                                 ; |wParam = 0

0040112B   . |6A 0E         push 0E                                  ; |Message = WM_GETTEXTLENGTH

0040112D   . |6A 03         push 3                                 ; |ControlID = 3

0040112F   . |FF75 08       push dword ptr ss:                ; |hWnd

00401132   . |E8 41020000   call <jmp.&USER32.SendDlgItemMessageA>   ; \SendDlgItemMessageA

00401137   . |A3 AF214000   mov dword ptr ds:, eax//eax返回用户字符数目5

0040113C   . |83F8 00       cmp eax, 0   //比较eax是否为0

0040113F   . |0F84 D5000000 je chap203.0040121A //是则跳走Over。

00401145   . |83F8 08       cmp eax, 8//比较eax是否大于8个字符。

00401148   . |0F8F CC000000 jg chap203.0040121A //是则跳走Over。

0040114E   . |8BF0          mov esi, eax

00401150   . |6A 00         push 0                                 ; /lParam = 0

00401152   . |6A 00         push 0                                 ; |wParam = 0

00401154   . |6A 0E         push 0E                                  ; |Message = WM_GETTEXTLENGTH

00401156   . |6A 04         push 4                                 ; |ControlID = 4

00401158   . |FF75 08       push dword ptr ss:                ; |hWnd

0040115B   . |E8 18020000   call <jmp.&USER32.SendDlgItemMessageA>   ; \SendDlgItemMessageA

00401160   . |83F8 00       cmp eax, 0//直接比较eax返回注册码字符数目9是否为0

00401163   . |0F84 B1000000 je chap203.0040121A//是则跳走Over。

00401169   . |3BF0          cmp esi, eax//比较用户名和注册码的长度是否相同。

0040116B   . |0F85 A9000000 jnz chap203.0040121A//不同跳走Over。



这里修改用户名



David

注册码
12345

再次来到这里。

00401171   . |68 60214000   push chap203.00402160                  ; /lParam = 402160

00401176   . |6A 08         push 8                                 ; |wParam = 8

00401178   . |6A 0D         push 0D                                  ; |Message = WM_GETTEXT

0040117A   . |6A 03         push 3                                 ; |ControlID = 3

0040117C   . |FF75 08       push dword ptr ss:                ; |hWnd

0040117F   . |E8 F4010000   call <jmp.&USER32.SendDlgItemMessageA>   ; \SendDlgItemMessageA

00401184   . |68 79214000   push chap203.00402179                  ; /lParam = 402179

00401189   . |6A 10         push 10                                  ; |wParam = 10

0040118B   . |6A 0D         push 0D                                  ; |Message = WM_GETTEXT

0040118D   . |6A 04         push 4                                 ; |ControlID = 4

0040118F   . |FF75 08       push dword ptr ss:                ; |hWnd

00401192   . |E8 E1010000   call <jmp.&USER32.SendDlgItemMessageA>   ; \SendDlgItemMessageA

00401197   . |B9 FFFFFFFF   mov ecx, -1

0040119C   > |41            inc ecx

0040119D   . |0FBE81 602140>movsx eax, byte ptr ds://逐位取用户名的16进制。

004011A4   . |83F8 00       cmp eax, 0   比较是否为0,判断输入是否是字符。

004011A7   . |74 32         je short chap203.004011DB//不是则跳走Over。

004011A9   . |BE FFFFFFFF   mov esi, -1

004011AE   . |83F8 41       cmp eax, 41//比较eax是否小于41(A)

004011B1   . |7C 67         jl short chap203.0040121A//小于over,不能是数字等字符。

004011B3   . |83F8 7A       cmp eax, 7A //比较eax是否大于7A(z)

004011B6   . |77 62         ja short chap203.0040121A //大于over,不能是数字等字符。

004011B8   . |83F8 5A       cmp eax, 5A//比较eax是否大于5A(Z)

004011BB   . |7C 03         jl short chap203.004011C0 //小于则跳走,不处理。

004011BD   . |83E8 20       sub eax, 20    //将小写字符转为大写。

004011C0   >46            inc esi                                                            

004011C1   . |0FBE96 172040>movsx edx, byte ptr ds: //计算序列号的原始字串。

004011C8   . |3BC2          cmp eax, edx//判断当前字符串是否等于edx。

004011CA   .^|75 F4         jnz short chap203.004011C0//不等则循环。

004011CC   . |0FBE86 3C2040>movsx eax, byte ptr ds: //如相等则eax=正确字符。

004011D3   . |8981 94214000 mov dword ptr ds:, eax //将字符存贮在00402194

004011D9   .^|EB C1         jmp short chap203.0040119C//循环。

004011DB   > |FF35 AF214000 push dword ptr ds:   //序列号数目5进堆栈。

004011E1   . |68 94214000   push chap203.00402194         //真码进入堆栈。

004011E6   . |68 79214000   push chap203.00402179      //假码入堆栈。

004011EB   . |E8 54000000   call chap203.00401244   //比较Call,跟进。

004011F0   . |83F8 01       cmp eax, 1//EAX=1则注册正确。

004011F3   .^\0F84 DEFEFFFF je chap203.004010D7//跳到注册成功对话框处。

004011F9   .EB 1F         jmp short chap203.0040121A

004011FB   >837D 10 01    cmp dword ptr ss:, 1             ; |

004011FF   .^ 0F84 22FFFFFF je chap203.00401127                      ; |

00401205   .837D 10 02    cmp dword ptr ss:, 2             ; |

00401209   .75 2F         jnz short chap203.0040123A               ; |

0040120B   >E8 B4000000   call <jmp.&KERNEL32.ExitProcess>         ; \ExitProcess

00401210   .B8 01000000   mov eax, 1

00401215   .^ E9 FFFEFFFF   jmp chap203.00401119

0040121A   >68 00200000   push 2000                              ; /Style = MB_OK|MB_TASKMODAL; Default case of switch 004011A4

0040121F   .68 01204000   push chap203.00402001                  ; |Title = "Duelist's Crackme #4"

00401224   .68 AE204000   push chap203.004020AE                  ; |Text = "Your registration info is invalid... Note that most of the special chars may raise registration problems!"

00401229   .6A 00         push 0                                 ; |hOwner = NULL

0040122B   .E8 36010000   call <jmp.&USER32.MessageBoxA>//错误提示。

.....................................................................



转存信息



0040201741 31 4C 53 4B 32 44 4AA1LSK2DJ

0040201F46 34 48 47 50 33 51 57F4HGP3QW

004020274F 35 45 49 52 36 55 54O5EIR6UT

0040202F59 5A 38 4D 58 4E 37 43YZ8MXN7C

0040203742 56 39 00 20 53 55 37BV9. SU7

0040203F43 53 4A 4B 46 30 39 4ECSJKF09N

0040204743 53 44 4F 39 53 44 46CSDO9SDF

0040204F30 39 53 44 52 4C 56 4B09SDRLVK

0040205737 38 30 39 53 34 4E 467809S4NF



004011EB   . |E8 54000000   call chap203.00401244   //比较Call,跟进。



00401244/$C8 000000   enter 0, 0

00401248|.B8 01000000   mov eax, 1

0040124D|.8B7D 08       mov edi, dword ptr ss:

00401250|.8B75 0C       mov esi, dword ptr ss:

00401253|.8B4D 10       mov ecx, dword ptr ss://esi 存放真码 KSN0K

00401256|.F3:A6         repe cmps byte ptr es:, byte ptr ds>

00401258|.67:E3 05      jcxz short chap203.00401260

0040125B|.B8 00000000   mov eax, 0

00401260|>C9            leave

00401261\.C2 0C00       retn 0C



注册码算法

取地址
处的字符与注册码第一位比较,不相等则esi加1,直到两者相同为止。

然后取 算出注册码第一位。

后面位数的一样。


【内存注册机】

修改内存

修改地址
401148

修改长度

6

原始指令

0F8FCC000000
修改指令
909090909090

添加
修改地址
40116B
修改长度
6
原始指令
0F85A9000000
修改指令
909090909090
添加
中断地址
4011EB
中断次数 1
第一字节 E8
指令长度 5
继续添加
中断地址
401256
中断次数 1
第一字节 F3
指令长度 2
最后内存方式寄存器 Esi

[ 本帖最后由 jzyjd 于 2009-3-10 23:14 编辑 ]
页: 1 [2]
查看完整版本: 上次发错了,这个才是不明码比较的。高手飘过。