cnpaf.net - 中国协议分析网

投递文章 投稿指南 RSS订阅 网站通告:
搜索: 您的位置主页>网络安全>工具使用>阅读文章

万能五笔2001注册码分析及暴力破解 上

12-20 13:42 来源: 作者: 【 评论:0 浏览:
  此软件比较复杂,未注册前,给出注册框,并限定了使用次数,使用两百次之后,不能继续使用,哪怕是输入正确的注册码也不行,重装也不行。输入注册码之后,软件退出,在每次启动时都要重新判断注册码正确与否。   
    它在注册时采用了从电脑获取电脑码,并将输入的注册码进行计算,算得的值同电脑码进行比较,相等则表示注册正确。由于每台电脑的电脑码不同,保证了一个注册码只能够用于同一台电脑。
    若用注册机的方法进行注册,由于在某些用户的机子上,已经超过了使用次数。这时注册已经晚了。所以没办法,最后还是采取暴力破解更可行。
    在注册方面,作者设置了很多的障碍:输入的注册码有固定的前四位和后四位,只有中间的几位才参与计算;在程序入口,也设置了相当多的障碍,加了许多的判断,让我几乎迷失在无穷的跳转中,即使在子程序也加入了跳转。最后很无赖,只好跟踪正确注册的程序,才找到正确的路径。
    写的有点长,对不起大家。
 
以下是对注册码的分析,然后是再对其进行暴力破解
运行TRW,装入!WNM,在出现对话框时,下BPX HMEMCPY,大家都是成年人,不用我说得太具体吧。
跟踪到以下代码:


016F:0048CB74  MOV      EDX,[00496D34]    此处存的是“tt98 0615"     
016F:0048CB7A  MOVSX    EAX,CX
016F:0048CB7D  MOV      DL,[EDX+EAX]      依次取出8,9,t,t
016F:0048CB80  CMP      DL,3F
016F:0048CB83  JZ      0048CB8B
016F:0048CB85  CMP      [ESP+EAX+1C],DL    依次输入的注册码的第4,3,2,1位
016F:0048CB89  JNZ      0048CB8F
016F:0048CB8B  DEC      CX
016F:0048CB8D  JNS      0048CB74          以上为比较前面四个字节是否为 tt98
016F:0048CB8F  CMP      CX,BYTE -01
016F:0048CB93  JNZ      0048CB9A
016F:0048CB95  MOV      EBP,01            =1  可能表示首四位是正确的
016F:0048CB9A  MOV      EDI,[00496CBC]    为 "0615"
016F:0048CBA0  MOV      ECX,FFFFFFFF       
016F:0048CBA5  SUB      EAX,EAX
016F:0048CBA7  REPNE SCASB
016F:0048CBA9  NOT      ECX               
016F:0048CBAB  DEC      ECX                算出为4位
016F:0048CBAC  LEA      EDI,[ESP+1C]      为输入的注册码
016F:0048CBB0  MOV      DX,CX
016F:0048CBB3  SUB      EAX,EAX
016F:0048CBB5  MOV      ECX,FFFFFFFF
016F:0048CBBA  REPNE SCASB
016F:0048CBBC  NOT      ECX         
016F:0048CBBE  DEC      ECX                算出输入的注册码位数
016F:0048CBBF  SUB      CX,DX              减去4位
016F:0048CBC2  TEST    CX,CX
016F:0048CBC5  JNG      0048CBF6
016F:0048CBC7  XOR      SI,SI
016F:0048CBCA  TEST    DX,DX
016F:0048CBCD  JNG      0048CBF0
016F:0048CBCF  MOV      EAX,[00496CBC]  存的是0615的地址
016F:0048CBD4  MOVSX    EDI,SI
016F:0048CBD7  MOV      AL,[EAX+EDI]    0615中的0
016F:0048CBDA  CMP      AL,3F            小于F
016F:0048CBDC  JZ      0048CBE9
016F:0048CBDE  MOVSX    EBX,CX
016F:0048CBE1  ADD      EBX,EDI
016F:0048CBE3  CMP      [ESP+EBX+1C],AL
016F:0048CBE7  JNZ      0048CBF0
016F:0048CBE9  INC      SI
016F:0048CBEB  CMP      DX,SI
016F:0048CBEE  JG      0048CBCF        以上几行比较后四位是否为0615
016F:0048CBF0  CMP      DX,SI
016F:0048CBF3  JNZ      0048CBF6
016F:0048CBF5  INC      EBP              由48CB95,可知道 EBP=2,可能表示首四位和末四位都正确
016F:0048CBF6  CMP      EBP,BYTE +02
016F:0048CBF9  JZ      0048CC05        跳到下面,

