• 标 题:Slam!seeker汉化版注册保护算法的分析 
  • 作 者:FTBirthday
  • 时 间:2003/06/04 02:24am
  • 链 接:http://bbs.pediy.com

标题:Slam!注册保护算法的分析
作者:FTBirthday
软件名称: Slam!seeker汉化版
软件版本: 1.0 完美版
适用系统: Win 9x/ME/2000/XP
授权形式: 共享软件
功能:一个小游戏.
工具:pw32dasmgold,Hiew32,trw2000.
下载:见附件.
这是个16位的软件,比较古老了点.所以pw32dasmgold反汇编代码看上去不太习惯.

**************************************************************************************
**************************************************************************************
运行后弹出一个注册框,随便输入注册码,trw2000设断bpx GETDLGITEMTEXT.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.8510(C)
|
:0001.8518 8B760E                 mov si, [bp+0E]
:0001.851B 56                     push si

* Possible Ref to Menu: WSLAMMENU, Item: "新游戏(N)"
                                 |
:0001.851C 6A64                   push 0064
:0001.851E 1E                     push ds
:0001.851F 68302E                 push 2E30
:0001.8522 6A40                   push 0040
:0001.8524 9AFFFF0000             call USER.GETDLGITEMTEXT  ---读入注册码
:0001.8529 803E302E00             cmp byte ptr [2E30], 00 ---是否为空
:0001.852E 7428                   je 8558          ----空则跳offset:8B4E
:0001.8530 E829FF                 call 845C        ----注册码检测的call
:0001.8533 0BC0                   or ax, ax
:0001.8535 7521                   jne 8558        
----可以跳过853F的MESSAGEBOX,用Hiew32改为je,仅是使输入任意错误注册码都不弹出失败提示框.
:0001.8537 56                     push si
:0001.8538 1E                     push ds
:0001.8539 680808                 push 0808
:0001.853C 50                     push ax
:0001.853D 50                     push ax
:0001.853E 50                     push ax
:0001.853F 9AEE110000             call USER.MESSAGEBOX  ----弹出"无效注册码"
:0001.8544 C606302E00             mov byte ptr [2E30], 00
:0001.8549 56                     push si

* Possible Ref to Menu: WSLAMMENU, Item: "新游戏(N)"
                                 |
:0001.854A 6A64                   push 0064
:0001.854C 1E                     push ds
:0001.854D 68302E                 push 2E30
:0001.8550 9AFFFF0000             call USER.SETDLGITEMTEXT
:0001.8555 EBAC                   jmp 8503
**************************************************************************************
**************************************************************************************
16位的软件,怪异,试试去掉nag,注册框nag是个DIALOGBOX

由pw32dasmgold反汇编知有三处代码调用了USER.DIALOGBOX,如下:
第一处:
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0928(U), :0001.09D0(U)
|
:0001.088C FF760E                 push word ptr [bp+0E]
:0001.088F 52                     push dx
:0001.0890 50                     push ax
:0001.0891 8BFA                   mov di, dx
:0001.0893 9ADE080000             call USER.DIALOGBOX
:0001.0898 57                     push di
:0001.0899 56                     push si
:0001.089A 9AEA080000             call KERNEL.FREEPROCINSTANCE

第二处:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0816(C)
|
:0001.08B0 C7060A130100           mov word ptr [130A], 0001
:0001.08B6 680D09                 push SEG ADDR of Segment 0001
:0001.08B9 681A14                 push 141A
:0001.08BC FF36B812               push word ptr [12B8]
:0001.08C0 9A17090000             call KERNEL.MAKEPROCINSTANCE
:0001.08C5 8956FC                 mov [bp-04], dx
:0001.08C8 FF36B812               push word ptr [12B8]
:0001.08CC 1E                     push ds

* Possible Reference to Dialog: ANGLEBOX
                                 |
