• 标 题: 破解FlashGet1.65的过程
  • 作 者:do77
  • 时 间:2005-01-10 18:25

一、首先是了解flashget 1.65的注册原理

flashget(以下简称fg)是先填写注册码,
填写好了以后fg会把注册码保存在注册表里面,
例如:

[HKEY_CURRENT_USER\Software\JetCar\JetCar\General]
"RegPass"="aabbccdd"

然后在下次启动的时候检查注册码是否正确来确定是否显示广告条。

二、破解原理

在调试工具中(我用的是ollydbg v1.10 http://home.t-online.de/home/Ollydbg/)
找到有关注册的那部分,然后进行跟踪,分析fg是如何判断是否注册的

三、ollydbg(以下简称odbg)使用简单介绍

打开odbg,open一个程序,odbg会自动会程序进行反汇编,
反汇编结束以后,你会看到整个窗口被分成了四个部分
左上角的用于显示反编译的代码
右上角的用于显示寄存器数据
左下角显示当前所载入的软件数据在内存中的位置
右下角显示被各种函数所使用的内存

四、破解

1、先用ollydbg打开flashget.exe,odbg自动对fg反汇编,
然后就能看到flashget.exe的汇编代码
下面要找到注册相关的部分,我们就来查找RegPass这个字段

在反汇编出来的代码窗口中点右键,选择“Search for->All referencd text strings”
弹出一个窗口,都是referencd text strings,点右键,选择“search for text”。
这里注意他只会往下找,所以要把光标移动到最上面再查找
填入RegPass,注意大小写。
一共找到两个,现在要排除一个。
都设置成断点(f2)
然后run(f9),发现到0041dce6的那个断点停下了,说明是fg启动时候调用的
取消这个断点,restart,run,发现fg界面出来了,说明另外一个断点应该是存入用的
而前面一个断点应该就是关键了

我们可以把这个地方加入bookmark,以后就可以方便的使用alt+数字转到这里

2、分析附近代码
观察附近的代码(空指令nop),以及左边的大括号(一个子程序)
发现以下代码,先不要仔细看:

0041DC80  /$ 6A FF          PUSH -1
0041DC82  |. 68 20334F00    PUSH flashget.004F3320                   ;  SE handler installation
0041DC87  |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
0041DC8D  |. 50             PUSH EAX
0041DC8E  |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP
0041DC95  |. 83EC 20        SUB ESP,20
0041DC98  |. 53             PUSH EBX
0041DC99  |. 55             PUSH EBP
0041DC9A  |. 56             PUSH ESI
0041DC9B  |. 57             PUSH EDI
0041DC9C  |. 68 E8B85300    PUSH flashget.0053B8E8
0041DCA1  |. 68 A0E55200    PUSH flashget.0052E5A0                   ;  ASCII "RegName"
0041DCA6  |. 8D4424 18      LEA EAX,DWORD PTR SS:[ESP+18]
0041DCAA  |. 8BE9           MOV EBP,ECX
0041DCAC  |. 68 A0C15200    PUSH flashget.0052C1A0                   ;  ASCII "General"
0041DCB1  |. 50             PUSH EAX
0041DCB2  |. 896C24 28      MOV DWORD PTR SS:[ESP+28],EBP
0041DCB6  |. E8 95C70C00    CALL flashget.004EA450
0041DCBB  |. 8DB5 60030000  LEA ESI,DWORD PTR SS:[EBP+360]
0041DCC1  |. 50             PUSH EAX
0041DCC2  |. 8BCE           MOV ECX,ESI
0041DCC4  |. C74424 3C 0000>MOV DWORD PTR SS:[ESP+3C],0
0041DCCC  |. E8 83660B00    CALL flashget.004D4354
0041DCD1  |. 83CF FF        OR EDI,FFFFFFFF
0041DCD4  |. 8D4C24 10      LEA ECX,DWORD PTR SS:[ESP+10]
0041DCD8  |. 897C24 38      MOV DWORD PTR SS:[ESP+38],EDI
0041DCDC  |. E8 3A650B00    CALL flashget.004D421B
0041DCE1  |. 68 E8B85300    PUSH flashget.0053B8E8
0041DCE6  |. 68 98E55200    PUSH flashget.0052E598                   ;  ASCII "RegPass"
0041DCEB  |. 8D4C24 1C      LEA ECX,DWORD PTR SS:[ESP+1C]
0041DCEF  |. 68 A0C15200    PUSH flashget.0052C1A0                   ;  ASCII "General"
0041DCF4  |. 51             PUSH ECX
0041DCF5  |. 8BCD           MOV ECX,EBP
0041DCF7  |. E8 54C70C00    CALL flashget.004EA450
0041DCFC  |. 81C5 64030000  ADD EBP,364
0041DD02  |. BB 01000000    MOV EBX,1
0041DD07  |. 50             PUSH EAX
0041DD08  |. 8BCD           MOV ECX,EBP
0041DD0A  |. 895C24 3C      MOV DWORD PTR SS:[ESP+3C],EBX
0041DD0E  |. E8 41660B00    CALL flashget.004D4354
0041DD13  |. 8D4C24 14      LEA ECX,DWORD PTR SS:[ESP+14]
0041DD17  |. 897C24 38      MOV DWORD PTR SS:[ESP+38],EDI
0041DD1B  |. E8 FB640B00    CALL flashget.004D421B
0041DD20  |. 8B16           MOV EDX,DWORD PTR DS:[ESI]
0041DD22  |. 8B42 F8        MOV EAX,DWORD PTR DS:[EDX-8]
0041DD25  |. 85C0           TEST EAX,EAX
0041DD27  |. 0F84 4E010000  JE flashget.0041DE7B
0041DD2D  |. 8B45 00        MOV EAX,DWORD PTR SS:[EBP]
0041DD30  |. 8B48 F8        MOV ECX,DWORD PTR DS:[EAX-8]
0041DD33  |. 85C9           TEST ECX,ECX
0041DD35  |. 0F84 40010000  JE flashget.0041DE7B
0041DD3B  |. 8BCE           MOV ECX,ESI
0041DD3D  |. E8 89210B00    CALL flashget.004CFECB
0041DD42  |. 8BCE           MOV ECX,ESI
0041DD44  |. E8 36210B00    CALL flashget.004CFE7F
0041DD49  |. 8B0E           MOV ECX,DWORD PTR DS:[ESI]
0041DD4B  |. 8379 F8 05     CMP DWORD PTR DS:[ECX-8],5
0041DD4F  |. 0F8E 26010000  JLE flashget.0041DE7B
0041DD55  |. 68 BCE55200    PUSH flashget.0052E5BC
0041DD5A  |. 8BCE           MOV ECX,ESI
0041DD5C  |. E8 851D0B00    CALL flashget.004CFAE6
0041DD61  |. 85C0           TEST EAX,EAX
0041DD63  |. 0F8C 12010000  JL flashget.0041DE7B
0041DD69  |. 68 B8E55200    PUSH flashget.0052E5B8
0041DD6E  |. 8BCE           MOV ECX,ESI
0041DD70  |. E8 711D0B00    CALL flashget.004CFAE6
0041DD75  |. 85C0           TEST EAX,EAX
0041DD77  |. 0F8C FE000000  JL flashget.0041DE7B
0041DD7D  |. 8BCD           MOV ECX,EBP
0041DD7F  |. E8 47210B00    CALL flashget.004CFECB
0041DD84  |. 8BCD           MOV ECX,EBP
0041DD86  |. E8 F4200B00    CALL flashget.004CFE7F
0041DD8B  |. 8B55 00        MOV EDX,DWORD PTR SS:[EBP]
0041DD8E  |. 8B42 F8        MOV EAX,DWORD PTR DS:[EDX-8]
0041DD91  |. 83F8 2C        CMP EAX,2C
0041DD94  |. 0F85 E1000000  JNZ flashget.0041DE7B
0041DD9A  |. 68 B0E55200    PUSH flashget.0052E5B0                   ;  ASCII "fgc-"
0041DD9F  |. 8BCD           MOV ECX,EBP
0041DDA1  |. E8 401D0B00    CALL flashget.004CFAE6
0041DDA6  |. 85C0           TEST EAX,EAX
0041DDA8  |. 75 06          JNZ SHORT flashget.0041DDB0
0041DDAA  |. 895C24 10      MOV DWORD PTR SS:[ESP+10],EBX
0041DDAE  |. EB 18          JMP SHORT flashget.0041DDC8
0041DDB0  |> 68 A8E55200    PUSH flashget.0052E5A8                   ;  ASCII "fgf-"
0041DDB5  |. 8BCD           MOV ECX,EBP
0041DDB7  |. E8 2A1D0B00    CALL flashget.004CFAE6
0041DDBC  |. 85C0           TEST EAX,EAX
0041DDBE  |. 0F85 B7000000  JNZ flashget.0041DE7B
0041DDC4  |. 894424 10      MOV DWORD PTR SS:[ESP+10],EAX
0041DDC8  |> 6A 2C          PUSH 2C
0041DDCA  |. 8BCD           MOV ECX,EBP
0041DDCC  |. E8 7A680B00    CALL flashget.004D464B
0041DDD1  |. 8BF8           MOV EDI,EAX
0041DDD3  |. 33C9           XOR ECX,ECX
0041DDD5  |. 83C7 04        ADD EDI,4
0041DDD8  |. 33F6           XOR ESI,ESI
0041DDDA  |> 8B07           /MOV EAX,DWORD PTR DS:[EDI]
0041DDDC  |. 8BD6           |MOV EDX,ESI
0041DDDE  |. 83C7 04        |ADD EDI,4
0041DDE1  |. 83EA 00        |SUB EDX,0                               ;  Switch (cases 0..2)
0041DDE4  |. 894424 1C      |MOV DWORD PTR SS:[ESP+1C],EAX
0041DDE8  |. 74 26          |JE SHORT flashget.0041DE10
0041DDEA  |. 4A             |DEC EDX
0041DDEB  |. 74 17          |JE SHORT flashget.0041DE04
0041DDED  |. 4A             |DEC EDX
0041DDEE  |. 75 38          |JNZ SHORT flashget.0041DE28
0041DDF0  |. 0FBE4C24 1E    |MOVSX ECX,BYTE PTR SS:[ESP+1E]          ;  Case 2 of switch 0041DDE1
0041DDF5  |. 0FBED4         |MOVSX EDX,AH
0041DDF8  |. 0FAFCA         |IMUL ECX,EDX
0041DDFB  |. 0FBE5424 1F    |MOVSX EDX,BYTE PTR SS:[ESP+1F]
0041DE00  |. 03CA           |ADD ECX,EDX
0041DE02  |. EB 1F          |JMP SHORT flashget.0041DE23
0041DE04  |> 0FBE4C24 1E    |MOVSX ECX,BYTE PTR SS:[ESP+1E]          ;  Case 1 of switch 0041DDE1
0041DE09  |. 0FBED4         |MOVSX EDX,AH
0041DE0C  |. 23CA           |AND ECX,EDX
0041DE0E  |. EB 0B          |JMP SHORT flashget.0041DE1B
0041DE10  |> 8A4C24 1E      |MOV CL,BYTE PTR SS:[ESP+1E]             ;  Case 0 of switch 0041DDE1
0041DE14  |. 8AD4           |MOV DL,AH
0041DE16  |. 33CA           |XOR ECX,EDX
0041DE18  |. 83E1 7F        |AND ECX,7F
0041DE1B  |> 0FBE5424 1F    |MOVSX EDX,BYTE PTR SS:[ESP+1F]
0041DE20  |. 0FAFCA         |IMUL ECX,EDX
0041DE23  |> 0FBEC0         |MOVSX EAX,AL
0041DE26  |. 03C8           |ADD ECX,EAX
0041DE28  |> 8B4424 10      |MOV EAX,DWORD PTR SS:[ESP+10]           ;  Default case of switch 0041DDE1
0041DE2C  |. 85C0           |TEST EAX,EAX
0041DE2E  |. 74 0C          |JE SHORT flashget.0041DE3C
0041DE30  |. 0FBE1D 2BC7520>|MOVSX EBX,BYTE PTR DS:[52C72B]
0041DE37  |. 83FE 02        |CMP ESI,2
0041DE3A  |. 74 07          |JE SHORT flashget.0041DE43
0041DE3C  |> 0FBE9E 28C7520>|MOVSX EBX,BYTE PTR DS:[ESI+52C728]
0041DE43  |> 8BC1           |MOV EAX,ECX
0041DE45  |. 33D2           |XOR EDX,EDX
0041DE47  |. F7F3           |DIV EBX
0041DE49  |. 8BC6           |MOV EAX,ESI
0041DE4B  |. 83E8 00        |SUB EAX,0                               ;  Switch (cases 0..2)
0041DE4E  |. 74 13          |JE SHORT flashget.0041DE63
0041DE50  |. 48             |DEC EAX
0041DE51  |. 74 09          |JE SHORT flashget.0041DE5C
0041DE53  |. 48             |DEC EAX
0041DE54  |. 75 11          |JNZ SHORT flashget.0041DE67
0041DE56  |. 85D2           |TEST EDX,EDX                            ;  Case 2 of switch 0041DE4B
0041DE58  |. 75 18          |JNZ SHORT flashget.0041DE72
0041DE5A  |. EB 0B          |JMP SHORT flashget.0041DE67
0041DE5C  |> 83FA 08        |CMP EDX,8                               ;  Case 1 of switch 0041DE4B
0041DE5F  |. 75 11          |JNZ SHORT flashget.0041DE72
0041DE61  |. EB 04          |JMP SHORT flashget.0041DE67
0041DE63  |> 85D2           |TEST EDX,EDX                            ;  Case 0 of switch 0041DE4B
0041DE65  |. 75 0B          |JNZ SHORT flashget.0041DE72
0041DE67  |> 46             |INC ESI                                 ;  Default case of switch 0041DE4B
0041DE68  |. 83FE 03        |CMP ESI,3
0041DE6B  |. 7D 23          |JGE SHORT flashget.0041DE90
0041DE6D  |.^E9 68FFFFFF    \JMP flashget.0041DDDA
0041DE72  |> 6A FF          PUSH -1
0041DE74  |. 8BCD           MOV ECX,EBP
0041DE76  |. E8 1F680B00    CALL flashget.004D469A
0041DE7B  |> 5F             POP EDI
0041DE7C  |. 5E             POP ESI
0041DE7D  |. 5D             POP EBP
0041DE7E  |. 33C0           XOR EAX,EAX
0041DE80  |. 5B             POP EBX
0041DE81  |. 8B4C24 20      MOV ECX,DWORD PTR SS:[ESP+20]
0041DE85  |. 64:890D 000000>MOV DWORD PTR FS:[0],ECX
0041DE8C  |. 83C4 2C        ADD ESP,2C
0041DE8F  |. C3             RETN
0041DE90  |> 6A FF          PUSH -1
0041DE92  |. 8BCD           MOV ECX,EBP
0041DE94  |. E8 01680B00    CALL flashget.004D469A
0041DE99  |. 8B45 00        MOV EAX,DWORD PTR SS:[EBP]
0041DE9C  |. 8B4C24 18      MOV ECX,DWORD PTR SS:[ESP+18]
0041DEA0  |. 6A 01          PUSH 1
0041DEA2  |. 50             PUSH EAX
0041DEA3  |. 68 A0C15200    PUSH flashget.0052C1A0                   ;  ASCII "General"
0041DEA8  |. E8 37C50C00    CALL flashget.004EA3E4
0041DEAD  |. 8B4C24 30      MOV ECX,DWORD PTR SS:[ESP+30]
0041DEB1  |. 5F             POP EDI
0041DEB2  |. F7D8           NEG EAX
0041DEB4  |. 1BC0           SBB EAX,EAX
0041DEB6  |. 5E             POP ESI
0041DEB7  |. 5D             POP EBP
0041DEB8  |. 5B             POP EBX
0041DEB9  |. F7D8           NEG EAX
0041DEBB  |. 64:890D 000000>MOV DWORD PTR FS:[0],ECX
0041DEC2  |. 83C4 2C        ADD ESP,2C
0041DEC5  \. C3             RETN

以上的代码就是判断RegPass是否正确的子程序了
我们再精简一下,只留下跳转语句、返回语句和跳转到的语句:

0041DC80  /$ 6A FF          PUSH -1
0041DD27  |. 0F84 4E010000  JE flashget.0041DE7B                     ;没有regpass的话在这里就跳了
0041DD35  |. 0F84 40010000  JE flashget.0041DE7B
0041DD4F  |. 0F8E 26010000  JLE flashget.0041DE7B
0041DD63  |. 0F8C 12010000  JL flashget.0041DE7B
0041DD77  |. 0F8C FE000000  JL flashget.0041DE7B
0041DD94  |. 0F85 E1000000  JNZ flashget.0041DE7B                    ;如果有个随便写的注册码的话在这里跳
0041DDA8  |. 75 06          JNZ SHORT flashget.0041DDB0
0041DDAE  |. EB 18          JMP SHORT flashget.0041DDC8
0041DDB0  |> 68 A8E55200    PUSH flashget.0052E5A8                   ;  ASCII "fgf-"
0041DDBE  |. 0F85 B7000000  JNZ flashget.0041DE7B
0041DDC8  |> 6A 2C          PUSH 2C
0041DDDA  |> 8B07           /MOV EAX,DWORD PTR DS:[EDI]
0041DDE8  |. 74 26          |JE SHORT flashget.0041DE10
0041DDEB  |. 74 17          |JE SHORT flashget.0041DE04
0041DDEE  |. 75 38          |JNZ SHORT flashget.0041DE28
0041DE02  |. EB 1F          |JMP SHORT flashget.0041DE23
0041DE04  |> 0FBE4C24 1E    |MOVSX ECX,BYTE PTR SS:[ESP+1E]          ;  Case 1 of switch 0041DDE1
0041DE0E  |. EB 0B          |JMP SHORT flashget.0041DE1B
0041DE10  |> 8A4C24 1E      |MOV CL,BYTE PTR SS:[ESP+1E]             ;  Case 0 of switch 0041DDE1
0041DE1B  |> 0FBE5424 1F    |MOVSX EDX,BYTE PTR SS:[ESP+1F]
0041DE23  |> 0FBEC0         |MOVSX EAX,AL
0041DE28  |> 8B4424 10      |MOV EAX,DWORD PTR SS:[ESP+10]           ;  Default case of switch 0041DDE1
0041DE2E  |. 74 0C          |JE SHORT flashget.0041DE3C
0041DE3A  |. 74 07          |JE SHORT flashget.0041DE43
0041DE3C  |> 0FBE9E 28C7520>|MOVSX EBX,BYTE PTR DS:[ESI+52C728]
0041DE43  |> 8BC1           |MOV EAX,ECX
0041DE4E  |. 74 13          |JE SHORT flashget.0041DE63
0041DE51  |. 74 09          |JE SHORT flashget.0041DE5C
0041DE54  |. 75 11          |JNZ SHORT flashget.0041DE67
0041DE58  |. 75 18          |JNZ SHORT flashget.0041DE72
0041DE5A  |. EB 0B          |JMP SHORT flashget.0041DE67
0041DE5C  |> 83FA 08        |CMP EDX,8                               ;  Case 1 of switch 0041DE4B
0041DE5F  |. 75 11          |JNZ SHORT flashget.0041DE72
0041DE61  |. EB 04          |JMP SHORT flashget.0041DE67
0041DE63  |> 85D2           |TEST EDX,EDX                            ;  Case 0 of switch 0041DE4B
0041DE65  |. 75 0B          |JNZ SHORT flashget.0041DE72
0041DE67  |> 46             |INC ESI                                 ;  Default case of switch 0041DE4B
0041DE6B  |. 7D 23          |JGE SHORT flashget.0041DE90
0041DE6D  |.^E9 68FFFFFF    \JMP flashget.0041DDDA
0041DE72  |> 6A FF          PUSH -1
0041DE7B  |> 5F             POP EDI                                  ;这里已经判断是没注册的了
0041DE8F  |. C3             RETN                                     ;这里返回,跳出了检查注册码的子函数,返回到了004128EB
0041DE90  |> 6A FF          PUSH -1
0041DEC5  \. C3             RETN

分析一下,可以发现:
a、很多跳转是到的0041DE7B。跳到0041DE7B以后,就是一个retn,返回了。
而这里返回就是被发现是未注册的了。
b、其他跳转都是在内部跳的,都是循环,不会跳出去,除了一个:
0041DE6B JGE SHORT flashget.0041DE90
他跳到了0041DE90,然后就是一个返回,所以说只可能这个是注册的返回。

现在,我们可以对上面的这个子程序做一个总体分析,
0041DC80-0041DDD8是初始判断
而0041DDDA-0041DE6D是进阶判断
0041DE7B-0041DE8F是注册码错误时的返回
0041DE90-0041DEC5是注册码正确时的返回

所以我们只要在一开始就跳到0041DE90就可以了
我的方法是在0041DD27把JE 0041DE7B修改成jmp 0041DE90
在odbg里面修改以后,记录二进制代码为E96401000090

五、修改文件

用WinHex或者UltraEdit修改
找到0001DD27(0041DD27)
把0F844E010000修改成E96401000090
OK,成功!

说明:

fg1.65和网上说的前面几个版本不同,不能直接从寄存器里面得到注册码的
而是通过对你提供的注册码的一步步循环的计算来判断是否正确
所以这里只是修改文件,并没有找出注册码的计算方法。
以前使用算号器,过了一段时候以后又会出现广告
据lucian说,是fg会上网验证的
所以还是直接修改文件保险、简单。

后记:

后来看了一下调用这个子程序的代码004128EB附近的代码
发现这个子程序的作用就是当注册码错误时,使EAX为0;
当注册码正确时(经上述5步破解),使EAX为1,然后
004128f2 MOV DWORD PTR SS:[EBP+284],EAX
只要令DWORD PTR SS:[EBP+284](0053bb74)不为0就去了广告
修改MOV DWORD PTR SS:[EBP+284],EAX为MOV DWORD PTR SS:[EBP+284],ECX
更或者004128EB CALL 0041DC80改成nop或者CALL 00425790(mov eax,1)
这样也少执行一段代码。

一开始我用的是w32dasm反编译的,
因为发现它比较容易上手,但是调试不太方便,太占cpu,反汇编太慢;
而odbg界面比较复杂,调试比较方便,所以开始我是两种工具结合使用的,
而后来随着对odbg的熟悉,全部使用odbg完成。