016F:0048CBFB  MOV      EBP,FFFFFFFE
016F:0048CC00  JMP      0048CD05

016F:0048CC05  MOV      EDI,[00496D34]      此处存的是“tt98 0615"
016F:0048CC0B  MOV      ECX,FFFFFFFF       
016F:0048CC10  SUB      EAX,EAX
016F:0048CC12  REPNE SCASB
016F:0048CC14  NOT      ECX                  ecx=5,这几行好像没什么用
016F:0048CC16  SUB      EAX,EAX
016F:0048CC18  LEA      ESI,[ESP+ECX+1B]  为输入的注册码后的第五位,即tt98后面的一位的地址
016F:0048CC1C  MOV      EDI,ESI           
016F:0048CC1E  MOV      ECX,FFFFFFFF
016F:0048CC23  REPNE SCASB
016F:0048CC25  NOT      ECX                ecx=b,即tt98后面剩余的位数+1,包括0615
016F:0048CC27  MOV      EDI,[00496CBC]      edi为0615地址
016F:0048CC2D  SUB      EAX,EAX           
016F:0048CC2F  LEA      EDX,[ECX-01]        edx=a,即tt98后面剩余的位数           
016F:0048CC32  MOV      ECX,FFFFFFFF
016F:0048CC37  REPNE SCASB
016F:0048CC39  NOT      ECX
016F:0048CC3B  DEC      ECX                ECX=4
016F:0048CC3C  MOV      EAX,ESI         
016F:0048CC3E  SUB      EAX,ECX            即输入的注册码位置               
016F:0048CC40  MOV      ECX,ESI           
016F:0048CC42  MOV      BYTE [EAX+EDX],00  即输入注册码的倒数第四位处,改位0,
                                            以便于下面调用函数判断注册码中部(除tt98和
                                            0165)的位数
016F:0048CC46  CALL    00491A20            !! : 判断输入的字符串是否满足要求,见子程序1
016F:0048CC4B  TEST    EAX,EAX           
016F:0048CC4D  JNZ      0048CC59            eax=1时,正确,跳转
016F:0048CC4F  MOV      EBP,FFFFFFFD
016F:0048CC54  JMP      0048CD05

016F:0048CC59  MOV      EDX,004930E8        此时存的“0604”字符
016F:0048CC5E  MOV      ECX,ESI            ESI为中间注册码首位地址
016F:0048CC60  MOV      EBP,FFFFFFFC
016F:0048CC65  CALL    00491A70            将其由字符串转换成二进制的数,见子程序2
016F:0048CC6A  CMP      WORD [00496D28],BYTE +01
016F:0048CC72  MOV      ESI,EAX
016F:0048CC74  JNZ      0048CCCF

