• 标 题:powerarchiver 8.00.58 之不完全破解+简单算法分析
  • 作 者:涩郎
  • 时 间:2003/04/05 09:46pm
  • 链 接:http://bbs.pediy.com

软件名称: powerarchiver 8.00.58
软件简介:  超强的文件压缩解压缩工具,有点像WINZIP,但比WINZIP强大,支持更多的格式.
下载地址:  http://www.powerarchiver.com/
此文目的: 学习该软件的注册码生成方法
调试工具: ollydbg1.09中文版、W32dsm9.0中文版、language
调试平台: Windows XP (哈哈,ollydbg真好,XP下也能调试了,想想吧,还有MP3)

过程:
1)  运行程序,按CTRL+HOME输入NAME和REGISTRATION CODE,程序弹出对话框:Incomplete or incorrect information,关闭程序.

2)  使用 language 检测主程序“POWERARC.exe”,没有壳.

3)  用W32dasm反编译POWERARC.exe,然后查找字符串"Incomplete or incorrect information" 双击找到的字符串,来到以下地方:
   走到005E5E23时弹出出错对话框,于是向上看,发现005E5DBF有一个跳转,于是在005E5CC4处设断.

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:005E5D79(C), :005E5D93(C), :005E5DA4(C)
|
:005E5DB2 8B55F8                  mov edx, dword ptr [ebp-08]         <------输入的REGISTRATION CODE
:005E5DB5 8B45FC                  mov eax, dword ptr [ebp-04]         <------输入的NAME
:005E5DB8 E807FFFFFF              call 005E5CC4
:005E5DBD 84C0                    test al, al
:005E5DBF 0F859D000000            jne 005E5E62
:005E5DC5 FE050C93BD00            inc byte ptr [00BD930C]
:005E5DCB A12C986800              mov eax, dword ptr [0068982C]
:005E5DD0 8B55FC                  mov edx, dword ptr [ebp-04]
:005E5DD3 E848EBE1FF              call 00404920
:005E5DD8 A1BC906800              mov eax, dword ptr [006890BC]
:005E5DDD 8B55F8                  mov edx, dword ptr [ebp-08]
:005E5DE0 E83BEBE1FF              call 00404920
:005E5DE5 A1FC906800              mov eax, dword ptr [006890FC]
:005E5DEA C60000                  mov byte ptr [eax], 00
:005E5DED A1DC926800              mov eax, dword ptr [006892DC]
:005E5DF2 8B00                    mov eax, dword ptr [eax]
:005E5DF4 8B8064060000            mov eax, dword ptr [eax+00000664]
:005E5DFA B201                    mov dl, 01
:005E5DFC E8E3FDE4FF              call 00435BE4
:005E5E01 A1DC926800              mov eax, dword ptr [006892DC]
:005E5E06 8B00                    mov eax, dword ptr [eax]
:005E5E08 8B8068060000            mov eax, dword ptr [eax+00000668]
:005E5E0E B201                    mov dl, 01
:005E5E10 E8CFFDE4FF              call 00435BE4
:005E5E15 668B0D545F5E00          mov cx, word ptr [005E5F54]
:005E5E1C B201                    mov dl, 01

* Possible StringData Ref from Code Obj ->"Incomplete or incorrect information."
                                 |
:005E5E1E B8605F5E00              mov eax, 005E5F60
:005E5E23 E878650500              call 0063C3A0
:005E5E28 A1AC916800              mov eax, dword ptr [006891AC]
:005E5E2D 833800                  cmp dword ptr [eax], 00000000
:005E5E30 7517                    jne 005E5E49
:005E5E32 A1DC926800              mov eax, dword ptr [006892DC]
:005E5E37 8B00                    mov eax, dword ptr [eax]
:005E5E39 8B809C030000            mov eax, dword ptr [eax+0000039C]

* Possible StringData Ref from Code Obj ->"PowerArchiver 2002 v8.00 (Unregistered)"
                                 |
:005E5E3F BA905F5E00              mov edx, 005E5F90
:005E5E44 E8B3FEE4FF              call 00435CFC

(略)

* Possible StringData Ref from Code Obj ->"Registration accepted! Thank you "
                                       ->"for purchasing PowerArchiver."
                                 |
