• 标 题:XnView1.68算法分析(高手勿进)
  • 作 者:lzqgj
  • 时 间:004-05-25,23:42
  • 链 接:http://bbs.pediy.com

破解工具:OLLYDBG1.09d,PEID0.8
破解对象:XnView1.68
下载地址:http://www.skycn.com/soft/3110.html
软件简介:
支持多达 70 种格式的图形浏览、转换、编辑软件, 还可制作 Slide Show。是否嫌ACDSEE太大功能太少?XNVIEW能很好地解决问题,他具有抓图、编辑图象、增加特效的功能,支持你所知道的所有格式及你不知道的格式(包括电影、MP3)。
破解说明:
    我真的需要这个软件。前几天买了数码相机,拍了些照片,想稍微修饰一下,顺便作看图软件。本来想用ACDSEE,但刚好看到一篇文章说其功能强大,可代替ACDSEE,人怕出名猪怕壮,所以当然要用用它了。
破解过程:
    用PEID侦出用ASPACK加壳。是个弱壳,很容易脱,不过我不想脱它,文件大了占地方。
    运行XnView1.68,点注册按钮出现注册框,运行OD,点ATTACH(附加)按钮,选择XnView进程,就可以用OD带壳调试它了。
    随便填入注册信息,确定后弹出非法注册的警告,于是在OD中下断点:bp MessageBoxA(注意大小写),再次注册,OD拦截下来,按CTRL+F9运行到返回,当按警告框确定按钮后OD再次拦下,F8返回到程序,到如下位置。