016F:0048CC76  MOV      DI,[00496D2E]
016F:0048CC7D  MOV      EDX,[00496CB0]
016F:0048CC83  SHR      DI,08
016F:0048CC87  MOV      CX,[00496D2E]
016F:0048CC8E  AND      CX,FF
016F:0048CC93  CALL    0048C790
016F:0048CC98  ADD      ESI,EAX
016F:0048CC9A  TEST    DI,DI
016F:0048CC9D  JNZ      0048CCA9
016F:0048CC9F  MOV      EDX,[00496CB4]
016F:0048CCA5  MOV      ECX,EDI
016F:0048CCA7  JMP      SHORT 0048CCB4
016F:0048CCA9  MOV      CX,DI
016F:0048CCAC  MOV      EDX,[00496CB4]
016F:0048CCB2  INC      CX
016F:0048CCB4  CALL    0048C790
016F:0048CCB9  MOV      ECX,EAX
016F:0048CCBB  TEST    ECX,ECX
016F:0048CCBD  JNZ      0048CCC6
016F:0048CCBF  MOV      EBP,FFFFFFFB
016F:0048CCC4  JMP      SHORT 0048CCFC
016F:0048CCC6  MOV      EAX,ESI
016F:0048CCC8  CDQ   
016F:0048CCC9  IDIV    ECX
016F:0048CCCB  MOV      EBP,EDX
016F:0048CCCD  JMP      SHORT 0048CCFC

016F:0048CCCF  CMP      WORD [00496D28],BYTE +02
016F:0048CCD7  JNZ      0048CCFC
016F:0048CCD9  MOV      DX,[00496D2E]      存的是 63 64,即6463
016F:0048CCE0  MOV      EAX,[00496CB4]      输入的注册人名地址
016F:0048CCE5  PUSH    EAX
016F:0048CCE6  MOV      ECX,[00496CB0]      也是 输入的注册人名地址
016F:0048CCEC  PUSH    ECX
016F:0048CCED  MOV      ECX,[00496AC4]      取出17EF7,十进制为98039,即我机子上的电脑码
016F:0048CCF3  CALL    0048C820            是由注册人名和电脑码算出一个数值
                                            !!! 若将此值换算成十进制,即为正确的中间注册码
016F:0048CCF8  MOV      EBP,EAX           
016F:0048CCFA  SUB      EBP,ESI           
016F:0048CCFC  TEST    EBP,EBP     
016F:0048CCFE  JZ      0048CD29            !!!  此值与原算得的二进制数比较,
                                                相等表示输入的注册码正确,应跳转

016F:0048CD00  MOV      EBP,FFFFFFFB       
016F:0048CD05  TEST    EBP,EBP
016F:0048CD07  JNL      0048CD29           
016F:0048CD09  INC      WORD [ESP+12]         
016F:0048CD0E  MOV      AX,[ESP+12]
016F:0048CD13  CMP      [00496D38],AX
016F:0048CD1A  JG      NEAR 0048C913
016F:0048CD20  JMP      SHORT 0048CD29
016F:0048CD22  MOV      EBP,[ESP+84]

016F:0048CD29  XOR      ESI,ESI           
016F:0048CD2B  TEST    EBP,EBP
016F:0048CD2D  JL      NEAR 0048CE08        若注册码正确,不跳
016F:0048CD33  MOV      AX,[ESP+12]       
016F:0048CD38  CMP      [00496D38],AX
016F:0048CD3F  JNG      NEAR 0048CE08
016F:0048CD45  MOV      EDX,01
016F:0048CD4A  MOV      ECX,[ESP+12]
016F:0048CD4E  CALL    0048C4C0            此处是判断是否过时,若过时,即使注册码对,也不能用   
016F:0048CD53  TEST    EAX,EAX
016F:0048CD55  JZ      0048CDCD            过时则不跳转,应跳转
016F:0048CD57  PUSH    DWORD 1010
016F:0048CD5C  MOV      EBX,[00496D3C]
016F:0048CD62  MOVSX    EAX,WORD [ESP+16]
016F:0048CD67  SHL      EAX,02
016F:0048CD6A  PUSH    DWORD 004930E0
016F:0048CD6F  LEA      ECX,[EAX+EAX*2]
016F:0048CD72  LEA      EDX,[ECX+ECX*4]
016F:0048CD75  MOV      ECX,[ESP+1C]
016F:0048CD79  MOV      EAX,[EDX+EBX+34]
016F:0048CD7D  PUSH    EAX
016F:0048CD7E  PUSH    ECX
016F:0048CD7F  CALL    `USER32!MessageBoxA`      出现过时框
016F:0048CD85  MOV      ECX,[ESP+14]
016F:0048CD89  PUSH    DWORD 1001
016F:0048CD8E  PUSH    ECX
016F:0048CD8F  CALL    `USER32!GetDlgItem`
016F:0048CD95  MOV      ECX,EAX
016F:0048CD97  CALL    0048B910
016F:0048CD9C  MOV      [00496A5E],SI
016F:0048CDA3  PUSH    ESI
016F:0048CDA4  MOV      [004931C0],SI
016F:0048CDAB  PUSH    DWORD 8002
016F:0048CDB0  PUSH    DWORD 0111
016F:0048CDB5  MOV      ECX,[00496C80]
016F:0048CDBB  PUSH    ECX
016F:0048CDBC  CALL    `USER32!SendMessageA`
016F:0048CDC2  POP      EBP
016F:0048CDC3  POP      EDI
016F:0048CDC4  POP      ESI
016F:0048CDC5  POP      EBX
016F:0048CDC6  ADD      ESP,A8
016F:0048CDCC  RET   