:005E5EEC B8C05F5E00              mov eax, 005E5FC0
:005E5EF1 E8AA640500              call 0063C3A0
:005E5EF6 A1AC916800              mov eax, dword ptr [006891AC]
:005E5EFB 833800                  cmp dword ptr [eax], 00000000
:005E5EFE 7517                    jne 005E5F17
:005E5F00 A1DC926800              mov eax, dword ptr [006892DC]
:005E5F05 8B00                    mov eax, dword ptr [eax]
:005E5F07 8B809C030000            mov eax, dword ptr [eax+0000039C]

* Possible StringData Ref from Code Obj ->"PowerArchiver 2002 v8.00"
                                 |
:005E5F0D BA08605E00              mov edx, 005E6008
:005E5F12 E8E5FDE4FF              call 00435CFC


4) 使用ollydbg载入POWERARC.exe在005E5CC4处设置断点,F9运行程序,输入name and regcode 点OK中断于此

* Referenced by a CALL at Address:
|:005E5DB8  
|
:005E5CC4 55                      push ebp
:005E5CC5 8BEC                    mov ebp, esp
:005E5CC7 83C4F4                  add esp, FFFFFFF4
:005E5CCA 53                      push ebx
:005E5CCB 33C9                    xor ecx, ecx
:005E5CCD 894DF4                  mov dword ptr [ebp-0C], ecx
:005E5CD0 8955F8                  mov dword ptr [ebp-08], edx
:005E5CD3 8945FC                  mov dword ptr [ebp-04], eax
:005E5CD6 8B45FC                  mov eax, dword ptr [ebp-04]
:005E5CD9 E85AF0E1FF              call 00404D38
:005E5CDE 8B45F8                  mov eax, dword ptr [ebp-08]
:005E5CE1 E852F0E1FF              call 00404D38
:005E5CE6 33C0                    xor eax, eax
:005E5CE8 55                      push ebp
:005E5CE9 682D5D5E00              push 005E5D2D
:005E5CEE 64FF30                  push dword ptr fs:[eax]
:005E5CF1 648920                  mov dword ptr fs:[eax], esp
:005E5CF4 8D55F4                  lea edx, dword ptr [ebp-0C]
:005E5CF7 8B45FC                  mov eax, dword ptr [ebp-04]   <------输入的NAME
:005E5CFA E8E5AB0800              call 006708E4
:005E5CFF 8B55F4                  mov edx, dword ptr [ebp-0C]   <------正确的regcode
:005E5D02 8B45F8                  mov eax, dword ptr [ebp-08]   <------输入的regcode
:005E5D05 E88AEFE1FF              call 00404C94
:005E5D0A 7504                    jne 005E5D10
:005E5D0C B301                    mov bl, 01
:005E5D0E EB02                    jmp 005E5D12

(略)

按F8一步步跟踪,在005E5CF7处发现输入的NAME,同时在005E5CFF发现正确的regcode,直觉告诉我005E5CFA的CALL是计算注册码的,于是跟入.
而且在005E5CFF发现一个经典对比:
:005E5CFF 8B55F4                  mov edx, dword ptr [ebp-0C]
:005E5D02 8B45F8                  mov eax, dword ptr [ebp-08]
:005E5D05 E88AEFE1FF              call 00404C94
:005E5D0A 7504                    jne 005E5D10

跟入005E5CFA来到此地:

* Referenced by a CALL at Addresses:
|:005E5CFA   , :0067681F  
|
:006708E4 55                      push ebp
:006708E5 8BEC                    mov ebp, esp
:006708E7 81C4CCFDFFFF            add esp, FFFFFDCC
:006708ED 53                      push ebx
:006708EE 56                      push esi
:006708EF 57                      push edi
:006708F0 33C9                    xor ecx, ecx
:006708F2 898DD0FDFFFF            mov dword ptr [ebp+FFFFFDD0], ecx
:006708F8 898DCCFDFFFF            mov dword ptr [ebp+FFFFFDCC], ecx
:006708FE 898DDCFDFFFF            mov dword ptr [ebp+FFFFFDDC], ecx
:00670904 898DD8FDFFFF            mov dword ptr [ebp+FFFFFDD8], ecx
:0067090A 898DE0FDFFFF            mov dword ptr [ebp+FFFFFDE0], ecx
:00670910 894DF0                  mov dword ptr [ebp-10], ecx
:00670913 8955F8                  mov dword ptr [ebp-08], edx
:00670916 8945FC                  mov dword ptr [ebp-04], eax
:00670919 8B45FC                  mov eax, dword ptr [ebp-04]
:0067091C E81744D9FF              call 00404D38
:00670921 33C0                    xor eax, eax
:00670923 55                      push ebp
:00670924 68330B6700              push 00670B33
:00670929 64FF30                  push dword ptr fs:[eax]
:0067092C 648920                  mov dword ptr fs:[eax], esp

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:006708BD(C)
|

