中国汉化 - www.shanse8.com

直接加微信

鼠标放在右下面微信图标上,会弹出微信二维码

扫描二维码访问中国汉化官网移动版

成就您每时每刻您所需要的

扫一扫,加微信好友

可直接咨询与求助

-->

教生手写注册机 [复制链接]

  • 42584阅读
  • 264回复
楼主  发表于: 2008-03-22 只看楼主 倒序阅读
0F

中国汉化网提醒您:

— 本帖被 admin 从 软件破解 移动到本区(2008-06-05) —
关键词: 教程经典破解
到一些黑客站点上转转,发现那些最受欢迎、点击次数最多的文章都是一些“教菜鸟使用木马”“入侵初级教程”之类文章,而“Outlook Express HTML邮件超长字节href值缓冲溢出缺陷”“PHP fopen()函数易遭到CRLF Injection攻击”这种文章却乏人问津,尽管这或许才是真正高手所关心的。 G.2\Sw  
75@!j[QL<  
现在看雪论坛上后一种文章逐渐增多,当然是因为大家的水平都提高了,但也给刚入门的菜鸟带来了麻烦,来了之后什么也看不懂,在高手看来不是问题的问题常常困扰新手们很长时间:为什么这里是关键跳转,那边是重要CALL?为什么有的CALL要跟进,有的CALL只需带过?我按照高手所写的一步步做下去成功了,可为什么要这样做呢?我想更有不少人好不容易破了一个明码比较的软件,想贴出来又怕为高手所不屑而做罢。 }ufzlHD  
%bu$t,  
因此我找了一个非常简单的CrackMe(如果你是高手,只静态调试应该就可以搞定了:)),从头到尾仔仔细细地写出了分析过程,在里面加入了些我认为应该注意的地方,希望能对刚入门的朋友有些帮助。我不是什么高手,最多算是破解得熟练一点儿了而已,也许这样才更能了解新手们的难处吧。 r] h>Bb  
VI xGD#m  
这里我用W32Dasm作为静态反汇编的工具,各位可能有用C32Asm或者其他的,基本功能其实应该差不多。 i-.]onR  
:G.u{cw  
先胡乱输入用户名和注册码,点"Check the Serial",看看错误信息是什么(如果出现“注册码正确”的话就别在这儿看了,赶紧买彩票去:D)好出来了,“This serial is *NOT* Valid!! Try again... : UNREGISTERED”。 / @v V^!#1  
 Mi>!  
好了运行W32Dasm把它反汇编,在串式参考(string reference)中找吧,注意当字串较长时有时不能完全显示,这时只要找前面一段就行了,比如这次就是,找到"This serial is *NOT* Valid!! Try ",就是它了,双击来到引用该字串的地方。(PS:有时错误信息在代码中会不止一次出现,这时只要多次双击就能找到其他的地方。) *5|;eN  
'CQ~ZV5  
下面我要引用代码了(这是在W32DASM里的形式,如果你用OD或SI动态跟踪时形式会略有不同)。不要被这么多代码搞晕了,建议先跳过代码看我的后面的说明,再从代码中对照。 ]_"c_QG  
Yvi.l6JL  
n-"(lWcp  
代码:-------------------------------------------------------------------------------- ;J uBybJb  
* Possible Reference to Dialog: DialogID_0001, CONTROL_ID:0066, "" \m xi8Z w  
                                  | 9QXBz=Fnf  