016F:0048CDCD  MOV      EAX,[ESP+14]
016F:0048CDD1  MOV      ECX,[00496C80]
016F:0048CDD7  MOV      BYTE [00496AB3],02
016F:0048CDDE  PUSH    EAX
016F:0048CDDF  PUSH    DWORD 8000
016F:0048CDE4  PUSH    DWORD 0111
016F:0048CDE9  PUSH    ECX
016F:0048CDEA  CALL    `USER32!SendMessageA`
016F:0048CDF0  MOV      ECX,[ESP+14]
016F:0048CDF4  PUSH    BYTE +01
016F:0048CDF6  PUSH    ECX
016F:0048CDF7  CALL    `USER32!EndDialog`
016F:0048CDFD  POP      EBP
016F:0048CDFE  POP      EDI
016F:0048CDFF  POP      ESI
016F:0048CE00  POP      EBX
016F:0048CE01  ADD      ESP,A8
016F:0048CE07  RET   








子程序1


016F:00491A20  PUSH    ESI                 
016F:00491A21  MOV      EDX,ECX        edx,ecx为注册码中间部分的起始地址
016F:00491A23  PUSH    EDI
016F:00491A24  XOR      ESI,ESI       
016F:00491A26  MOV      EDI,EDX        edi为注册码中间部分的起始地址
016F:00491A28  MOV      ECX,FFFFFFFF
016F:00491A2D  SUB      EAX,EAX
016F:00491A2F  REPNE SCASB
016F:00491A31  NOT      ECX         
016F:00491A33  DEC      ECX            中间部分的位数
016F:00491A34  TEST    ECX,ECX     
016F:00491A36  JNG      00491A56      位数小于1,跳转,但不出错;位数大于1,不跳
          以下循环判断中间注册码是否满足条件
016F:00491A38  MOV      AL,[EDX+ESI]  取出字符
016F:00491A3B  CMP      AL,30
016F:00491A3D  JC      00491A5E
016F:00491A3F  CMP      AL,39
016F:00491A41  JA      00491A5E      是否在0~9之间,不再,则出错输出EAX=0
016F:00491A43  INC      ESI   
016F:00491A44  MOV      EDI,EDX
016F:00491A46  MOV      ECX,FFFFFFFF
016F:00491A4B  SUB      EAX,EAX
016F:00491A4D  REPNE SCASB
016F:00491A4F  NOT      ECX
016F:00491A51  DEC      ECX
016F:00491A52  CMP      ECX,ESI
016F:00491A54  JG      00491A38      循环判断
016F:00491A56  MOV      EAX,01        正确,输出EAX=1
016F:00491A5B  POP      EDI
016F:00491A5C  POP      ESI
016F:00491A5D  RET   
016F:00491A5E  XOR      EAX,EAX
016F:00491A60  POP      EDI
016F:00491A61  POP      ESI
016F:00491A62  RET   