* Possible StringData Ref from Code Obj ->"IP-POWERARC"
                                 |
:0067092F BE440B6700              mov esi, 00670B44
:00670934 8DBDECFEFFFF            lea edi, dword ptr [ebp+FFFFFEEC]
:0067093A A5                      movsd
:0067093B A5                      movsd
:0067093C A5                      movsd
:0067093D 8D85ECFDFFFF            lea eax, dword ptr [ebp+FFFFFDEC]
:00670943 8B55FC                  mov edx, dword ptr [ebp-04]
:00670946 B9FF000000              mov ecx, 000000FF
:0067094B E81042D9FF              call 00404B60
:00670950 33C0                    xor eax, eax
:00670952 8A85ECFEFFFF            mov al, byte ptr [ebp+FFFFFEEC]
:00670958 8945F4                  mov dword ptr [ebp-0C], eax
:0067095B 33FF                    xor edi, edi
:0067095D BE03140000              mov esi, 00001403                      <-----ESI=1403(H)=5123(O)
:00670962 8D45F0                  lea eax, dword ptr [ebp-10]
:00670965 50                      push eax
:00670966 89B5E4FDFFFF            mov dword ptr [ebp+FFFFFDE4], esi
:0067096C C685E8FDFFFF00          mov byte ptr [ebp+FFFFFDE8], 00
:00670973 8D95E4FDFFFF            lea edx, dword ptr [ebp+FFFFFDE4]
:00670979 33C9                    xor ecx, ecx

* Possible StringData Ref from Code Obj ->"%1.2x"
                                 |
:0067097B B8580B6700              mov eax, 00670B58
:00670980 E89BBBD9FF              call 0040C520
:00670985 33C0                    xor eax, eax
:00670987 8A85ECFDFFFF            mov al, byte ptr [ebp+FFFFFDEC]
:0067098D 85C0                    test eax, eax
:0067098F 7E6B                    jle 006709FC
:00670991 8945EC                  mov dword ptr [ebp-14], eax
:00670994 8D9DEDFDFFFF            lea ebx, dword ptr [ebp+FFFFFDED]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:006709FA(C)
|
:0067099A 33C0                    xor eax, eax
:0067099C 8A03                    mov al, byte ptr [ebx]           <-----用户名依次ASC()入AL
:0067099E 03C6                    add eax, esi                     <-----EAX=EAX+ESI
:006709A0 B9FF000000              mov ecx, 000000FF                <-----ECX=FF(H)=255(O)
:006709A5 99                      cdq
:006709A6 F7F9                    idiv ecx                         <-----除法运算
:006709A8 8BF2                    mov esi, edx                     <-----ESI=EAX MOD ECX (EAX除以ECX的余数入ESI)
:006709AA 3B7DF4                  cmp edi, dword ptr [ebp-0C]      <-----检查是否超出"IP-POWERARC"的长度,保证程序取其中的字符
:006709AD 7D03                    jge 006709B2                     <-----大于等于就跳
:006709AF 47                      inc edi                          <-----否则EDI=EDI+1
:006709B0 EB05                    jmp 006709B7

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:006709AD(C)
|
:006709B2 BF01000000              mov edi, 00000001                 <-----如果EDI超出"IP-POWERARC"的长度,则EDI=1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:006709B0(U)
|
:006709B7 33C0                    xor eax, eax
:006709B9 8A843DECFEFFFF          mov al, byte ptr [ebp+edi-00000114]   <----"IP-POWERARC"指定位置的字符依次ASC()入AL
:006709C0 33F0                    xor esi, eax                          <---- ESI=ESI XOR EAX
:006709C2 8D85E0FDFFFF            lea eax, dword ptr [ebp+FFFFFDE0]
:006709C8 50                      push eax
:006709C9 89B5E4FDFFFF            mov dword ptr [ebp+FFFFFDE4], esi
:006709CF C685E8FDFFFF00          mov byte ptr [ebp+FFFFFDE8], 00
:006709D6 8D95E4FDFFFF            lea edx, dword ptr [ebp+FFFFFDE4]
:006709DC 33C9                    xor ecx, ecx

