开刀对象:3DMark 2001 SE Build 330版For Win9x/ME/2000/XP(2002年6月17日发布)Madonion的3D Mark系列测试软件凭籍着亮丽的画面和动感的音乐两大法宝,已经成为了标准测试软件,且深受大家的喜爱。简便的操作,直观的结果,与3D Winbench相比,3D Mark确实更能打动我们这些普通玩家。新版本里更加入了对DirectX 9.0、AGP 3.0 (AGP 8x)、日文和韩文操作系统、新型号的硬件产品(主要在图形芯片方面)的支持,修正了上个版本的一些BUG。
目的:练手,该软件在不注册的情况一样可以正常使用,注册后增加网上服务功能!
下载地址:http://file.mydrivers.com/tools/tweak/3DMark2001SE.exe
使用工具:PEid, W32Dasm, Ollydbg1.09
使用平台:Windows XP SP1
难度:比较简单
过程:
1、用PEid检查3dmark2001se.exe,发现是用VC++6.0编写,无壳。
2、采用静态分析的方法,看是否能找到有助破解的字符串。用W32Dasm打开3dmark2001se.exe,由于文件体积比较大,分析的时间较长。分析完毕后,在“字串参考”中找到三条十分有用的信息。一条是恭喜成功注册云云,另外两条是一样的,当然是说注册码不正确了。双击其中一条,在其汇编附近没发现明显的注册码判断语句,双击另外一条,到达如下地方:
* Reference To: MFC42.Ordinal:18BE, Ord:18BEh
00440598 . E87DE71F00
CALL 0063ED1A
0044059D . 8BB5A0000000 MOV ESI, DWORD PTR
[EBP+000000A0]
004405A3 . 8B46F8 MOV
EAX, DWORD PTR [ESI-08]
004405A6 . 85C0 TEST
EAX, EAX
004405A8 . 751F JNZ
004405C9
004405AA . 50 PUSH
EAX
* Possible Reference to String Resource ID=61600: "Incorrect registration information.Please enter the correc"
004405AB . 68A0F00000
PUSH 0000F0A0
004405B0 . 8BCB MOV
ECX, EBX
004405B2 . E8 2945FCFF CALL 00404AE0
004405B7 . 5E POP
ESI
004405B8 . 5D POP
EBP
004405B9 . 5B POP
EBX
004405BA . 8B4C24 34 MOV ECX, DWORD
PTR [ESP+34]
004405BE . 64:890D 00000>MOV DWORD PTR FS:[00000000],
ECX
004405C5 . 83C4 40 ADD ESP,
00000040
004405C8 . C3 RET
在00440598处有一个Call,后面有一个Test和JNZ,很经典的判断注册码正确与否的格式。在这里下断点吧!
3、用Ollydbg打开3dmark2001se.exe后,点Register,用户名:Hartnett,试验码:1234567890(随便输的)。然后在执行模块中转到3dmark2001se.exe领空,在00440598处下断点。在3dmark中点OK后,程序被断下。第一遍用F8粗跟,大致分析一遍后用F7+F8,到如下地方:
00610C10 . 6A FF
PUSH -1
00610C12 . 68 D4FA7400 PUSH 3DMark20.0074FAD4
; SE handler
installation
00610C17 . 64:A1 0000000>MOV EAX, DWORD PTR
FS:[0]
00610C1D . 50 PUSH
EAX
00610C1E . 64:8925 00000>MOV DWORD PTR FS:[0],
ESP
00610C25 . 83EC 24 SUB ESP,
24
00610C28 . 53 PUSH
EBX
00610C29 . 56 PUSH
ESI
00610C2A . 8B7424 40 MOV ESI, DWORD
PTR SS:[ESP+40]
00610C2E . 57 PUSH
EDI
00610C2F . 8B7E 08 MOV EDI,
DWORD PTR DS:[ESI+8]
00610C32 . 33DB XOR
EBX, EBX
00610C34 . 83FF 17 CMP EDI,
17 在此判断注册码是否23位。
00610C37 . 895C24 0C MOV DWORD PTR
SS:[ESP+C], EBX
00610C3B . 0F85 5A010000 JNZ 3DMark20.00610D9B 不是23位的话跳走(爆破点)
00610C41 . 8B46 04 MOV EAX,
DWORD PTR DS:[ESI+4]
00610C44 . 3BC3 CMP
EAX, EBX
00610C46 . 8B15 5CF77500 MOV EDX, DWORD PTR DS:[<&MSVCP60.?_C>;
MSVCP60.?_C@?1??_Nullstr@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@CAPBDXZ@4DB
00610C4C . 8BCA MOV
ECX, EDX
00610C4E . 74 03 JE
SHORT 3DMark20.00610C53
00610C50 . 8D48 05 LEA ECX,
DWORD PTR DS:[EAX+5]
00610C53 > 8039 2D CMP
BYTE PTR DS:[ECX], 2D 第六个字符是否是“-”
00610C56 . 0F85 3F010000 JNZ 3DMark20.00610D9B 不是的话注册失败
00610C5C . 3BC3 CMP
EAX, EBX
00610C5E . 8BCA MOV
ECX, EDX
00610C60 . 74 03 JE
SHORT 3DMark20.00610C65
00610C62 . 8D48 0B LEA ECX,
DWORD PTR DS:[EAX+B]
00610C65 > 8039 2D CMP
BYTE PTR DS:[ECX], 2D 第十二个字符是否是“-”
00610C68 . 0F85 2D010000 JNZ 3DMark20.00610D9B 不是的话注册失败
00610C6E . 3BC3 CMP
EAX, EBX
00610C70 . 75 04 JNZ
SHORT 3DMark20.00610C76
00610C72 . 8BC2 MOV
EAX, EDX
00610C74 . EB 03 JMP
SHORT 3DMark20.00610C79
00610C76 > 83C0 11 ADD
EAX, 11
00610C79 > 8038 2D CMP
BYTE PTR DS:[EAX], 2D 第十八个字符是否是“-”
00610C7C . 0F85 19010000 JNZ 3DMark20.00610D9B 从这里知道,注册码采用
00610C82 . 6A 05 PUSH 5 xxxxx-xxxxx-xxxxx-xxxxx的格式
00610C84 . 53 PUSH
EBX
00610C85 . 8D4424 18 LEA EAX, DWORD
PTR SS:[ESP+18]
00610C89 . 50 PUSH
EAX
00610C8A . 8BCE MOV
ECX, ESI
........
于是在00610C8A处下一断点,按F9换到3dmark2001se下,重新输入注册试验码:12345-67890-12345-67890。点OK后按F9直到00610C8A,跟着程序走一遍,会轻而易举地发现下面的程序把注册试验码中间的“-”去掉,成为12345678901234567890的形式。由于Ollydbg的跟踪结果会随时显示在寄存器对话框中,我们可以非常清楚地看到转换后的注册码,同时,我们也可以从函数名称上大致知道这个函数是做什么的,这里就不再具体分析了。继续跟到如下代码处:
00611211 |> 8B46
04 /MOV EAX, DWORD PTR DS:[ESI+4]
00611214 |. 85C0 |TEST
EAX, EAX
00611216 |. 75 07 |JNZ
SHORT 3DMark20.0061121F
00611218 |. A1 5CF77500 |MOV EAX, DWORD PTR
DS:[<&MSVCP60.?_C@>
0061121D |. EB 02 |JMP
SHORT 3DMark20.00611221
0061121F |> 03C2 |ADD
EAX, EDX
00611221 |> 8B4C24 1C |MOV ECX,
DWORD PTR SS:[ESP+1C]
00611225 |. 8B71 08 |MOV ESI,
DWORD PTR DS:[ECX+8]
00611228 |. 85F6 |TEST
ESI, ESI
0061122A |. 8A00 |MOV
AL, BYTE PTR DS:[EAX]
0061122C |. 884424 13 |MOV BYTE PTR
SS:[ESP+13], AL
00611230 |. 76 3E |JBE
SHORT 3DMark20.00611270
00611232 |. 83FE 01 |CMP ESI,
1
00611235 |. 72 39 |JB
SHORT 3DMark20.00611270
00611237 |. 8B79 04 |MOV EDI,
DWORD PTR DS:[ECX+4]
0061123A |. 0FBEE8 |MOVSX EBP,
AL
0061123D |. 56 |PUSH
ESI
0061123E |. 55 |PUSH
EBP
0061123F |. 57 |PUSH
EDI
00611240 |. FFD3 |CALL
EBX
; msvcrt.memchr
00611242 |. 83C4 0C |ADD ESP,
0C
00611245 |. 85C0 |TEST
EAX, EAX
00611247 |. 74 1F |JE
SHORT 3DMark20.00611268
00611249 |> 8A10 |/MOV
DL, BYTE PTR DS:[EAX]
0061124B |. 8D4C24 13 ||LEA ECX, DWORD
PTR SS:[ESP+13]
0061124F |. 3A11 ||CMP
DL, BYTE PTR DS:[ECX]
00611251 |. 74 36 ||JE
SHORT 3DMark20.00611289
00611253 |. 2BF8 ||SUB
EDI, EAX
00611255 |. 8D743E FF ||LEA ESI, DWORD
PTR DS:[ESI+EDI-1]
00611259 |. 56 ||PUSH
ESI
0061125A |. 8D78 01 ||LEA EDI,
DWORD PTR DS:[EAX+1]
0061125D |. 55 ||PUSH
EBP
0061125E |. 57 ||PUSH
EDI
0061125F |. FFD3 ||CALL
EBX 这个Call把输入的注册码换个形式。
00611261 |. 83C4 0C ||ADD ESP,
0C
00611264 |. 85C0 ||TEST
EAX, EAX
00611266 |.^ 75 E1 |\JNZ SHORT
3DMark20.00611249
00611268 |> 8B5424 14 |MOV EDX,
DWORD PTR SS:[ESP+14]
0061126C |. 8B7C24 24 |MOV EDI, DWORD
PTR SS:[ESP+24]
00611270 |> A1 E8F67500 |MOV EAX, DWORD
PTR DS:[<&MSVCP60.?npo>
00611275 |. 8B00 |MOV
EAX, DWORD PTR DS:[EAX]
00611277 |> 8B0D E8F67500 |MOV ECX, DWORD PTR
DS:[<&MSVCP60.?npo>; MSVCP60.?npos@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@2IB
0061127D |. 3B01 |CMP
EAX, DWORD PTR DS:[ECX]
0061127F |. 74 1B |JE
SHORT 3DMark20.0061129C
00611281 |. 8B4F 04 |MOV ECX,
DWORD PTR DS:[EDI+4]
00611284 |. 890491 |MOV
DWORD PTR DS:[ECX+EDX*4], EAX 转换后的注册码保存
00611287 |. EB 22 |JMP
SHORT 3DMark20.006112AB
00611289 |> 8B4C24 1C |MOV ECX,
DWORD PTR SS:[ESP+1C]
0061128D |. 8B51 04 |MOV EDX,
DWORD PTR DS:[ECX+4]
00611290 |. 8B7C24 24 |MOV EDI, DWORD
PTR SS:[ESP+24]
00611294 |. 2BC2 |SUB
EAX, EDX
00611296 |. 8B5424 14 |MOV EDX, DWORD
PTR SS:[ESP+14]
0061129A |.^ EB DB |JMP SHORT
3DMark20.00611277
0061129C |> 8B47 04 |MOV
EAX, DWORD PTR DS:[EDI+4]
0061129F |. C70490 FFFFFF>|MOV DWORD PTR DS:[EAX+EDX*4],
-1
006112A6 |. C64424 12 00 |MOV BYTE PTR SS:[ESP+12],
0
006112AB |> 8B7424 20 |MOV ESI,
DWORD PTR SS:[ESP+20]
006112AF |. 8B46 08 |MOV EAX,
DWORD PTR DS:[ESI+8]
006112B2 |. 42 |INC
EDX 循环次数加1
006112B3 |. 3BD0 |CMP
EDX, EAX
006112B5 |. 895424 14 |MOV DWORD PTR
SS:[ESP+14], EDX 循环20次,注册码位数
006112B9 |.^ 0F82 52FFFFFF \JB 3DMark20.00611211
上面的程序将把注册码转换成另一种形式。这里要注意比较原码和转换码,发现其中的一一对应关系,以方便后面找到真正的注册码。由于我们所用的试验码排列有序,可以清楚地看到这种对应关系,即:1->18;2->19;3->1A;4->1B;5->1C;6->1D;7->1E;8->1F;9->20;0->17。那字母呢?也很简单,如果你不想费脑筋把Call
EBX弄清楚的话,可直接把试验码换成ABCDE-FGHIJ-KLMNO-PQRST,然后看看转换后的结果就行了。结果是A->00;B->01;C->03;D->04;......还有一点要说明一下的是转换后的注册码是以DWord形式保存的,也就是说,我们的试验码转换成:
18 00 00 00 19 00 00 00 1A
00 00 00 1B 00 00 00
1C 00 00 00 1D 00 00 00 1E
00 00 00 1F 00 00 00
20 00 00 00 17 00 00 00 18
00 00 00 19 00 00 00
1A 00 00 00 1B 00 00 00 1C
00 00 00 1D 00 00 00
1E 00 00 00 1F 00 00 00 20
00 00 00 17 00 00 00
继续跟程序,到达如下关键地方:
0061079A > 8B4C24
14 MOV ECX, DWORD PTR SS:[ESP+14] 注册码的判断以5位为单位
0061079E . 8B51 08 MOV EDX,
DWORD PTR DS:[ECX+8]
006107A1 . 8B41 0C MOV EAX,
DWORD PTR DS:[ECX+C]
006107A4 . 8B69 04 MOV EBP,
DWORD PTR DS:[ECX+4]
006107A7 . 8B7424 28 MOV ESI, DWORD
PTR SS:[ESP+28] ESI赋值21
006107AB . 03C2 ADD
EAX, EDX
006107AD . 8B11 MOV
EDX, DWORD PTR DS:[ECX]
006107AF . 03C5 ADD
EAX, EBP
006107B1 . 03C2 ADD
EAX, EDX 将前4个数字累加
006107B3 . 33D2 XOR
EDX, EDX EDX清零
006107B5 . F7F6 DIV
ESI 累加值除以21
006107B7 . 8B59 10 MOV EBX,
DWORD PTR DS:[ECX+10] 将第5位送入EBX
006107BA . 3BDA CMP
EBX, EDX EBX与余数比较
006107BC . 0F85 10010000 JNZ 3DMark20.006108D2 不相等的话玩完(爆破点)
006107C2 . 8B51 1C MOV EDX,
DWORD PTR DS:[ECX+1C] 继续比较下5位
006107C5 . 8B41 20 MOV EAX,
DWORD PTR DS:[ECX+20]
006107C8 . 8B59 18 MOV EBX,
DWORD PTR DS:[ECX+18]
006107CB . 03C2 ADD
EAX, EDX
006107CD . 8B51 14 MOV EDX,
DWORD PTR DS:[ECX+14]
006107D0 . 03C3 ADD
EAX, EBX
006107D2 . 03C2 ADD
EAX, EDX
006107D4 . 33D2 XOR
EDX, EDX
006107D6 . F7F6 DIV
ESI
006107D8 . 8B69 24 MOV EBP,
DWORD PTR DS:[ECX+24]
006107DB . 3BEA CMP
EBP, EDX
006107DD . 0F85 EF000000 JNZ 3DMark20.006108D2 不相等跳走(爆破点)
006107E3 . 8B51 30 MOV EDX,
DWORD PTR DS:[ECX+30] 再比较下5位
006107E6 . 8B41 34 MOV EAX,
DWORD PTR DS:[ECX+34]
006107E9 . 03C2 ADD
EAX, EDX
006107EB . 0341 2C ADD EAX,
DWORD PTR DS:[ECX+2C]
006107EE . 0341 28 ADD EAX,
DWORD PTR DS:[ECX+28]
006107F1 . 33D2 XOR
EDX, EDX
006107F3 . F7F6 DIV
ESI
006107F5 . 8B59 38 MOV EBX,
DWORD PTR DS:[ECX+38]
006107F8 . 3BDA CMP
EBX, EDX
006107FA . 0F85 D2000000 JNZ 3DMark20.006108D2 不相等再跳走(爆破点)
00610800 . 8B51 10 MOV EDX,
DWORD PTR DS:[ECX+10] 第一次判断的余数
00610803 . 8D042B LEA
EAX, DWORD PTR DS:[EBX+EBP] 第二次判断的余数
00610806 . 03C2 ADD
EAX, EDX 三次余数和
00610808 . 33D2 XOR
EDX, EDX
0061080A . F7F6 DIV
ESI 除以21H
0061080C . 8B79 3C MOV EDI,
DWORD PTR DS:[ECX+3C]
0061080F . 3BFA CMP
EDI, EDX 余数与第16位比较
00610811 . 0F85 B9000000 JNZ 3DMark20.006108D0 第16位的判断(爆破点)
00610817 . 8B51 24 MOV EDX,
DWORD PTR DS:[ECX+24] 第二次判断的余数
0061081A . 8D041F LEA
EAX, DWORD PTR DS:[EDI+EBX] 第三、四次判断的余数
0061081D . 03C2 ADD
EAX, EDX 余数和
0061081F . 33D2 XOR
EDX, EDX
00610821 . F7F6 DIV
ESI 除以21H
00610823 . 8B69 40 MOV EBP,
DWORD PTR DS:[ECX+40]
00610826 . 3BEA CMP
EBP, EDX
00610828 . 0F85 A2000000 JNZ 3DMark20.006108D0 第17位的判断(爆破点)
0061082E . 8D042F LEA
EAX, DWORD PTR DS:[EDI+EBP]
00610831 . 03C3 ADD
EAX, EBX
00610833 . 33D2 XOR
EDX, EDX
00610835 . F7F6 DIV
ESI
00610837 . 8B59 44 MOV EBX,
DWORD PTR DS:[ECX+44]
0061083A . 3BDA CMP
EBX, EDX
0061083C . 0F85 8E000000 JNZ 3DMark20.006108D0 第18位的判断(爆破点)
00610842 . 8D042B LEA
EAX, DWORD PTR DS:[EBX+EBP]
00610845 . 03C7 ADD
EAX, EDI
00610847 . 33D2 XOR
EDX, EDX
00610849 . F7F6 DIV
ESI
0061084B . 8B41 48 MOV EAX,
DWORD PTR DS:[ECX+48]
0061084E . 3BC2 CMP
EAX, EDX
00610850 . 75 7E JNZ
SHORT 3DMark20.006108D0 第19位的判断(爆破点)
00610852 . 03C3 ADD
EAX, EBX
00610854 . 03C5 ADD
EAX, EBP
00610856 . 33D2 XOR
EDX, EDX
00610858 . F7F6 DIV
ESI
0061085A . 3951 4C CMP DWORD
PTR DS:[ECX+4C], EDX
0061085D . 75 71 JNZ
SHORT 3DMark20.006108D0 第20位的判断(爆破点)
0061085F . 51 PUSH
ECX
00610860 . E8 5FE00200 CALL <JMP.&MFC42.#825_??3@YAXPAX@Z>
00610865 . 8B4C24 28 MOV ECX, DWORD
PTR SS:[ESP+28]
00610869 . 33F6 XOR
ESI, ESI
0061086B . 83C4 04 ADD ESP,
4
0061086E . 3BCE CMP
ECX, ESI
00610870 . 897424 14 MOV DWORD PTR
SS:[ESP+14], ESI
00610874 . 897424 18 MOV DWORD PTR
SS:[ESP+18], ESI
00610878 . 897424 1C MOV DWORD PTR
SS:[ESP+1C], ESI
0061087C . 74 1C JE
SHORT 3DMark20.0061089A
0061087E . 8A41 FF MOV AL,
BYTE PTR DS:[ECX-1]
00610881 . 84C0 TEST
AL, AL
00610883 . 74 0B JE
SHORT 3DMark20.00610890
00610885 . 3C FF CMP
AL, 0FF
00610887 . 74 07 JE
SHORT 3DMark20.00610890
00610889 . FEC8 DEC
AL
0061088B . 8841 FF MOV BYTE
PTR DS:[ECX-1], AL
0061088E . EB 0A JMP
SHORT 3DMark20.0061089A
00610890 > 49 DEC
ECX
00610891 . 51 PUSH
ECX
00610892 . E8 2DE00200 CALL <JMP.&MFC42.#825_??3@YAXPAX@Z>
00610897 . 83C4 04 ADD ESP,
4
0061089A > 8B4C24 34 MOV ECX,
DWORD PTR SS:[ESP+34]
0061089E . 3BCE CMP
ECX, ESI
006108A0 . 897424 24 MOV DWORD PTR
SS:[ESP+24], ESI
006108A4 . 897424 28 MOV DWORD PTR
SS:[ESP+28], ESI
006108A8 . 897424 2C MOV DWORD PTR
SS:[ESP+2C], ESI
006108AC . 74 1E JE
SHORT 3DMark20.006108CC
006108AE . 8A41 FF MOV AL,
BYTE PTR DS:[ECX-1]
006108B1 . 84C0 TEST
AL, AL
006108B3 . 74 0D JE
SHORT 3DMark20.006108C2
006108B5 . 3C FF CMP
AL, 0FF
006108B7 . 74 09 JE
SHORT 3DMark20.006108C2
006108B9 . FEC8 DEC
AL
006108BB . 8841 FF MOV BYTE
PTR DS:[ECX-1], AL
006108BE . B0 01 MOV
AL, 1
006108C0 . EB 7B JMP
SHORT 3DMark20.0061093D
006108C2 > 49 DEC
ECX
006108C3 . 51 PUSH
ECX
006108C4 . E8 FBDF0200 CALL <JMP.&MFC42.#825_??3@YAXPAX@Z>
006108C9 . 83C4 04 ADD ESP,
4
006108CC > B0 01 MOV
AL, 1
006108CE . EB 6D JMP
SHORT 3DMark20.0061093D
006108D0 > 33FF XOR
EDI, EDI
006108D2 > 51 PUSH
ECX
006108D3 . E8 ECDF0200 CALL <JMP.&MFC42.#825_??3@YAXPAX@Z>
算法分析:注册码判断正确与否是以5位为单位进行的。前三次判断(即前15位注册码)是一样的,即将前四位累加,然后除以21H,将余数与第五位比较,相等的话再进行下一次判断。以试验码为例,判断过程为:1->18;2->19;3->1A;4->1B,累加进来为66H,除以21H,余数是3。03H对应的原码是字母D。为方便我们找到可用的注册码,我们可以把试验码的前15位换成1234D-1234D-1234D-XXXXX。注意:程序会自动把输入的小写字母变成大写字母。
转换码为: 18 00 00 00 19 00 00 00 1A 00 00 00 1B 00 00 00
03 00 00 00 18 00 00 00 19
00 00 00 1A 00 00 00
1B 00 00 00 03 00 00 00 18
00 00 00 19 00 00 00
1A 00 00 00 1B 00 00 00 03
00 00 00 14 00 00 00
14 00 00 00 14 00 00 00 14
00 00 00 14 00 00 00
从第16位开始,注册码判断开始改变。
第16位:前三次余数和(03+03+03=09)除以21H的余数(09)与第16位比较,09H对应原码字母L
第17位:第四次判断的余数(09),加上第二、三次判断的余数,即(03+03+09=0F)除以21H的余数(0F)与第17位比较,0FH对应原码字母S。
第18位:第三、四、五次判断的余数和,即(03+09+0F=1B)除以21H的余数(1B),与第18位比较,1BH对应原码数字4。
第19位:第四、五、六次判断的余数和,即(09+0F+1B=33)除以21H的余数(12),与第19位比较,12H对应原码字母V。
第20位:第五、六、七次判断的余数和,即(0F+1B+12=3C)除以21H的余数(1B),与第20位比较,1BH对应原码数字4。
综上所述,第16-20位注册码是LS4V4,可用的完整注册码为:1234D-1234D-1234D-LS4V4.
弄清楚了注册码的生成过程,就可以写注册机了。当然了,如果不想费力气找注册码的话,也可以爆破的,爆破点我已经在代码中标出了。
整个注册过程用户名并不参与计算,你可以随便输入你想用的用户名!用户名和注册码保存在注册表中:
[HKEY_LOCAL_MACHINE\SOFTWARE\MadOnion.com\Registration2001]
"3DMarkRegName"="Hartnett"
"3DMarkRegKey"="1234D1234D1234DLS4V4"
但愿我把上述过程写得比较清楚了,呵呵!