子程序2


016F:00491A70  SUB      ESP,BYTE +08 
016F:00491A73  MOV      [ESP+04],EDX        0604字符串
016F:00491A77  PUSH    EBX
016F:00491A78  MOV      DWORD [ESP+04],00
016F:00491A80  PUSH    ESI
016F:00491A81  PUSH    EDI
016F:00491A82  PUSH    EBP
016F:00491A83  MOV      ESI,01
016F:00491A88  PUSH    ECX
016F:00491A89  MOV      EBP,ECX              ESI为中间注册码首位地址
016F:00491A8B  CALL    `KERNEL32!lstrlenA`  求出中间注册码长度
016F:00491A91  LEA      EDI,[EAX-01]          EDI=长度-1
016F:00491A94  TEST    EDI,EDI
016F:00491A96  JL      00491AD3              长度大于0则不跳,否则出错
                                       
                                      以下循环       
016F:00491A98  MOV      BL,[EBP+EDI+00]      依次取出中间注册码末位,末位-1,......
016F:00491A9C  CMP      BL,30
016F:00491A9F  JC      00491AAA
016F:00491AA1  CMP      BL,39
016F:00491AA4  JA      00491AAA              是否在0~9之间
016F:00491AA6  TEST    EDI,EDI     
016F:00491AA8  JNL      00491AB8            肯定要跳
016F:00491AAA  MOV      ECX,00493504
016F:00491AAF  MOV      EDX,[ESP+14]
016F:00491AB3  CALL    00491600

016F:00491AB8  XOR      EAX,EAX
016F:00491ABA  LEA      ECX,[ESI+ESI*4]      由491A83知,esi开始1,算得ECX=5,以后依次esi*10,即10,100,1000.....
016F:00491ABD  MOV      AL,BL
016F:00491ABF  SUB      EAX,BYTE +30        将此字符转换成二进制数
016F:00491AC2  IMUL    EAX,ESI             
016F:00491AC5  LEA      ESI,[ECX*2+`DOSMGR_BackFill_Allowed`] 
                                            DOSMGR_BackFill_Allowed=0
                                            算得ESI=10
016F:00491ACC  ADD      [ESP+10],EAX        原来的字符
016F:00491AD0  DEC      EDI
016F:00491AD1  JNS      00491A98            循环,直至所有的字符 

016F:00491AD3  MOV      EAX,[ESP+10]          由上面的分析,可知此子程序将输入中间注册码
016F:00491AD7  POP      EBP                                  由字符串转换成二进制的数
016F:00491AD8  POP      EDI
016F:00491AD9  POP      ESI
016F:00491ADA  POP      EBX
016F:00491ADB  ADD      ESP,BYTE +08
016F:00491ADE  RET   


总结一下,以上代码将输入的注册码进行判断,首先看注册码的起始和结尾的固定码是否正确,若正确判断中间注册码是否满足一定要求。然后取出本机的电脑码,由其算出正确的注册码。
关键点:
在48ccf3处,算出正确的注册码(要转换成十进制才能看到)
在48ccfe处与输入的注册码进行比较。

上面的这一段,其实是我的失败经验。因为我不知怎么乱搞,把注册次数搞成了0次,这下即使得到注册码也没用了,只好用暴力法破解。


分析文件入口处的代码:


016F:0048E01D  MOV      ECX,01
016F:0048E022  CALL    00490AA0                      取得电脑信息码98039
016F:0048E027  XOR      EAX,EAX
016F:0048E029  MOV      AX,[00496D32]                 
016F:0048E02F  TEST    AH,C0                          ah=f0
016F:0048E032  JNZ      NEAR 0048E066                  应该跳转