* Possible StringData Ref from Code Obj ->"%1.2x"
                                 |
:006709DE B8580B6700              mov eax, 00670B58
:006709E3 E838BBD9FF              call 0040C520
:006709E8 8B95E0FDFFFF            mov edx, dword ptr [ebp+FFFFFDE0]    <---- EDX=ESI(ESI的值作为字符串付给EDX.可能这个功能,因

为我是汇编盲)
:006709EE 8D45F0                  lea eax, dword ptr [ebp-10]
:006709F1 E89641D9FF              call 00404B8C
:006709F6 43                      inc ebx
:006709F7 FF4DEC                  dec [ebp-14]
:006709FA 759E                    jne 0067099A                         <------下一循环

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0067098F(C)                                                     <----此处向下的程序功能是在字符串中取字符,因为我是汇编盲    
|                                                                      具体方法也不是太清楚,只是靠猜的,好像是从最后开始向前
                                                                      两个一组在下面这段字串中取字符,还请哪个大侠不吝赐教
:006709FC 8B45F0                  mov eax, dword ptr [ebp-10]  <---NAME经处理后形成的字符串,也就是每次运算后的字符串联接起来
:006709FF E88041D9FF              call 00404B84
:00670A04 8BF0                    mov esi, eax
:00670A06 85F6                    test esi, esi
:00670A08 7903                    jns 00670A0D
:00670A0A 83C603                  add esi, 00000003

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00670A08(C)
|
:00670A0D C1FE02                  sar esi, 02
:00670A10 C685ECFDFFFF00          mov byte ptr [ebp+FFFFFDEC], 00
:00670A17 BB01000000              mov ebx, 00000001

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00670AE1(C)
|
:00670A1C 8D85DCFDFFFF            lea eax, dword ptr [ebp+FFFFFDDC]
:00670A22 8D95ECFDFFFF            lea edx, dword ptr [ebp+FFFFFDEC]
:00670A28 E8FB40D9FF              call 00404B28
:00670A2D 8D85DCFDFFFF            lea eax, dword ptr [ebp+FFFFFDDC]
:00670A33 50                      push eax
:00670A34 8D85D4FDFFFF            lea eax, dword ptr [ebp+FFFFFDD4]
:00670A3A 8BFB                    mov edi, ebx
:00670A3C 0FAFFE                  imul edi, esi
:00670A3F 8B55F0                  mov edx, dword ptr [ebp-10]
:00670A42 8A543AFF                mov dl, byte ptr [edx+edi-01]
:00670A46 885001                  mov byte ptr [eax+01], dl
:00670A49 C60001                  mov byte ptr [eax], 01
:00670A4C 8D95D4FDFFFF            lea edx, dword ptr [ebp+FFFFFDD4]
:00670A52 8D85D8FDFFFF            lea eax, dword ptr [ebp+FFFFFDD8]
:00670A58 E8CB40D9FF              call 00404B28
:00670A5D 8B95D8FDFFFF            mov edx, dword ptr [ebp+FFFFFDD8]
:00670A63 58                      pop eax
:00670A64 E82341D9FF              call 00404B8C
:00670A69 8B95DCFDFFFF            mov edx, dword ptr [ebp+FFFFFDDC]
:00670A6F 8D85ECFDFFFF            lea eax, dword ptr [ebp+FFFFFDEC]
:00670A75 B9FF000000              mov ecx, 000000FF
:00670A7A E8E140D9FF              call 00404B60
:00670A7F 8D85D0FDFFFF            lea eax, dword ptr [ebp+FFFFFDD0]
:00670A85 8D95ECFDFFFF            lea edx, dword ptr [ebp+FFFFFDEC]
:00670A8B E89840D9FF              call 00404B28
:00670A90 8D85D0FDFFFF            lea eax, dword ptr [ebp+FFFFFDD0]
:00670A96 50                      push eax
:00670A97 8D85D4FDFFFF            lea eax, dword ptr [ebp+FFFFFDD4]
:00670A9D 8B55F0                  mov edx, dword ptr [ebp-10]
:00670AA0 8A543AFE                mov dl, byte ptr [edx+edi-02]
:00670AA4 885001                  mov byte ptr [eax+01], dl
:00670AA7 C60001                  mov byte ptr [eax], 01
:00670AAA 8D95D4FDFFFF            lea edx, dword ptr [ebp+FFFFFDD4]
:00670AB0 8D85CCFDFFFF            lea eax, dword ptr [ebp+FFFFFDCC]
:00670AB6 E86D40D9FF              call 00404B28
:00670ABB 8B95CCFDFFFF            mov edx, dword ptr [ebp+FFFFFDCC]
:00670AC1 58                      pop eax
:00670AC2 E8C540D9FF              call 00404B8C
:00670AC7 8B95D0FDFFFF            mov edx, dword ptr [ebp+FFFFFDD0]
:00670ACD 8D85ECFDFFFF            lea eax, dword ptr [ebp+FFFFFDEC]
:00670AD3 B9FF000000              mov ecx, 000000FF                    
:00670AD8 E88340D9FF              call 00404B60                        
:00670ADD 43                      inc ebx                              
:00670ADE 83FB05                  cmp ebx, 00000005                    
:00670AE1 0F8535FFFFFF            jne 00670A1C                     <-----此处与00670A1C之间的代码不是太清楚望各位大侠指教
:00670AE7 8B45F8                  mov eax, dword ptr [ebp-08]
:00670AEA 8D95ECFDFFFF            lea edx, dword ptr [ebp+FFFFFDEC]    <-----此处可见正确的注册码
:00670AF0 E83340D9FF              call 00404B28
:00670AF5 33C0                    xor eax, eax
:00670AF7 5A                      pop edx
:00670AF8 59                      pop ecx
:00670AF9 59                      pop ecx
:00670AFA 648910                  mov dword ptr fs:[eax], edx
:00670AFD 683A0B6700              push 00670B3A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00670B38(U)
|
:00670B02 8D85CCFDFFFF            lea eax, dword ptr [ebp+FFFFFDCC]
:00670B08 BA02000000              mov edx, 00000002
:00670B0D E8DE3DD9FF              call 004048F0
:00670B12 8D85D8FDFFFF            lea eax, dword ptr [ebp+FFFFFDD8]
:00670B18 BA03000000              mov edx, 00000003
:00670B1D E8CE3DD9FF              call 004048F0
:00670B22 8D45F0                  lea eax, dword ptr [ebp-10]
:00670B25 E8A23DD9FF              call 004048CC
:00670B2A 8D45FC                  lea eax, dword ptr [ebp-04]
:00670B2D E89A3DD9FF              call 004048CC
:00670B32 C3                      ret

