• 标 题:Tutor13  How to crack Drag And View v4.50
  • 作 者:dREAMtHEATER
  • 时 间:16/17th, Oct 1999
  • 链 接:http://bbs.pediy.com

作者:dREAMtHEATER
E-mail:dreamtheater@263.net
写作日期: 16/17th, Oct 1999

软件背景资料

运行平台: Win9X/NT 
文件名称: dv95.exe
程序类型: 文件格式浏览器
下载地点: http://www.canyonsw.com
文件大小: 1,970KB

使用的工具

SoftIce V4.0--Win9X Debugger
W32Dasm V8.93--Win9X Dissembler
RegSnap V2.51--Registry Analyzing Tool
Registry Studio V1.01--Enhanced Registry Editor

保护类型
Serials(*)  Nag Screens(*)  Keyfiles( )  Crippled( )  Packed( )  CD-Checks( ) 
                                         
难易程度
Easy(X)  Medium( )  Hard( )  Pro( )

                  ----------=======声明========----------

      未经作者同意,不得修改、引用原文,一切权利保留。
      本教程只供教学用,其他一切用途皆被禁止。
             
                  ----------=======软件介绍========----------

    超强的浏览,编辑程序,支持拖放功能,支持各种文本、图形,甚至数据库的浏览。可取代
ACDsee,UltraEdit等。
它所支持的文件类型如下:
- Word, Works, WordPerfect, Ami Pro,
Q&AWrite, 纯文本、二进制文件等类型文档。
- Excel, Lotus, Quattro等电子表格
- FoxPro, Clipper, dBase数据库
- 播放动态GIF文件
- 播放MIDI, WAV和RMI声音文件
- 播放AVI动画
- 大量最新的Internet文件格式
- 使用Active X控制显示Web页面
- 大量的图形文件

注册后能够支持下列格式:
PowerPoint PPT
Autocad DXF
Micrografx Designer DRW
Computer Graphics Metafiles CGM
Encapsulated Postscript Files EPS
HPGL
Lotus PIC
WordPerfect Graphics WPG

                                ----摘自该软件的汉化说明(作者:张楚权)
   
                ----------=======软件的保护系统========-------
   
      该软件可以免费试用三十天,六十天后必须注册,时间写在
HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES\CLSID\{34ee9750-9350-11d1-8fee-004095e2400c}默认键
值中,注册后在注册表:  HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES\CLSID\{34ee9750-9350-11d1-
8fee-004095e2400c}\InprocServer32 这个子键下写入默认键值:“ole32.DLL”,如果是重新获得
30天试用期,将在:
HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES\CLSID\{34ee9750-9350-11d1-8fee-004095e2400c}下写入
一个DWORD值 “Extension=0x00000001(1)”。可见,该程序并不是将真正的注册码写入注册表,而
是以“ole32.DLL”和“Extension=0x00000001(1)”为标志。

                  ----------========正文========----------

如何计算注册码

      运行程序,还好!没有讨厌的nag出现,直接到菜单中寻找注册项,没有!难道是过期后才提
示注册?对!将系统时间往后调,关闭窗口,准备重新运行。就在我按下窗口的关闭按纽后,哇!
Nag出现了,原来它躲在这里!点击上面的"Enter Code" button,进入注册窗口,输入1234567890。
      在SoftIce中设断点"bpx hmemcpy" ,Ctrl-D,回到注册窗口,press "OK" button,BOOM!你又立
即回到SoftIce中,"bc *",取消所有断点,Press F12数次,直到下面的代码出现:

:00402B15 6A0F                    push 0000000F
:00402B17 50                      push eax

* Possible Reference to Dialog: DialogID_0083, CONTROL_ID:01F9, ""
                                  |
:00402B18 68F9010000              push 000001F9
:00402B1D 56                      push esi

