python写的第一个注册机

来源:互联网 发布:淘宝借贷在哪里 编辑:程序博客网 时间:2024/05/18 03:46

 本文是从看雪上学习的。网址如下:http://bbs.pediy.com/showthread.php?threadid=23014 。

算法分析部分还是直接从那里贴过来吧,以后备用:

===========================================分析说明=====================================================

【软件名称】Bad Sector CrackMe1
【下载地址】附件(附KeyGen源码,本文和CrackMe1)
【应用平台】Win9x/NT/2000/XP
【软件大小】10K
【软件限制】没有。
【保护方式】用户名+序列号
【破 解 者】andy00
【破解难度】1/10
【破解声明】只是为了熟悉逆向工程。
【破解工具】OllyDbg,ResHacker,Windows自带计算器
【注册机下载】仅提供源代码,支持共享软件
【软件简介】My firts Crackme..ahh.This one is damn easy and I expect from anyoneto create keygen 
            for it, but if you cant code one,it would be enough to understand how it calculates real serial. 
            Enjoy btw. it's not packed/protected.   -Bad Sector
            
            
;======================================================================================================
【分析过程】

为了熟悉逆向工程,静态分析能力,不调试

1、 直接用OllyDbg反汇编,无壳;

2、 在ResHacker看到用户名栏ID为C8,注册码栏为C9

3、 在OllyDbg查找输入函数GetWindowText和GetDlgItemText,顺利地找到了GetDlgItemText,
    找到nIDDlgItem(要获取字符串的控件的ID)参数为03EB的那一个,这个GetDlgItemText应该就是获取输入的注册码的地方了.
(这里说明下,我在xp sp3下是用的GetDlgItemTextA这个函数)
00401139     6A 32           push 32                            ; nMaxCount=32;
0040113B     68 F3204000     push Crackme1.004020F3             ; lpNameBuf=004020F3;
00401140     68 C8000000     push 0C8                           ; nIDDlgItem=C8;
00401145     FF75 08         push dword ptr ss:[ebp+8]
00401148     E8 DE000000     call <jmp.&USER32.GetDlgItemTextA> ; eax=GetDlgItemTextA(hDlg,nIDDlgItem,lpNameBuf,nMaxCount);
                                                                ;取用户名到004020F3,用户名字符个数放到eax
0040114D     83F8 00         cmp eax,0
00401150     0F84 99000000   je Crackme1.004011EF               ; if(eax==0) goto 004011EF(失败消息);没有输入则失败
00401156     83F8 04         cmp eax,4
00401159     0F82 90000000   jb Crackme1.004011EF               ; if(eax<4) goto 004011EF(失败消息);字符数<4失败
0040115F     33C9            xor ecx,ecx
00401161     33DB            xor ebx,ebx
00401163     33F6            xor esi,esi                        ; ecx=ebx=esi=0;寄存器ECX,EBX,ESI清0
00401165     8945 FC         mov dword ptr ss:[ebp-4],eax       ; localVar1=eax;用局部变量localVar1保存字符个数
00401168     0FBE81 F3204000 movsx eax,byte ptr ds:[ecx+4020F3] ; eax=strUserName[ecx];取用户名第ecx+1个字符到eax
0040116F     83F8 20         cmp eax,20
00401172     74 07           je short Crackme1.0040117B         ; if(eax==空格) goto 0040117B继续循环
                                                                ;此处说明程序忽略空格
00401174     6BC0 04         imul eax,eax,4                     ; eax=eax*4;
00401177     03D8            add ebx,eax                        ; ebx==ebx+eax;
00401179     8BF3            mov esi,ebx                        ; esi=ebx;
0040117B     41              inc ecx                            ; ecx=ecx+1;计数器增加1
0040117C     3B4D FC         cmp ecx,dword ptr ss:[ebp-4]
0040117F   ^ 75 E7           jnz short Crackme1.00401168        ; if(ecx!=localVar1) goto 00401168 没取完取下个字符;
00401181     83FE 00         cmp esi,0
00401184     74 69           je short Crackme1.004011EF         ; if (esi==0) goto 004011EF(失败消息);若ESI等于0,则注册失败;
00401186     BB 89476500     mov ebx,654789                     ; ebx=654789;
0040118B     0FBE81 F2204000 movsx eax,byte ptr ds:[ecx+4020F2] ; eax=lpNameBuf[ecx-1];取第ecx个字符
                                                                ; 与后面结合可知此片循环从最后倒着取字符处理
00401192     4B              dec ebx                            ; ebx=ebx-1;
00401193     6BC3 02         imul eax,ebx,2                     ; eax=ebx*2;
00401196     03D8            add ebx,eax                        ; ebx=ebx+eax;
00401198     4B              dec ebx                            ; ebx=ebx-1;
00401199     49              dec ecx                            ; ecx=ecx-1;
0040119A   ^ 75 EF           jnz short Crackme1.0040118B        ; if(ecx!=0) goto 0040118B;若ecx==0,继续取字符;