说了这么多真是累死了,看来得好好学一下汇编了.还是用粗通的VB来还原这个过程吧,希望大家能看懂
Sub Main()
   On Error Resume Next
   Dim yourname As String, initstr As String, esi As Long
   Dim tmp As String, i As Integer, temp As String
   Dim sn As String
   yourname = Trim(InputBox("请输入注册名,名字太短可能会有错误的结果."+chr(13)+chr(10)+"因为对字符串的筛选方法是猜的"))
   yourname = StrConv(yourname, 128) '因为是VB所以要解决UNICODE问题
   If LenB(yourname) = 0 Then End
   initstr = "IP-POWERARC"
   Do Until LenB(yourname) \ Len(initstr) = 0 '保证initstr的长度大于等于yourname的长度以便计算
       initstr = initstr + "IP-POWERARC"
       DoEvents
   Loop
   esi = &H1403        'esi的初值
   tmp = Hex(esi)
   For i = 1 To LenB(yourname)
       esi = (AscB(MidB(yourname, i, 1)) + esi) Mod &HFF Xor Asc(Mid(initstr, i, 1))
       '每一位依次ASC()后加ESI,然后对255取模,最后与程序内置的一段字符串"IP-POWERARC"的相应位
       '的ASC进行异或
       If esi < 16 Then                '在小于16(也就是小于等于&hF)的数前加"0"
           temp = "0" + Hex(esi)
       Else
           temp = Hex(esi)
       End If
       tmp = tmp + temp
   Next i
   'tmp为程序生成的一串字符,至此应该都是正确的,下面可不敢保证.因为我是汇编盲,以下取注册码的过程是猜的.
   '程序从最后两位开始,在tmp中平均取8位注册码
   For i = Len(tmp) To 1 Step -(Len(tmp) \ 4)
       sn = Mid(tmp, i, 1) + Mid(tmp, i - 1, 1) + sn
   Next i
   If Len(sn) > 8 Then sn = Left(sn,
   MsgBox "Your sn is: " + sn, 64, "大概吧!祝好运!"
   End
End Sub