004696E7  CALL DWORD PTR DS:[541584]               ; USER32.MessageBoxA
004696ED  PUSH 7D0   --->返回到此,上面即是警告框
向上找找有没有跳转可跳过,发现如下代码:
004696A6  PUSH EDX
004696A7  PUSH EAX
004696A8  CALL xnview.0040B3C0         --->对NAME进行计算
004696AD  LEA ECX,DWORD PTR SS:[ESP+18]
004696B1  PUSH ECX
004696B2  CALL xnview.004734E3         --->将输入码转化为十六进制
004696B7  MOV ECX,DWORD PTR SS:[ESP+14]
004696BB  ADD ESP,0C
004696BE  CMP ECX,EAX                 --->比较
004696C0  JE SHORT xnview.0046971F    --->不跳则OVER
程序用十六进制明码比较,让我们在40B3C0处下断进去看看算法。跟进后看到如下代码。
0040B3C0    MOV EDX,DWORD PTR SS:[ESP+4]
0040B3C4    PUSH EBX
0040B3C5    PUSH EBP
0040B3C6    PUSH ESI
0040B3C7    PUSH EDI
0040B3C8    MOV EDI,EDX
0040B3CA    OR ECX,FFFFFFFF
0040B3CD    XOR EAX,EAX
0040B3CF    REPNE SCAS BYTE PTR ES:[EDI]
0040B3D1    NOT ECX
0040B3D3    DEC ECX
0040B3D4    MOV ESI,xnview.0056B798
0040B3D9    MOV EBP,ECX
0040B3DB    MOV ECX,5
0040B3E0    MOV EDI,xnview.0058BA08
0040B3E5    REP MOVS DWORD PTR ES:[EDI],DWORD PTR>; 复制表的内容
0040B3E7    MOV ESI,EAX
0040B3E9    JE SHORT xnview.0040B40C
0040B3EB    MOV CL,BYTE PTR DS:[ESI+EDX]          ; 逐字取出NAME
0040B3EE    MOV BL,CL
0040B3F0    XOR BL,BYTE PTR DS:[EAX+58BA08]       ; 与查表结果(1~5字节)进行XOR运算
0040B3F6    INC EAX
0040B3F7    CMP EAX,5                             ; 将循环5次
0040B3FA    MOV BYTE PTR DS:[ESI+EDX],BL          ; 结果保存
0040B3FD    MOV BYTE PTR DS:[EAX+58BA07],CL       ; 用NAME覆盖表中内容
0040B403    JNZ SHORT xnview.0040B407
0040B405    XOR EAX,EAX                           ;若EAX=5则重0开始计数,即NAME长度大于5时表中内容会被循环覆盖(5个一循环),下类似
0040B407    INC ESI
0040B408    CMP ESI,EBP
0040B40A    JB SHORT xnview.0040B3EB
0040B40C    XOR EDI,EDI
0040B40E    XOR ECX,ECX
0040B410    TEST EBP,EBP
0040B412    JBE SHORT xnview.0040B43A
0040B414    MOV BL,BYTE PTR DS:[EDI+58BA0D]       ; 继续查表(6~10字节)准备第二轮运算
0040B41A    MOV ESI,EBP
0040B41C    SUB ESI,ECX
0040B41E    DEC ESI
0040B41F    MOV AL,BYTE PTR DS:[ESI+EDX]          ; 从最后一位开始倒过来取第一轮运算的结果
0040B422    XOR BL,AL                             ; XOR计算
0040B424    INC EDI
0040B425    MOV BYTE PTR DS:[ESI+EDX],BL          ; 用第二轮结果覆盖第一轮结果
0040B428    MOV BYTE PTR DS:[EDI+58BA0C],AL       ; 用第一轮结果覆盖表内容
0040B42E    CMP EDI,5
0040B431    JNZ SHORT xnview.0040B435
0040B433    XOR EDI,EDI
0040B435    INC ECX
0040B436    CMP ECX,EBP
0040B438    JB SHORT xnview.0040B414
0040B43A    XOR ESI,ESI
0040B43C    XOR EDI,EDI
0040B43E    TEST EBP,EBP
0040B440    JBE SHORT xnview.0040B463
0040B442    MOV AL,BYTE PTR DS:[EDI+EDX]          ; 取第二轮计算结果准备进行第三次运算
0040B445    MOV CL,BYTE PTR DS:[ESI+58BA12]       ; 继续查表(11~15字节)
0040B44B    XOR CL,AL                             ; XOR计算
0040B44D    INC ESI
0040B44E    MOV BYTE PTR DS:[EDI+EDX],CL          ; 用第三轮结果覆盖第二轮结果
0040B451    MOV BYTE PTR DS:[ESI+58BA11],AL       ; 第二轮结果覆盖表内容
0040B457    CMP ESI,5
0040B45A    JNZ SHORT xnview.0040B45E
0040B45C    XOR ESI,ESI
0040B45E    INC EDI
0040B45F    CMP EDI,EBP
0040B461    JB SHORT xnview.0040B442
0040B463    XOR EDI,EDI
0040B465    XOR ECX,ECX
0040B467    TEST EBP,EBP
0040B469    JBE SHORT xnview.0040B491
0040B46B    MOV BL,BYTE PTR DS:[EDI+58BA17]       ; 查表(16~20字节)准备第四轮计算
0040B471    MOV ESI,EBP
0040B473    SUB ESI,ECX
0040B475    DEC ESI
0040B476    MOV AL,BYTE PTR DS:[ESI+EDX]          ; 取第三轮结果倒过来进行第四轮计算结果计算
0040B479    XOR BL,AL
0040B47B    INC EDI
0040B47C    MOV BYTE PTR DS:[ESI+EDX],BL          ; 用第四轮结果覆盖第三轮结果
0040B47F    MOV BYTE PTR DS:[EDI+58BA16],AL       ; 将第三轮结果覆盖表中内容
0040B485    CMP EDI,5
0040B488    JNZ SHORT xnview.0040B48C
0040B48A    XOR EDI,EDI
0040B48C    INC ECX
0040B48D    CMP ECX,EBP
0040B48F    JB SHORT xnview.0040B46B
0040B491    MOV EDI,DWORD PTR SS:[ESP+18]
0040B495    XOR EAX,EAX
0040B497    TEST EBP,EBP
0040B499    MOV DWORD PTR DS:[EDI],0
0040B49F    JBE SHORT xnview.0040B4B8
0040B4A1    MOV ECX,EAX
0040B4A3    AND ECX,3                             ; 取位计数器,使其到第5次时又从0开始
0040B4A6    MOV BL,BYTE PTR DS:[ECX+EDI]          ; 取值,前4次为空,第5次从头开始取,即取得第四轮结果首位
0040B4A9    LEA ESI,DWORD PTR DS:[ECX+EDI]        ; ESI为保存注册码的地址
0040B4AC    MOV CL,BYTE PTR DS:[EAX+EDX]          ; 取第四轮计算结果,准备转化为注册码
0040B4AF    ADD BL,CL                             ; 相加,前4位加0,第五次时首位与末位相加
0040B4B1    INC EAX
0040B4B2    CMP EAX,EBP
0040B4B4    MOV BYTE PTR DS:[ESI],BL              ; 结果保存在[ESI]
0040B4B6    JB SHORT xnview.0040B4A1
0040B4B8    POP EDI
0040B4B9    POP ESI
0040B4BA    POP EBP
0040B4BB    POP EBX
0040B4BC    RETN