* Reference To: USER32.GetDlgItemTextA, Ord:00F5h  <==程序调用"GetDlgItemTextA"来获取
                                                      你输入的code,在SI中你也可以设置
                                                      这个断点,但请记住,在你不知道程
                                                      序调用什么函数之前,"hmemcpy"应
                                                      是你的首选,它的命中率为99.9% ,
                                                      这会节省你的时间,但需要你有较
                                                      多的经验。
                                  |
:00402B1E FF1570BD4400            Call dword ptr [0044BD70]
:00402B24 FF35EC5A4400            push dword ptr [00445AEC]
:00402B2A 8D45EC                  lea eax, dword ptr [ebp-14]  <==eax指向输入的code
:00402B2D 50                      push eax 
:00402B2E 56                      push esi
:00402B2F E83C000000              call 00402B70  <==code check
:00402B34 83C40C                  add esp, 0000000C
:00402B37 85C0                    test eax, eax 
:00402B39 7417                    je 00402B52  <==good/bad boy
:00402B3B 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"Thank You"
                                  |
:00402B3D 6808134400              push 00441308

* Possible StringData Ref from Data Obj ->"Program is registered"
                                  |
:00402B42 68F0124400              push 004412F0
:00402B47 56                      push esi

* Reference To: USER32.MessageBoxA, Ord:0195h
                                  |
:00402B48 FF1574BD4400            Call dword ptr [0044BD74]

      为了了解程序如何进行注册码计算的,我们需要trace into "call 00402B70",因此在
:00402B70处设断点,重新回到注册窗口,填入fake code,这回你进入了下面的这段代码:

* Referenced by a CALL at Address:
|:00402B2F 
|
:00402B70 55                      push ebp
:00402B71 8BEC                    mov ebp, esp
:00402B73 56                      push esi
:00402B74 57                      push edi
:00402B75 8B7D0C                  mov edi, dword ptr [ebp+0C]
:00402B78 57                      push edi  <==eax point to code you type into

* Reference To: KERNEL32.lstrlenA, Ord:02A1h
                                  |
:00402B79 FF1508BA4400            Call dword ptr [0044BA08]  <==获取你输入code的字符串
                                                                长度
:00402B7F 83F80E                  cmp eax, 0000000E 
:00402B82 7550                    jne 00402BD4  <==not equal to 14 ,bad boy
:00402B84 57                      push edi
:00402B85 33F6                    xor esi, esi

* Reference To: USER32.CharUpperA, Ord:002Bh
                                  |
:00402B87 FF1564BD4400            Call dword ptr [0044BD64]  <==将输入的code中的小写字
                                                                母变成大写。
:00402B8D 33C9                    xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402BAF(C)
|
:00402B8F 8A0439                  mov al, byte ptr [ecx+edi]---------+
:00402B92 3C41                    cmp al, 41                        |
:00402B94 0FBEC0                  movsx eax, al                      |   
:00402B97 7C06                    jl 00402B9F                        |
:00402B99 8D7406BF                lea esi, dword ptr [esi+eax-41]    |
:00402B9D EB04                    jmp 00402BA3                      |
                                                                    |
* Referenced by a (U)nconditional or (C)onditional Jump at Address:  |
|:00402B97(C)                                                        |
|                                                                    |
:00402B9F 8D7406D0                lea esi, dword ptr [esi+eax-30]    |
                                                                    |---real serial
* Referenced by a (U)nconditional or (C)onditional Jump at Address:  |  check
|:00402B9D(U)                                                        |
|                                                                    |
:00402BA3 83FE09                  cmp esi, 00000009                  |
:00402BA6 7E03                    jle 00402BAB                      |
:00402BA8 83EE09                  sub esi, 00000009                  |
                                                                    |
* Referenced by a (U)nconditional or (C)onditional Jump at Address:  |
|:00402BA6(C)                                                        |
|                                                                    |
:00402BAB 41                      inc ecx                            |
:00402BAC 83F90E                  cmp ecx, 0000000E                  |
:00402BAF 7CDE                    jl 00402B8F -----------------------+
:00402BB1 83FE04                  cmp esi, 00000004
:00402BB4 750F                    jne 00402BC5  〈== if eax=4, you'll recover more 30
                                                    days to evaluate it