:00401085 6A66                    push 00000066    ;输入用户名的文本框ID &GfDo4$  
:00401087 53                      push ebx    ;对话框句柄 ngt?9i;N  
+vr|J:  
* Reference To: USER32.GetDlgItem, Ord:0000h >;K!yI?0  
                                  | yI{4h $c  
:00401088 E8159C0000              Call 0040ACA2    ;得到文本框句柄 h@2YQgw`  
:0040108D 6A64                    push 00000064    ;得到字符串的最大长度 ip+?k<]z  
:0040108F 8D9548FFFFFF            lea edx, dword ptr [ebp+FFFFFF48] CcJ%; .V,T  
:00401095 52                      push edx    ;EDX是存取字符串的地址 EXbaijHQG  
:00401096 50                      push eax    ;EAX是上面得到的文本框句柄 \Dx;AKs  
|e_'% d&  
* Reference To: USER32.GetWindowTextA, Ord:0000h B9: i.rQ  
                                  | K^Ho%_)  
:00401097 E8129C0000              Call 0040ACAE    ;得到用户名,在[ebp+FFFFFF48] c }7gHud  
1>=]lMW  
* Possible Reference to Dialog: DialogID_0001, CONTROL_ID:0068, "" mhgvN-? "h  
                                  | l+#uQo6cqQ  
:0040109C 6A68                    push 00000068    ;同样的操作,输入注册码的文本框ID 7Tc^}Q  
:0040109E 53                      push ebx v05$"Ig  
a_ \t(U  
* Reference To: USER32.GetDlgItem, Ord:0000h 3z0 %uY[e  
                                  | aeE~[m  
:0040109F E8FE9B0000              Call 0040ACA2 a] P0PH~  
:004010A4 6A64                    push 00000064 g!;a5p6  
:004010A6 8D8DE4FEFFFF            lea ecx, dword ptr [ebp+FFFFFEE4] 2f5YkmGc";  
:004010AC 51                      push ecx H}cq|hodn  
:004010AD 50                      push eax ,0@QBr5P  
b/d 1(B@  
* Reference To: USER32.GetWindowTextA, Ord:0000h I`nC\%g  
                                  | fwi -   
:004010AE E8FB9B0000              Call 0040ACAE    ;得到注册码,在[ebp+FFFFFEE4] pB0 SCS*  
~Kt2g\BSok  
* Possible Reference to Dialog: DialogID_0001, CONTROL_ID:0067, "" riQ0'-p  
                                  | jt0f*e YE8  
:004010B3 6A67                    push 00000067    ;这个是最下面的提示的文本框的ID eyy%2> b  
:004010B5 53                      push ebx L|p+;ex  
7 C6qGCzlG`  
* Reference To: USER32.GetDlgItem, Ord:0000h $ncP#6  
                                  | WO*dO9O  
:004010B6 E8E79B0000              Call 0040ACA2    ;得到句柄 IeAi'  
:004010BB 8BF0                    mov esi, eax    ;放在ESI备用 W^i[7 r  
:004010BD 8D8548FFFFFF            lea eax, dword ptr [ebp+FFFFFF48] ~&WBA]w'+  
:004010C3 50                      push eax    ;指向用户名 B.}j1 Bb  
:004010C4 E867050000              call 00401630    ;得到用户名长度 bUe6f,8,  
:004010C9 59                      pop ecx QtLd(& !v  
:004010CA 8945D8                  mov dword ptr [ebp-28], eax  ;长度放在[ebp-28] 'jYKfq~_cJ  
:004010CD 8D95E4FEFFFF            lea edx, dword ptr [ebp+FFFFFEE4] %?J-0  
:004010D3 52                      push edx    ;指向注册码 '`&b1Rc  
:004010D4 E857050000              call 00401630    ;得到注册码长度 TVK*l*  
:004010D9 59                      pop ecx ]'<"qY  
:004010DA 68EAB04000              push 0040B0EA P}vk5o'  
:004010DF E84C050000              call 00401630 EQX?Zs?C  
:004010E4 59                      pop ecx ;".]W;I*O  
:004010E5 680EB14000              push 0040B10E 5>-~!Mg1  
:004010EA E841050000              call 00401630 Wqe0m_7  
:004010EF 59                      pop ecx 0NXaAf:2Z  
:004010F0 837DD803                cmp dword ptr [ebp-28], 00000003 e09QaY  
:004010F4 7E7B                    jle 00401171    ;用户名长度不能小于等于3 oot kf=  
:004010F6 90                      nop w +HKvOs5c  
:004010F7 90                      nop _r`(P#Hy  
:004010F8 90                      nop Fyc":{Jd  
:004010F9 90                      nop LG=_>:~t>  
:004010FA 33C9                    xor ecx, ecx uf`/-jY  
:004010FC 33D2                    xor edx, edx :!fU+2$`^(  
:004010FE 33DB                    xor ebx, ebx rji<g>GQ  
:00401100 33C0                    xor eax, eax JR|P]}  
:00401102 837DD832                cmp dword ptr [ebp-28], 00000032 C+0BV~7J<<  
:00401106 7D69                    jge 00401171    ;用户名长度不能大于等于32h QPW+L*2  
:00401108 90                      nop rR(\fX!dg  
:00401109 90                      nop /?S,u,R  
:0040110A 90                      nop 1+Bj` ACP  
:0040110B 90                      nop :(i=> ~O  
XpdjWLO]C<  
* Referenced by a (U)nconditional or (C)onditional Jump at Address: ?d)FYB  
|:0040111C(C) Jy0(g T  
| #wF6WxiG  
:0040110C 0FBE840D48FFFFFF        movsx eax, byte ptr [ebp+ecx-000000B8];依次取用户名的字符 ;z9U_  
:00401114 41                      inc ecx    ;ECX为循环变量  bRx}ih  
:00401115 33C1                    xor eax, ecx    ;取的字符与循环变量XOR *m&(h@l  
:00401117 03D8                    add ebx, eax    ;把结果累加到EBX /z4n?&tM  
:00401119 3B4DD8                  cmp ecx, dword ptr [ebp-28]  ;循环变量与用户名长度相比 $WbfRyXi7'  
:0040111C 75EE                    jne 0040110C    ;如果未取完就跳回继续 9<"l!noy  
:0040111E 6BC006                  imul eax, 00000006  ;最后一轮计算的结果在EAX, 乘6 &DWSu`z  
:00401121 C1E307                  shl ebx, 07    ;前面累加结果左移7位 8LlWXeD9  
:00401124 03C3                    add eax, ebx    ;相加 fUB+9G(Bx  
:00401126 8945C8                  mov dword ptr [ebp-38], eax Bmi9U   
:00401129 FF75C8                  push [ebp-38]    ;把上面结果压栈 TL([hR _  
+qmV|$rmM  
* Possible StringData Ref from Data Obj ->"%lX" RGLi#:0_.x  
                                  | jNP%BNd1f  
:0040112C 6838B44000              push 0040B438    ;一个转换的标识 G4)X~.Fy  
:00401131 8D8D80FEFFFF            lea ecx, dword ptr [ebp+FFFFFE80] F vHd `  
:00401137 51                      push ecx    ;存放转换结果的地址 ?., 2EC=+  
:00401138 E8873D0000              call 00404EC4    ;数字转为十六进制字串 axdRV1+s  
:0040113D 83C40C                  add esp, 0000000C x%, !px3s  
:00401140 8D8580FEFFFF            lea eax, dword ptr [ebp+FFFFFE80] q@Sj$  
:00401146 50                      push eax    ;上面转换的字串 HH'5kE0;d  
:00401147 8D95E4FEFFFF            lea edx, dword ptr [ebp+FFFFFEE4] };]f 3  
:0040114D 52                      push edx    ;假注册码 ph=U<D4  
C07U.nzh  
* Reference To: KERNEL32.lstrcmpA, Ord:0000h =idZvD  
                                  | &!O~ f  