016F:0048E038  XOR      EAX,EAX
016F:0048E03A  MOV      AX,[00496D32]
016F:0048E040  TEST    AH,10
016F:0048E043  JZ      NEAR 0048E066                [496d32]=10 表示次数已用完
016F:0048E049  PUSH    BYTE +00
016F:0048E04B  PUSH    DWORD 8003
016F:0048E050  PUSH    DWORD 0111
016F:0048E055  MOV      EAX,[00496C80]
016F:0048E05A  PUSH    EAX
016F:0048E05B  CALL    `USER32!SendMessageA`          次数已用完错误框
016F:0048E061  JMP      0048E06B

016F:0048E066  CALL    0048E680
016F:0048E06B  CMP      DWORD [00493170],BYTE +00
016F:0048E072  JZ      NEAR 0048E08E
016F:0048E078  MOV      ECX,[EBP-50]
016F:0048E07B  CALL    00490CC0                      若注册表中的注册码不对,显示开始的注册框,里面又有跳转见子程序3,要改
016F:0048E080  MOV      [EBP-50],EAX
016F:0048E083  MOV      ECX,[EBP-50]
016F:0048E086  CALL    00490D80                      若注册码正确,即显示正确框,里面有跳转,见子程序4,要改
016F:0048E08B  MOV      [EBP-50],EAX
016F:0048E08E  CMP      DWORD [EBP-50],BYTE +01
016F:0048E092  JNZ      NEAR 0048E0BF
016F:0048E098  XOR      EAX,EAX
016F:0048E09A  MOV      AX,[004931B8]
016F:0048E0A0  TEST    EAX,EAX
016F:0048E0A2  JZ      NEAR 0048E0BF
016F:0048E0A8  XOR      EAX,EAX
016F:0048E0AA  MOV      AX,[00496A9F]
016F:0048E0B0  TEST    EAX,EAX
016F:0048E0B2  JZ      NEAR 0048E0BF
016F:0048E0B8  DEC      WORD [00496A9F]
016F:0048E0BF  CMP      DWORD [EBP-50],BYTE +01
016F:0048E0C3  JNZ      NEAR 0048E1D5
016F:0048E0C9  XOR      EAX,EAX
016F:0048E0CB  MOV      AX,[004931B8]
016F:0048E0D1  TEST    EAX,EAX
016F:0048E0D3  JZ      NEAR 0048E1D5
016F:0048E0D9  XOR      EAX,EAX
016F:0048E0DB  MOV      AX,[0049317C]
016F:0048E0E1  TEST    AL,02
016F:0048E0E3  JNZ      NEAR 0048E107
016F:0048E0E9  CMP      DWORD [00493178],BYTE +00
016F:0048E0F0  JZ      NEAR 0048E107                  应该跳转

016F:0048E0F6  XOR      EAX,EAX
016F:0048E0F8  MOV      AX,[0049317C]
016F:0048E0FE  OR      EAX,BYTE +02
016F:0048E101  MOV      [0049317C],AX
016F:0048E107  XOR      EAX,EAX
016F:0048E109  MOV      AX,[0049317C]
016F:0048E10F  TEST    AL,02
016F:0048E111  JZ      NEAR 0048E146                  应该跳转

016F:0048E117  CALL    00491250
016F:0048E11C  MOV      [004931B8],AX
016F:0048E122  XOR      EAX,EAX
016F:0048E124  MOV      AX,[004931B8]
016F:0048E12A  TEST    EAX,EAX
016F:0048E12C  JNZ      NEAR 0048E146
016F:0048E132  PUSH    BYTE +00
016F:0048E134  PUSH    DWORD 004930B8
016F:0048E139  PUSH    DWORD 004932DC
016F:0048E13E  PUSH    BYTE +00
016F:0048E140  CALL    `USER32!MessageBoxA`            server is full 错误信息

收藏此篇文章内容到:
Tags:
责任编辑:
  • 请文明参与讨论,禁止漫骂攻击。 用户名:新注册) 密码: 匿名:
    评论总数:0 [ 查看全部 ] 网友评论
    关于我们 - 广告合作 - 网站地图 - 版权说明 - 网站历史 - 世界排名 - 加入收藏 - 设为首页 - 返回顶部