:00402BB6 FF7510                  push [ebp+10]
:00402BB9 FF7508                  push [ebp+08]
:00402BBC E8A3000000              call 00402C64  <==写注册表
:00402BC1 59                      pop ecx
:00402BC2 59                      pop ecx
:00402BC3 EB3D                    jmp 00402C02

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402BB4(C)
|
:00402BC5 8B4510                  mov eax, dword ptr [ebp+10]  <==eax=5
:00402BC8 3BF0                    cmp esi, eax
:00402BCA 7508                    jne 00402BD4  <==good/bad boy
:00402BCC 48                      dec eax
:00402BCD 7425                    je 00402BF4
:00402BCF 83E804                  sub eax, 00000004
:00402BD2 7419                    je 00402BED

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00402B82(C), :00402BCA(C)
|
:00402BD4 6A10                    push 00000010

* Possible StringData Ref from Data Obj ->"Invalid Code"
                                  |
:00402BD6 6888134400              push 00441388

* Possible StringData Ref from Data Obj ->"Sorry, Invalid Code!"
                                  |
:00402BDB 6870134400              push 00441370
:00402BE0 FF7508                  push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:0195h
                                  |
:00402BE3 FF1574BD4400            Call dword ptr [0044BD74]
:00402BE9 33C0                    xor eax, eax
:00402BEB EB15                    jmp 00402C02

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

* Possible StringData Ref from Data Obj ->"{34ee9750-9350-11d1-8fee-004095e2400c}"
                                  |
:00402BED 6890114400              push 00441190
:00402BF2 EB05                    jmp 00402BF9

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

* Possible StringData Ref from Data Obj ->"{6ea280e0-9350-11d1-8fee-004095e2400c}"
                                  |
:00402BF4 68E0114400              push 004411E0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402BF2(U)
|
:00402BF9 E808000000              call 00402C06  <==写注册表
:00402BFE 59                      pop ecx
:00402BFF 6A01                    push 00000001
:00402C01 58                      pop eax

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00402BC3(U), :00402BEB(U)
|
:00402C02 5F                      pop edi
:00402C03 5E                      pop esi
:00402C04 5D                      pop ebp
:00402C05 C3                      ret

      从:00402B8F到:00402BAC计算注册码,你能看懂吗?其中,edi指向code字符串的首地址,
我们可以将我们输入的code看作一个字符串数组(假设为reg(I)),按顺序取字符串的每一位,共进
行十四次循环,每次将该位字符的ACSII码值与0x41(字符“A”)相比,若小于则将码值减去0x30(
字符“0”),所得值加上esi(初始值为零)再赋给esi;若大于等于,则减去0x41,其他步骤同前。每
次循环的最后将esi与9比较,大于9则令esi=esi-9。
      循环计算结束,所得esi值若等于4,你将重新获得30天试用期,等于5,你就是注册用户了
,等于其他数,程序就认为你输入了无效的注册码。
      为了便于理解,我将上面计算注册码的部分翻译成BASIC语言(注:48,65代表"0","A"十进
制ASCII值):

esi=0
for i=1 to 14
  a=asc(reg(i))-65
    if a<0 then
    esi=esi+asc(reg(i))-48
    else
    esi=esi+asc(reg(i))-65
  end if
  if esi>9 then
    esi=esi-9
  end if
next i
if esi=5 then goto goodbay
    else
      if esi=4 then goto more30days
      end if
end if
    goto badboy
     
      经过上面的讲述你能独立算出正确的注册码吗?可以看出,有无数个14位字符组成的字符串
符合上述条件。最简单、直接的推算,可以写出50000000000000,5jjjjjjjjjjjjj,11111111111111
.......你能类推吗?

If you have any questions,please free drop me at dreamtheater@263.net

dREAMtHEATER