算法小结:
NAME(i)为每个字节,S(i)为表中内容
第一轮:
取表中1~5字节分别与NAME(i)进行XOR计算,保存在A(i)中
然后将S(i)用NAME(i)覆盖,若NAME长度大于5,用第6位覆盖第1位,依次类推
第二轮:
A(i)从最后一位开始分别与表中6~10字节进行XOR计算,保存在B(i)中
然后表6~10位用A(i)覆盖,若NAME长度大于5,用第6位覆盖第6位,依次类推
第三轮:
取表中11~15字节分别与B(i)进行XOR计算,保存在C(i)中
然后表11~15位用B(i)覆盖,若NAME长度大于5,用第6位覆盖第11位,依次类推
第四轮:
C(i)从最后一位开始分别与表中16~20字节进行XOR计算,保存在D(i)中
然后表16~20位用A(i)覆盖,若NAME长度大于5,用第6位覆盖第16位,依次类推
第五轮:
将D(i)组合为注册码:将D(i)四个一组,得到一个四字节的结果,保存在E(i)中。如:
E(1)=D(1)+D(5)+D(9)+....得到一个字节,依次类推。
然后将E(1)~E(4)反向读取得到一个十六进制结果,如AABBCCDD反向为DDCCBBAA,即为最终注册码。


表中内容为: &HAA &H89 &HC4 &HFE &H46 &H78 &HF0 &HD0 &H03 &HE7 
             &HF7 &HFD &HF4 &HE7 &HB9 &HB5 &H1B &HC9 &H50 &H73, 共20字节

用VB可做成注册机:
Dim A(), C()

Private Sub Text1_Change()
   t = Text1.Text: ln = Len(t)
   B = Array(0, &HAA, &H89, &HC4, &HFE, &H46, &H78, &HF0, &HD0, &H3, &HE7, _
             &HF7, &HFD, &HF4, &HE7, &HB9, &HB5, &H1B, &HC9, &H50, &H73)
   ReDim A(ln)
      For i = 1 To ln
         k = (i - 1) Mod 5 + 1
         A(i) = Asc(Mid(t, i, 1))
         R = A(i) Xor B(k): B(k) = A(i): A(i) = R
         If A(i) >= 256 Then A(i) = A(i) - 256
      Next
      Text2.Text = A(ln)
      j = ln
      For i = 1 To ln
         k = (i - 1) Mod 5 + 1 + 5
         R = A(j) Xor B(k): B(k) = A(j): A(j) = R
         If A(j) >= 256 Then A(j) = A(j) - 256
         j = j - 1
      Next
      j = 1
      For i = 1 To ln
         k = (i - 1) Mod 5 + 1 + 10
         R = A(j) Xor B(k): B(k) = A(j): A(j) = R
         If A(j) >= 256 Then A(j) = A(j) - 256
         j = j + 1
      Next
      j = ln
      For i = 1 To ln
         k = (i - 1) Mod 5 + 1 + 15
         R = A(j) Xor B(k): B(k) = A(j): A(j) = R
         If A(j) >= 256 Then A(j) = A(j) - 256
         j = j - 1
      Next
      ReDim C(1 To 4)
      For i = 1 To ln
         k = (i - 1) Mod 4 + 1
         C(k) = C(k) + A(i)
         If C(k) >= 256 Then C(k) = C(k) - 256
      Next
      Text2.Text = C(4) * 256 * 256 * 256 + _
                   C(3) * 256 * 256 + C(2) * 256 + C(1)
End Sub