:0001.08CD 687202                 push 0272
:0001.08D0 FF760E                 push word ptr [bp+0E]
:0001.08D3 52                     push dx
:0001.08D4 50                     push ax
:0001.08D5 89863AFF               mov [bp+FF3A], ax
:0001.08D9 89963CFF               mov [bp+FF3C], dx
:0001.08DD 9AFFFF0000             call USER.DIALOGBOX
:0001.08E2 8BF8                   mov di, ax
:0001.08E4 66FFB63AFF             push word ptr [bp+FF3A]
:0001.08E9 9AFFFF0000             call KERNEL.FREEPROCINSTANCE
:0001.08EE 0BFF                   or di, di
:0001.08F0 74AD                   je 089F
:0001.08F2 FF760E                 push word ptr [bp+0E]
:0001.08F5 666800000500           push 00050000

* Possible Reference to Dialog: REGISTRATIONINFO, CONTROL_ID:00FF, ""
                                 |
:0001.08FB 666AFF                 push FFFFFFFF
:0001.08FE 9A6B020000             call USER.POSTMESSAGE
:0001.0903 EB9A                   jmp 089F

第三处:
* Referenced by a CALL at Address:
|:0001.0F47
|
:0001.8572 C8040000               enter 0004, 00
:0001.8576 57                     push di
:0001.8577 56                     push si
:0001.8578 1E                     push ds

* Possible StringData Ref from Data Seg 002 ->"Wslam"
                                 |
:0001.8579 683308                 push 0833
:0001.857C 1E                     push ds

* Possible StringData Ref from Data Seg 002 ->"RegisID"
                                 |
:0001.857D 682B08                 push 082B
:0001.8580 1E                     push ds
:0001.8581 682A08                 push 082A
:0001.8584 1E                     push ds
:0001.8585 68302E                 push 2E30
:0001.8588 6A40                   push 0040
:0001.858A 1E                     push ds

* Possible StringData Ref from Data Seg 002 ->"wslam.ini"
                                 |
:0001.858B 682008                 push 0820
:0001.858E 9A4F160000             call KERNEL.GETPRIVATEPROFILESTRING
:0001.8593 E8C6FE                 call 845C   ----注册码检测的call
:0001.8596 0BC0                   or ax, ax
:0001.8598 7548                   jne 85E2  
----这个跳转可以跳过,offset:8BB8,用Hiew32改为je,一运行,爆破成功!去掉了注册框.
:0001.859A 683C5D                 push SEG ADDR of Segment 0001
:0001.859D 68E884                 push 84E8
:0001.85A0 FF36B812               push word ptr [12B8]
:0001.85A4 9A465D0000             call KERNEL.MAKEPROCINSTANCE
----这儿下断点bpx MAKEPROCINSTANCE就能拦到下面那个弹出注册框的DIALOGBOX.
:0001.85A9 8BF0                   mov si, ax
:0001.85AB FF36B812               push word ptr [12B8]
:0001.85AF 1E                     push ds

* Possible Reference to Dialog: REGISTRATIONINFO
                                 |
:0001.85B0 683908                 push 0839
:0001.85B3 FF7604                 push word ptr [bp+04]
:0001.85B6 52                     push dx
:0001.85B7 50                     push ax
:0001.85B8 8BFA                   mov di, dx
:0001.85BA 9A94080000             call USER.DIALOGBOX ---向上看有无跳过的地方.
:0001.85BF 57                     push di
:0001.85C0 56                     push si
:0001.85C1 9AD25D0000             call KERNEL.FREEPROCINSTANCE
:0001.85C6 E893FE                 call 845C
:0001.85C9 0BC0                   or ax, ax
:0001.85CB 7415                   je 85E2
:0001.85CD 1E                     push ds

* Possible StringData Ref from Data Seg 002 ->"Wslam"
                                 |
:0001.85CE 685C08                 push 085C
:0001.85D1 1E                     push ds

* Possible StringData Ref from Data Seg 002 ->"RegisID"
                                 |
:0001.85D2 685408                 push 0854
:0001.85D5 1E                     push ds
:0001.85D6 68302E                 push 2E30
:0001.85D9 1E                     push ds

* Possible StringData Ref from Data Seg 002 ->"wslam.ini"
                                 |