:0040114E E8339C0000              Call 0040AD86    ;比较 O_y?53X  
:00401153 85C0                    test eax, eax /&G )IY]g  
:00401155 750D                    jne 00401164    ;这里就是关键的跳转 F9 C3i  
%R LGO&  
* Possible StringData Ref from Data Obj ->"Congratulations! IF this number " >X-*Hu'U#  
                                        ->"comes *FROM YOUR* keygen, Write " 6T{SRN{  
                                        ->"a tutorial dude ;)." {]dH+J7  
                                  | -[.A6W  
:00401157 683CB44000              push 0040B43C    ;指向表示成功的字符串 UqZ#mKi  
:0040115C 56                      push esi    ;ESI还记得么?那个提示文本框的句柄 #~`]eM5`J  
"4e{Cq  
* Reference To: USER32.SetWindowTextA, Ord:0000h R3Ka^l8R|  
                                  | m kHcGB!~  
:0040115D E8289B0000              Call 0040AC8A    ;显示出来 'ai!6[|SD  
:00401162 EB18                    jmp 0040117C [*AWCV  
Seb J}P1x  
* Referenced by a (U)nconditional or (C)onditional Jump at Address:  `Aa*}1  
|:00401155(C) @%sr#YqY  
| nH % 1lD?:  
 V_-{TGKX  
* Possible StringData Ref from Data Obj ->"This serial is *NOT* Valid!! Try " N"wp2w  
                                        ->"again... : UNREGISTERED" <UMT:`h1MZ  
                                  | &9F(uk=X  
:00401164 6890B44000              push 0040B490    ;开始时停在这句,向上找跳转 V9Gk``F<RZ  
:00401169 56                      push esi    ;ESI提示文本框的句柄 5zBayJh#  
x3++JG  
* Reference To: USER32.SetWindowTextA, Ord:0000h }th^l*g  
                                  | +\O[)\  
:0040116A E81B9B0000              Call 0040AC8A mC}!;`$8p  
:0040116F EB0B                    jmp 0040117C _noQk3N  
Y4B< ]C4  
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: a|v}L,  
|:004010F4(C), :00401106(C) yw( E}   
| AIXvS*Y,  
r4D 6I,  
* Possible StringData Ref from Data Obj ->"Name must contain more than 4 " OJ'x>kE  
                                        ->"chars and less than 50 chars !!" #!FLX*,  
                                  | g}-Ch#  
:00401171 68C9B44000              push 0040B4C9    ;用户名不符合要求跳到这里 D-8>?`n\  
:00401176 56                      push esi    ;ESI提示文本框的句柄 ;^,2 QsM  
GD$jP?  
* Reference To: USER32.SetWindowTextA, Ord:0000h [wM<J$=2  
                                  | yMNLsR~rh  
:00401177 E80E9B0000              Call 0040AC8A xmDX1sL**  
lbES9o5  
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: FNDLqf!j  
|:00401162(U), :0040116F(U) s'^zudx  
|  afEp4(X~  
:0040117C 5F                      pop edi JXlFo3<  
:0040117D 5E                      pop esi z#!xqIg0  
:0040117E 5B                      pop ebx >:]fN61#  
:0040117F 8BE5                    mov esp, ebp er5}=cFZ  
:00401181 5D                      pop ebp    ;整理一下返回了 'KGY;8<x]  
:00401182 C3                      ret skcMGEB  
-------------------------------------------------------------------------------- N,ik&NIWy  
双击后光标停在401164这一句。很明显,如果我们来到这句时我们就死翘翘了,而如果我们的注册码正确的话当然不会来到这一句(废话太多了:p)那么这一句上面就肯定会有一个条件跳转的指令。(这是找爆破点时的基本思想)向上找找看,找到了: F!>K8q  
7o z(hO~  
:00401155 750D                    jne 00401164 >V(2Ke Y  
W7A'5  
正好跳到401164错误信息那一句。呵呵,如果你想爆破的话,只要把750D改成740D(je,把条件反过来,注册码错误就显示正确信息:D)或者改成EB0D(jmp,无条件跳转,不管三七二十一就正确)。 f 5i`B*/  
UKK}$B  
OK,我们不能满足于此啊,咱们看看它的算法是怎样的,也像那些神秘兮兮的高手似的写一个注册机出来。:D [/uKo13  
W? UCo6<m  
我先给各位补一点课,就是对函数的调用。除了一些DELPHI程序之外,对函数参数的传递大都用堆栈来完成,简单地说就是把函数的各个参数先PUSH进去,然后再CALL这个函数。在函数内部呢,一般[ebp+8]是第一个参数,[ebp+C]是第二个参数,每次多加4依此类推。而函数内部的局部变量常用[ebp-4][ebp-8]...等等。(原因讲起来有点复杂,先记住就行了)函数的返回值在EAX里。 SA>;]6)`(  
Ql*/{#$  
一般来说,软件的判断注册部分都是一个函数,在函数开头最经典的两句就是 o m_&|9B)  
G0s:Dum  
push ebp <M'IR f/D  
mov ebp,esp M<$l&%<`G  
)vU{JY;  
这和堆栈处理有关,我们菜鸟先不用太明白,知道这通常是一个函数的开始就行了。向上找找有没有丫,找到了没有,在最上面哪(我上面没有列出来)。如果你想完整地判断它的算法的话,一般从这里开始就行了。在这个程序中前面都是一些初始化之类的东东,所以我把前面一部分省略了。(这也是破解时的原则,不要在无关紧要的地方费功夫,在高级语言中,代码有很大部分是机器自动生成的,电脑一行行写代码不知道累,人脑一行行读代码怎么受得了?你的脑袋是几GHz的CPU?常见有些没有破解经验的汇编高手,完全懂得每行代码的意思,就是找不到关键的地方,原来他跟了半天都是在API里转,白做无用功了。) h5F'eur  
$m=z87hX  
好了,现在可以动态调试了。我们在开头这里下个断点,一步步向下看,出现了一个CALL GetDlgItem,我们来看一看函数说明(手头一份这个是必需的) ~v54$#CB  
3N*Shzusbt  
HWND GetDlgItem( !F<?he<U  
    HWND hDlg,  // handle of dialog box _@OYC<  
    int nIDDlgItem  // identifier of control Fp]8f&l8  
  ); ;Z`)*TRp4  
9bNIaC*M  
呵呵,简单的说这个函数就是让程序确定一个对话框上的控件,第一个参数是对话框的句柄,第二个参数是对话框上某个控件的ID,函数会返回该控件的句柄,这样在下面就可以用这个句柄来操作了。看程序: ~Op1NE  
>Qx#2x+  
eLYFd,?9  
代码:-------------------------------------------------------------------------------- P&tK}Se^V  
* Possible Reference to Dialog: DialogID_0001, CONTROL_ID:0066, "" y%,BDyK  
                                  | J9 =gv0  
:00401085 6A66                    push 00000066    ;控件ID E nvs[YZe  
:00401087 53                      push ebx    ;对话框句柄 vvM)Rb,  
;9PM?Iy[  
* Reference To: USER32.GetDlgItem, Ord:0000h K(d!0S  
                                  | f$>orVm%.  
:00401088 E8159C0000              Call 0040ACA2 X u_<4  
-------------------------------------------------------------------------------- eC$v0Gtq  
看见第一行没有,DialogID_0001,CONTROL_ID:0066,压进去了一个66作为第二个参数:控件ID(注意API调用是从右至左,也就是最后面一个参数先PUSH),用 资源查看工具 看看ID为66的是甚么呀,呵呵就是那个输入用户名的文本框嘛。好了,现在我们有文本框的句柄了,存在EAX里。接着向下看,又一个API,是GetWindowText。看看说明: `0^i #  
[tzSr=,Cg  
int GetWindowText( hQm4R]a  
    HWND hWnd,  // handle of window or control with text .NT&>X~.V  
    LPTSTR lpString,  // address of buffer for text AuTplO0_rE  
    int nMaxCount  // maximum number of characters to copy f4S@lyYF  
  ); 2]9<%-=S  
5uo(z,WLR  
从名字也能猜出来了,这个函数就是得到一个窗口类控件的文本。第一个参数是该控件的句柄,第二个是存放得到的文本的缓冲区的地址,第三个参数设定取文本的最大长度。看程序: {0e{!v  
]7t\%_  
代码:-------------------------------------------------------------------------------- -^H5z+"^  
:0040108D 6A64                    push 00000064    ;最大长度 f*vk1dS:*3  
:0040108F 8D9548FFFFFF            lea edx, dword ptr [ebp+FFFFFF48];把[ebp+FFFFFF48]先放在EDX里 9'q/&uH  
:00401095 52                      push edx    ;缓冲区地址[ebp+FFFFFF48] rp#*uV9;  
:00401096 50                      push eax    ;EAX?是上面那个API的返回值呀,控件句柄 j{R|]SjW2H  
XOg(k(&T  
* Reference To: USER32.GetWindowTextA, Ord:0000h ]8>UII,US  
                                  | rg^\BUa-W,  
:00401097 E8129C0000              Call 0040ACAE G=!bM(]R~  
-------------------------------------------------------------------------------- s<_LcQbt{  
好了,现在 D ebp+FFFFFF48 看看,是不是输入的用户名?(说明,在OLLY或SICE里这个是[ebp-B8]的形式,其实是一样的) 7]xz8t  
X,EYa>RSy_  
下面有类似的操作,只是控件ID成了68,可想而知就是得到注册码了,注册码放在[ebp+FFFFFEE4]。 &tz%WW%D8  
<Mn7`i  
呵呵,继续,到了这么几句: 0S:!Gv +  
[{p?BTs  
代码:-------------------------------------------------------------------------------- O<Sc.@~  
:004010BD 8D8548FFFFFF            lea eax, dword ptr [ebp+FFFFFF48] lDPRn~[#\  
:004010C3 50                      push eax v8[ek@  
:004010C4 E867050000              call 00401630 D*T$ v   
-------------------------------------------------------------------------------- .H (}[eG_  
这是干甚么牙?要不要进4010C4这个CALL 401630看看?且慢!我前面说过了,不要在无关紧要的地方费力,(啪!一个鸡蛋扔上来:谁知道这里是不是重要啊?)别急嘛,一般来说,先粗略地跟一遍,试着猜猜CALL的作用。如果发现返回值很可疑,再跟进细看也不迟。(这就需要一定的“直觉”了,英文叫“Sence”,台湾老大叫“触机”或者“先死:D”,别担心,破解得多了自然会有这种感觉,这种感觉很难说出来,有时候一见那种阵势就知道关键地方到了) 3@TG.)N4  
a[P>SqT4`  
又扯远了,我们回来看代码。一个CALL,前面有PUSH EAX,很明显是CALL的参数了。(见我前面的说明)看看EAX:lea eax,dword ptr [ebp+FFFFFF48]。[ebp+FFFFFF48]还有没有印象?对了,就是前面API调用中放用户名的地址呀。过了这里后D eax,呵呵不就是咱们的用户名吗,我输入的是“RoBa”,带过这个CALL后看看EAX是什么,嗯~~~~是4。想到什么了?没有?没关系咱们继续看下面: fyg~KF}  
K!- &Zv  
代码:-------------------------------------------------------------------------------- "Yfr"1RmO  
:004010C9 59                      pop ecx HDSA]{:sl  
:004010CA 8945D8                  mov dword ptr [ebp-28], eax  ;记住,上面的返回结果在[ebp-28] fJn3"D'  
:004010CD 8D95E4FEFFFF            lea edx, dword ptr [ebp+FFFFFEE4] APQQ:'>N4~  
:004010D3 52                      push edx @u"kX2>Eq  
:004010D4 E857050000              call 00401630 >xU72l#5  
-------------------------------------------------------------------------------- ~E3SC@KL  
又是一个CALL 401630,和上面一样的。看看它的参数EDX,[ebp+FFFFFEE4]呵就是假注册码呀,我输的是'87654321',返回值EAX=8,发现什么没有?对,这个CALL就是求一个字符串的长度嘛,要是跟进去又给费不少时间。向下: ek(kY6x:  
e"o6C\c  
代码:-------------------------------------------------------------------------------- hk"9D<&i>b  
:004010F0 837DD803                cmp dword ptr [ebp-28], 00000003 8t T&BmT  
:004010F4 7E7B                    jle 00401171 Y>78h2AU  
W>q*.9}Y"  
:00401102 837DD832                cmp dword ptr [ebp-28], 00000032 Pghva*&  
:00401106 7D69                    jge 00401171 !!-}ttFA  
-------------------------------------------------------------------------------- n!kk~65|  
还记得[ebp-28]是什么吗?对,就是用户名的长度,这几句的意思就很明显了,用户名的长度必须大于3小于32h,不然就跳到401171去了,你可以跟过去看看是什么,呵呵是用户名不符合要求之类的提示。 [D<RV3x9  
( E"&UC[  
好了我们来到关键地方喽: #RR:3ZP ZC  
V_+}^  
#sz]PZ\  
代码:-------------------------------------------------------------------------------- [ 5CS}FB  
* Referenced by a (U)nconditional or (C)onditional Jump at Address: #/n|@z'  
|:0040111C(C) g:3d<CS  
| iX8h2l  
:0040110C 0FBE840D48FFFFFF        movsx eax, byte ptr [ebp+ecx-000000B8] Fe_::NVvk  
:00401114 41                      inc ecx  avu*>SB  
:00401115 33C1                    xor eax, ecx 90  
:00401117 03D8                    add ebx, eax Nk lz_ ]  
:00401119 3B4DD8                  cmp ecx, dword ptr [ebp-28] io1S9a(y  
:0040111C 75EE                    jne 0040110C  *A~($ZtL  
-------------------------------------------------------------------------------- EpRXjz  
呵呵,是不是又晕了?[ebp+ecx-B8]这是啥呀?别着急,车到山前必有路。先 d ebp+ecx-B8看看,哟,不还是咱们的用户名吗?:D 怎么回事?好好想想,ecx现在是0,[ebp-B8]和[ebp+FFFFFF48](记得不?放用户名的地址)不是一回事嘛!(不明白的去补习一下负数的表示方法,我也不知道为什么W32DASM有时候非把-B8写成FFFFFF48) 33=Mm/<m$P  
f|- m ^/y  
再仔细看看,movsx eax,byte ptr [ebp+ecx-000000B8],注意是byte ptr,即以字节的方式读取(就是说每次读出一个字符),而且又加上了个ecx。如果你破解多了的话,应该立刻就明白:关键的地方到了。 X4d Xm>*?=  
+90u!r^v  
这是一个很典型的循环结构,看出来没?ecx就是循环变量了,每执行一次会从用户名中取一个字符,然后ecx加1,这样[ebp+ecx-B8]就指向用户名的下一个字符了。对取出来的字符与循环变量进行XOR运算,把结果累加到EBX。然后循环变量与[ebp-28]也就是用户名长度比较,如果不等于的话也就是还没取完,就返回上去继续取用户名的下一个字符。这样直到取完为止。 R'S c  
GLo\q:5A  
代码:-------------------------------------------------------------------------------- Wr]O  
:0040111E 6BC006                  imul eax, 00000006  ;EAX其实是上面最后一轮计算的结果,乘6 ' oBo|  
:00401121 C1E307                  shl ebx, 07    ;EBX是几轮计算累加起来的结果,左移7位 ~Y\QGuT  
:00401124 03C3                    add eax, ebx    ;加起来 i?ZA x4D  
:00401126 8945C8                  mov dword ptr [ebp-38], eax W\HLal  
:00401129 FF75C8                  push [ebp-38]    ;上面的结果,作为一个参数 A;odVaH7  
A|2 <A !  
* Possible StringData Ref from Data Obj ->"%lX" L30>| g  
                                  | $kD7y5  
:0040112C 6838B44000              push 0040B438    ;"%lX"有点眼熟哟 nHrP>zN  
:00401131 8D8D80FEFFFF            lea ecx, dword ptr [ebp+FFFFFE80] [6O04"6K  
:00401137 51                      push ecx    ;这是什么呢? OWqrD@  
:00401138 E8873D0000              call 00404EC4 _B}9 f  
:0040113D 83C40C                  add esp, 0000000C PXa5g5 !  
-------------------------------------------------------------------------------- a|U}Ammr  
前面几句是继续上面的计算,把EAX*6和EBX左移7位的值加进来,然后结果复制到[ebp-38]这个局部变量里作为下面CALL的一个参数,接着[ebp+FFFFFE80]作第二个参数,然后又一个CALL,还是那样,先别着急跟进去,前后看看有没有可疑之处: HC?0Lj  
pG(Fz0b{  
第一个参数[ebp-38],没什么好说的,上面计算的结果。第二个参数指向"%lX",这个字串写过C语言的都有印象吧,就是在printf里把一个数字按照大写的16进制方式显示出来所用的标识符,比方说把一个数字255转换成字串“FF”。(在WinAPI里叫wsprintf)第三个参数是什么呢?前面这种形式见多了吧,猜猜! r)Or\HL  
4e}{$s$Xx  
我们验证一下前面猜想是否正确,我用"RoBa"上面算出来的结果是46430,也就是16进制的B55E,我们跟过这个CALL看看结果如何?什么,结果在哪?聪明的你还没想到吗,上面那第三个参数[ebp+FFFFFE80]就是结果的地址呀。怎么样不出所料吧。 #hpIyy%n  
z* RSMfRW  
(其实从40113D这一句add esp,C也能看出来,因为在函数外平衡堆栈的只有这个一个参数数目不定的函数。引申一下,看不懂没关系啦:D ) :VJV5f{  
`v~!H\q  
接着看啦: i=-8@  
IJ0#iA. T  
代码:-------------------------------------------------------------------------------- &-=K:;x  
:00401140 8D8580FEFFFF            lea eax, dword ptr [ebp+FFFFFE80];眼熟吗,刚才的转换结果呀 nx B32  
:00401146 50                      push eax  ;EAX指向上面转换得到的字符串 t-!m vx9Z  
:00401147 8D95E4FEFFFF            lea edx, dword ptr [ebp+FFFFFEE4];这个很早了,向前面找找是啥 '#A:.P  
:0040114D 52                      push edx  ;EDX指向我们输入的假注册码 IO"hF  
p-,Iio+  
* Reference To: KERNEL32.lstrcmpA, Ord:0000h 5/ * >v  
                                  | -6`;},Yr  
:0040114E E8339C0000              Call 0040AD86 +;dXDZ2  
:00401153 85C0                    test eax, eax Ig9d#c  
:00401155 750D                    jne 00401164  ;关键跳转哟 ;%Q&hwj  
-------------------------------------------------------------------------------- iDw.i"b  
哈哈,lstrcmp,什么意思不用我说了吧,当然是STRingCoMPare字符串比较啦。把计算的结果与前面输入的假码比较,相等就OK了。好了,现在把上面的完整的代码过一遍,怎么样,写个注册机不难吧? m2O&2[g  
\(fq8AL?  
代码:-------------------------------------------------------------------------------- ,Kw5Ro`I:  
#include <string.h> #ib^Kg  
#include <stdio.h> h/K@IA d  
#include <stdlib.h> [;^,CD|P  
b#a@ rh  
void main() =9$mbn r  
{ ,E}$[mHyjz  
  int EAX=0,EBX=0,len; lhO2'#]i  
  char name[50]={0}; v{y{sA  
  char password[50]={0}; S4bBafj[I  
  printf("Please input your name:"); ,2,5Odrz  
  scanf("%s",name); AVFjBybu9  
  len=strlen(name); < kP+eD  
  for (int i=0;i<len;i++) l r~gG3   
  { /S~m)$vu  
    EAX=name^(i+1); Lgi[u"Du  
    EBX+=EAX; .:9s}%Z r  
  } Cq\I''~8  
  EAX*=6; &leK}je [  
  EBX<<=7; RiR:69xwR*  
  EAX+=EBX; |B^G:7c  
  printf("Your password is: %lX\n",EAX); 4c159wsnQ  
  printf("KeyGen by RoBa  Enjoy Cracking,Newbies!\n"); PDP[5q r  
} Zj VWxQ  
-------------------------------------------------------------------------------- 2Z/K(J"&J  
简单的C程序哟,你也可以用你熟悉的语言写一个。 'C>U=cE7  
aGoE,5  
后记: thW<   
`<fh+*  
这是一个简单的CRACKME,本来三言两语就能解决的,被我啰啰嗦嗦说了这么一大堆,就是希望能把问题真正地说明白了,希望通过这篇文章让你发现,破解软件乃至写注册机并不是多么困难的事,只要坚持下去,谁都有成为高手的那一天.
3条评分金币+2
青囊明仪 金币 +2 - 2011-09-27
北极光 无名金币 +20 有你支持论坛更精彩 2008-03-22
admin 无名金币 +20 优秀内容 2008-03-22
分享到
离线 北极光
发表于: 2008-03-22 只看该作者
1F
希望LZ写完基础知识后多出写破解教程!会汉化、会破解搞死那些老毛子!
离线 admin 【总管理员】
发表于: 2008-03-22 只看该作者
2F
喜欢制作注册机的朋友们,可以借鉴了。。。
离线 lishanqiang
发表于: 2008-03-23 只看该作者
3F
看起来好复杂啊。。。。。
离线 kinkon
发表于: 2008-03-23 只看该作者
4F
嗯..我以前也在看雪论坛学习过...不过还是不能熟练...继续学习中
离线 she88
发表于: 2008-03-26 只看该作者
5F
看不懂呀
离线 frank1314
发表于: 2008-04-04 只看该作者
6F
LZ你还收徒弟么 C@<gCMj,"  
我想跟你学习\ %%)y4>I  
收我好么???
离线 cc799
发表于: 2008-04-14 只看该作者
7F
火星文,,,,看不懂,帮顶
离线 rong9970
发表于: 2008-04-17 只看该作者
8F
有点复杂,因为我不懂,学习
离线 JACKYYOUNG
发表于: 2008-04-28 只看该作者
9F
看起来好复杂啊。。。。。 ,3`RM $  
谁能破vray 1.50sp2?
快速回复
限150 字节
温馨提示:严禁胡乱恶意回复帖子,违者严惩,严重者封号!
 
上一个 下一个
      你的浏览器不支持js脚本,无法发帖,请修改浏览器设置,支持js脚本并刷新页面后再发帖!
      欢迎光临中国汉化网

      登录后更精彩!

      下拉
      使用快捷登录 或 免费注册