0040119C     56              push esi                           ; arg1=esi;
0040119D     53              push ebx                           ; arg2=ebx;
0040119E     68 C7204000     push Crackme1.004020C7             ; lpFmt="BS-%lX-%lu";
004011A3     68 BB214000     push Crackme1.004021BB             ; lpOut=004021BB;
004011A8     E8 6C000000     call <jmp.&USER32.wsprintfA>       ; wsprintf(lpOut,lpFmt,arg2,arg1);
                                                                ;用esi,ebx的值和格式"BS-%lX-%lu"生成正确的注册码放到004021BB
                                                                ;此处可跟踪004021BB得到正确的注册码
004011AD     58              pop eax
004011AE     58              pop eax
004011AF     58              pop eax
004011B0     58              pop eax
004011B1     E8 01000000     call Crackme1.004011B7             ; SubFun004011B7();注册码检验函数
004011B6     C3              retn


;=================================SubFun004011B7()注册码逐位检验函数==================================

                                                                ;以下过程取注册码并逐位验证
                                                                
004011B7     33C9            xor ecx,ecx                        ; ecx=0;
004011B9     6A 32           push 32                            ; nMaxCount=32;最多取50个字符
004011BB     68 57214000     push Crackme1.00402157             ; lpKeyBuf=00402157;注册码取到00402157
004011C0     68 C9000000     push 0C9                           ; nIDDlgItem=C9;(注册码输入控件ID)
004011C5     FF75 08         push dword ptr ss:[ebp+8]          ; hDlg=[ebp+8];
004011C8     E8 5E000000     call <jmp.&USER32.GetDlgItemTextA> ; eax=GetDlgItemTextA(hDlg,nIDDlgItem,lpKeyBuf,nMaxCount);
                                                                ; 取输入的注册码到00402157
004011CD     83F8 00         cmp eax,0
004011D0     74 1D           je short Crackme1.004011EF         ; if(eax==0) goto 004011EF(失败消息);没有输入失败
004011D2     33C9            xor ecx,ecx                        ; ecx=0;
004011D4     0FBE81 57214000 movsx eax,byte ptr ds:[ecx+402157] ; eax=lpKeyBuf[ecx];取注册码第ecx+1个字符
004011DB     0FBE99 BB214000 movsx ebx,byte ptr ds:[ecx+4021BB] ; ebx=lpOut[0];取正确注册码第ecx+1个字符
004011E2     3BC3            cmp eax,ebx
004011E4     75 09           jnz short Crackme1.004011EF        ; if(ebx!=eax) goto 004011EF(失败消息)不相等就失败;
004011E6     83F8 00         cmp eax,0
004011E9     74 19           je short Crackme1.00401204         ; if(eax==0) goto 00401204(成功消息);
                                                                ; 此处可暴破 
                                                                ; 此处作者用eax==0判断字符取完
004011EB     41              inc ecx                            ; ecx=ecx+1;
004011EC   ^ EB E6           jmp short Crackme1.004011D4        ; goto 004011D4(循环比较)继续下一位注册码比较;
004011EE     C3              retn


;========================================注册失败消息================================================

004011EF     6A 10           push 10
004011F1     68 E4204000     push Crackme1.004020E4             ; ASCII "Nope"
004011F6     68 E9204000     push Crackme1.004020E9             ; ASCII "Try again"
004011FB     FF75 08         push dword ptr ss:[ebp+8]
004011FE     E8 34000000     call <jmp.&USER32.MessageBoxA>
00401203     C3              retn


;========================================注册成功消息==================================================

00401204     6A 40           push 40
00401206     68 D2204000     push Crackme1.004020D2             ; ASCII "Solved"
0040120B     68 D9204000     push Crackme1.004020D9             ; ASCII "Well done."
00401210     FF75 08         push dword ptr ss:[ebp+8]
00401213     E8 1F000000     call <jmp.&USER32.MessageBoxA>
00401218     C3              retn


;======================================================================================================


再贴上自己的python代码:

def zhuceji(usrname):unamelen=len(usrname)esi=0for i in range(unamelen):eax=ord(usrname[i])if eax != 32:eax=eax*4esi=eax+esiebx=0x654789print "%x" %ebxfor i in range(unamelen):ebx=ebx-1ebx+=ebx*2-1print "%x" %ebxebx=0xFFFFFFFF & ebx  #只取ebx的后面八位print 'BS-%08X-%d' %(ebx,esi)while(1):usrname=raw_input("input usrname:")zhuceji(usrname)


0 0
原创粉丝点击