:0001.85DA 684A08                 push 084A
:0001.85DD 9A375E0000             call KERNEL.WRITEPRIVATEPROFILESTRING
-----------------------------------------------------------------------------
然后用trw2000拦截DIALOGBOX,设断bpx DIALOGBOX,试探各DIALOGBOX的作用.
:0001.0891 8BFA                   mov di, dx
:0001.0893 9ADE080000             call USER.DIALOGBOX 弹出菜单里的对话框.

:0001.85B8 8BFA                   mov di, dx
:0001.85BA 9A94080000             call USER.DIALOGBOX 弹出注册框.

:0001.08D9 89963CFF               mov [bp+FF3C], dx
:0001.08DD 9AFFFF0000             call USER.DIALOGBOX 功能不明.
-----------------------------------------------------------------------------
注册算法分析
-----注册码检测call 845C如下:
(如需动态分析,trw2000设断bpx GETDLGITEMTEXT,pmodule返回既是)
* Referenced by a CALL at Addresses:
|:0001.8530, :0001.8593, :0001.85C6
----------------------------
三个地方调用了注册码检测call,
:0001.8530,作用为验证输入的注册码
:0001.8593,程序启动时,用来判断是否弹出注册对话框
:0001.85C6,第二次验证输入的注册码,类似双重保险.
----------------------------
:0001.845C C8220000               enter 0022, 00
:0001.8460 57                     push di
:0001.8461 56                     push si
:0001.8462 33D2                   xor dx, dx
:0001.8464 8956FE                 mov [bp-02], dx  ----bp-02地址处双字节清零
:0001.8467 BE302E                 mov si, 2E30      -----2E30处存放了注册码
:0001.846A 3814                   cmp [si], dl  ---判断注册码第一位是否为零
:0001.846C 7426                   je 8494       ----为零则跳转
:0001.846E 8D7EDE                 lea di, [bp-22] ----bp-22的有效值给di

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.8492(C)
|-------下面是一个循环对注册码字符进行变换
:0001.8471 8D46FE                 lea ax, [bp-02] ----bp-02的有效值给ax
:0001.8474 3BF8                   cmp di, ax      ----比较di, ax
:0001.8476 731C                   jnb 8494       ----di>=ax则跳
:0001.8478 8A04                   mov al , [si]  ----注册码首字符ASCII码给al
:0001.847A 98                     cbw ---CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
:0001.847B 8BD8                   mov bx, ax    ----符号扩展后的注册码首字符给bx
:0001.847D F687FD0804             test byte ptr [bx+08FD], 04
:0001.8482 740A                   je 848E
:0001.8484 98                     cbw  
:0001.8485 2D3000                 sub ax, 0030    ----ax=ax-0030
:0001.8488 8905                   mov [di], ax    ----把ax赋给di所指地址处的值
:0001.848A 83C702                 add di, 0002    ----di=di+0002
:0001.848D 42                     inc dx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.8482(C)
|
:0001.848E 46                     inc si
:0001.848F 803C00                 cmp byte ptr [si], 00  ----判断注册码处理完毕否
:0001.8492 75DD                   jne 8471      ----没完跳回继续循环
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.846C(C), :0001.8476(C)
|
:0001.8494 83FA10                 cmp dx, 0010    
----注册码位数与10(hex)即16(dec)比较,在这儿设断点bpx ****(每次运行不同):8494可拦下所有调用
:0001.8497 7C48                   jl 84E1   ------<=10则跳过下面一大段,直接返回.
------下面的bp-**都是注册码(设为a[i])经过变换后的相应值(设为a[i]')
:0001.8499 8B46E0                 mov ax, [bp-20]     ----注册码第二位变换值a[1]'给ax
:0001.849C F76EEA                 imul word ptr [bp-16]---a[1]'=a[1]'*a[6]'
:0001.849F F76EF4                 imul word ptr [bp-0C]---a[1]'=a[1]'*a[6]'*a[11]'
:0001.84A2 F76EF6                 imul word ptr [bp-0A]---a[1]'=a[1]'*a[6]'*a[11]'*a[12]'
:0001.84A5 8BC8                   mov cx, ax   ---cx=ax=a[1]'*a[6]'*a[11]'*a[12]'
:0001.84A7 8B46E4                 mov ax, [bp-1C]     ----注册码第四位变换值a[3]'给ax
:0001.84AA F76EE6                 imul word ptr [bp-1A]
:0001.84AD F76EF2                 imul word ptr [bp-0E]
:0001.84B0 F76EF8                 imul word ptr [bp-08]
:0001.84B3 03C8                   add cx, ax  
     ---cx=cx+ax=a[1]'*a[6]'*a[11]'*a[12]'+a[3]'*a[4]'*a[10]'*a[13]'
:0001.84B5 8B46EC                 mov ax, [bp-14]    ----注册码第八位变换值a[7]'给ax
:0001.84B8 F76EEE                 imul word ptr [bp-12]
:0001.84BB F76EF0                 imul word ptr [bp-10]
:0001.84BE F76EFC                 imul word ptr [bp-04]
:0001.84C1 03C8                   add cx, ax
---cx=cx+ax=a[1]'*a[6]'*a[11]'*a[12]'+a[3]'*a[4]'*a[10]'*a[13]'+a[7]'*a[8]'*a[9]'*a[15]'
:0001.84C3 8B46E2                 mov ax, [bp-1E]    ----注册码第三位变换值a[2]'给ax
:0001.84C6 F76EE8                 imul word ptr [bp-18]
:0001.84C9 F76EFA                 imul word ptr [bp-06]
:0001.84CC F76EDE                 imul word ptr [bp-22]
:0001.84CF 03C1                   add ax, cx
---ax=cx+ax=a[1]'*a[6]'*a[11]'*a[12]'+a[3]'*a[4]'*a[10]'*a[13]'+a[7]'*a[8]'*a[9]'*a[15]'+a[2]'*a[5]'*a[14]'*a[0]'
* Possible Ref to Menu: WSLAMMENU, Item: "帮助(H)..."
                                 |
:0001.84D1 B9F401                 mov cx, 01F4   ----cx=01F4
:0001.84D4 99                     cwd
:0001.84D5 F7F9                   idiv cx  
----------------------------------------------------
div 源(eax=eax/源,edx=余数)
IDIV    整数除法. 以上两条,结果回送:
             商回送AL,余数回送AH, (字节运算);
         或  商回送AX,余数回送DX, (字运算).
----------------------------------------------------
:0001.84D7 83FA7F                 cmp dx, 007F    ----余数和007F比较
:0001.84DA 7505                   jne 84E1        ----不相等则失败
关键比较,offset:8AFA,用Hiew32改为je,OK了!
:0001.84DC C746FE0100             mov word ptr [bp-02], 0001 ---注册标志位置入

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.8497(C), :0001.84DA(C)
|
:0001.84E1 8B46FE                 mov ax, [bp-02]    ----ax存放注册标志位
:0001.84E4 5E                     pop si
:0001.84E5 5F                     pop di
:0001.84E6 C9                     leave
:0001.84E7 C3                     ret

总结:
注册码必须为16位
1.处理过程
[注册码ASCII码值+08FD]处值与04比较,不同则
注册码处理值=注册码ASCII码值-30(hex)

2.检验过程:
简化bp-**=**,所以bp-12下面写为12
22     20      1E      1C     1A      18     16     14     内存中的处理值
1      2       3       4      5       6      7      8      对应第i位注册码
a[0]' a[1]'   a[2]'   a[3]'  a[4]'   a[5]'  a[6]'   a[7]'  对应注册码处理值


12     10      0E       0C      0A       08      06       04
9      10      11       12      13       14      15       16
a[8]' a[9]'   a[10]'   a[11]'  a[12]'   a[13]'  a[14]'   a[15]'

令sum=a[1]'*a[6]'*a[11]'*a[12]'+a[3]'*a[4]'*a[10]'*a[13]'+a[7]'*a[8]'*a[9]'*a[15]'+a[2]'*a[5]'*a[14]'*a[0]'

sum%01F4与007F比较,相等则注册成功!
喜欢做注册机的话,就试试看吧!