近日对目前较为流行的asp.net treeview 控件的性能进行了测试。如radtreeview,flytreeview,iewebcontroltreeview等。总体感觉,作为一个独立产品,flytreeview的外观更为俏丽,性能也最为丰富,可谓精雕细琢。用它遍历服务器硬盘,仿真资源管理器目录的速度是非常快的;它所具有的独一无二的异步加载功能,对那些梦想把全部数据都绑定到一个web树上,又不想影响客户端加载速度的程序开发者来讲,flytreeview切实能使我们鱼肉和熊掌兼得。用过一段时间的iewebcontroltreeview,深感其性能的平平,反应的迟缓,因而一见到flytreeview for asp.net 3.1 便爱不释手,flytreeview for asp.net 3.2 出来以后便立即下载了一个。由于试用期过后必须调整“座机”的系统时间才能继续使用,感觉很不方便,便决定自己动手,延长一下试用期,也借机学习一下优秀软件的编制技巧,了解一些书本上得不到的知识。
一、环境准备
1、基本环境:microsoft visual studio .net 200x开发环境和iis服务。
2、path环境:为方便在命令行上使用有关工具,需要确保更新系统的path环境变量。以使系统能在任何目录下都能找到所需的.net工具。为此,需要将 x:\program files\microsoft visual studio .net 2003 dk\v1.1\bin和x:\winnt\microsoft.net\framework\v1.1.4322(v1.0.3705)这两个目录的完整路径添加到path环境变量字符串的末尾,如(图一):
另外,为确保在任何目录下都能进入命令行,须对文件夹的右键菜单添加一个进入命令行的快捷选项。其方法见(图二)。这样,在资源管理器中当对需要进入命令行的文件夹右击鼠标的时候,就会出现图三的画面,选择“进入命令行”即可,免去了手工键入全路径的繁琐过程,见(图三)。 二、工具准备
1、反编译器:代码分析工具我用的是reflector 4.1.6.0 的试用版,可从 http://www.aisto.com/roeder/dotnet/下载最新版本,reflector 可以将目标代码反编译成il、c#、vb.net、 delphi四种语言,可供你根据自己的语言习惯进行选择。 reflector 试用版装载后如果出现过期问题,可通过调整系统时钟予以解决,当然,也可以试着用reflector自己把reflector的代码分析一下将这个问题解决了,但不这样做也不影响我们的后续工作。将控件完整的反编译成破解档的工具就使用环境中已有的microsoft免费提供的msil反汇编器ildasm。经过第一步的准备,我们已经可以在需要的时候在任何目录中调用它。
2、汇编程序:使用环境中已有的microsoft免费提供的msil汇编程序ilasm,通过使用 ilasm.exe 运行我们破解处理过的ildasm生成的有关文件以生成最终的破解控件。同 ildasm 一样,经过第一步的准备,我们已经可以在需要的时候在任何目录中调用它。
3、其他工具:记事本、计算器等,均为系统默认的工具、软件。 三、破解过程
1、安装flytreeview:运行flytreeview_for_asp_setup.3.2.exe,并注意安装过程中选中安装示例web应用程序。如(图四): 在浏览器中浏览示例页面,控件未过期时的正常画面如(图五):
将系统时钟向后调整(如一年)后,再次浏览上述页面,则控件立即抛出异常如下(图六):
2、控件分析:
在你喜欢的位置新建一文件夹,姑且起名为“flytreeview破解”,作为我们的工作目录;将示例站点bin目录中的ninerays.web.ui.webcontrols.flytreeview.dll拷贝一份到工作目录;用记事本在我们的工作目录里再新建两个批处理文件,以方便后续工作,代码如下:myildasm.batildasm ninerays.web.ui.webcontrols.flytreeview.dll
/output:ninerays.web.ui.webcontrols.flytreeview.il myilasm.batilasm /dll /resource:ninerays.web.ui.webcontrols.flytreeview.res
/output:ninerays.web.ui.webcontrols.flytreeview.dll /key:treekey.snk
ninerays.web.ui.webcontrols.flytreeview.il
基本准备就绪后,启动 reflector 打开工作目录中的ninerays.web.ui.webcontrols.flytreeview.dll,如(图七)
根据以往破解经验及之前破解flytreeview for asp.net 3.1 的经历,web控件的试用限制通常是在 new,render,init等位置实现。为此,我们直接展开ninerays.web.ui.webcontrols.flytreeview中的flytreeview类,以(图六)中抛出的异常信息“9rays.net flytreeview for asp.net trial license has expired.” 为线索,逐个浏览该类中的重点方法与函数的反汇编代码,发现异常是在flytreeview类的构造函数new()中抛出的,其高级语言代码如下:
c#代 码vb.net代码public flytreeview()
{
this._designpage = null;
this._clientruntimepath = “/aspnet_client/ninerays_web_
ui_webcontrols_flytreeview_3_2_83_3/”;
this._loadingmessage = “loading…”;
this._expandlevel = 0;
this._childindent = 0x12;
this._supportie55 = false;
this._oldselectednodekeylist = null;
this._restorevalue = null;
this._defaultnodetype = null;
this._nodeeventsargs = new arraylist();
this._selectednode = null;
if (datetime.now > global.trial_expire_date)
{
throw new exception(“9rays.net flytreeview
for asp.net trial license has expired.”);
}
this._nodetypes = new treenodetypecollection();
this._nodetypes._flytreeview = this;
this.font.name = “tahoma”;
this.font.size = fontunit.xsmall;
this.borderstyle = borderstyle.none;
this.clientruntimepath = “/aspnet_client/ninerays_web_
ui_webcontrols_flytreeview_3_2_83_3/”;
}
public sub new()
me._designpage = nothing
me._clientruntimepath = “/aspnet_client/ninerays_web_
ui_webcontrols_flytreeview_3_2_83_3/”
me._loadingmessage = “loading…”
me._expandlevel = 0
me._childindent = 18
me._supportie55 = false
me._oldselectednodekeylist = nothing
me._restorevalue = nothing
me._defaultnodetype = nothing
me._nodeeventsargs = new arraylist
me._selectednode = nothing
if (datetime.now > global.trial_expire_date) then
throw new exception(“9rays.net flytreeview
for asp.net trial license has expired.”)
end if
me._nodetypes = new treenodetypecollection
me._nodetypes._flytreeview = me
me.font.name = “tahoma”
me.font.size = fontunit.xsmall
me.borderstyle = borderstyle.none
me.clientruntimepath = “/aspnet_client/ninerays_web
_ui_webcontrols_flytreeview_3_2_83_3/”
end sub 相关截图见(图八):
显然,关键代码是:if (datetime.now > global.trial_expire_date) then
throw new exception(“9rays.net flytreeview for asp.net trial license has expired.”)
end if global.trial_expire_date中保存的应该是控件试用的最后期限,我们只要将global.trial_expire_date中的期限值向后延长一定年限就可以达到破解的要求了,因为我们毕竟不是要做该控件的注册机,不需要再做更复杂的分析。为此,我们在点击(图八)中蓝色加亮的trial_expire_date,转到静态全局类global,浏览其相关代码,我们找到了如下关键代码:
语 言代 码il汇编.method private hidebysig specialname rtspecialname static void .cctor() cil managed
{
// code size: 18 byte(s)
.maxstack 4
l_0000: ldsflda [mscorlib]system.datetime ninerays.web.ui.webcontrols.flytreeview.global::trial_expire_date
l_0005: ldc.i4 2004
l_000a: ldc.i4.8
l_000b: ldc.i4.3
l_000c: call instance void [mscorlib]system.datetime::.ctor(int32, int32, int32)
l_0011: ret
} c#static global()
{
global.trial_expire_date = new datetime(0x7d4, 8, 3);
}vb.netprivate shared sub new()
global.trial_expire_date = new datetime(2004, 8, 3)
end sub delphiconstructor global.create;
begin
global.trial_expire_date.create(2004, 8, 3)
end; 相应的截图见(图九):
在以上由reflector反编译出的代码中,以vb.net和delphi代码最为直观,它使我们一眼就看出该控件的最后使用期限为2004年8月3日。(不同时间下载或安装的flytreeview表现在代码中的截止日期可能不同,笔者未特意考证)
下一步的工作就是进入实际破解了。
3、控件破解:
在工作目录中双击反汇编批处理文件myildasm.bat,工作目录中便出现了反汇编后得出的ninerays.web.ui.webcontrols.flytreeview.il等相关文件,见下表:
ninerays.web.ui.webcontrols.flytreeview.il
ninerays.web.ui.webcontrols.flytreeview.resources.previews.iconless.gif
ninerays.web.ui.webcontrols.flytreeview.flynodeset.resources
ninerays.web.ui.webcontrols.flytreeview.flycontextmenu.bmp
ninerays.web.ui.webcontrols.flytreeview.resources.previews.default.gif
ninerays.web.ui.webcontrols.flytreeview.design.autoformatform.resources
ninerays.web.ui.webcontrols.flytreeview.resources.previews.msdn.gif
ninerays.web.ui.webcontrols.flytreeview.resources.previews.night.gif
ninerays.web.ui.webcontrols.flytreeview.flytreeview.bmp
ninerays.web.ui.webcontrols.flytreeview.design.prenodetypesbutton.resources
ninerays.web.ui.webcontrols.flytreeview.resources.previews.office-2003.gif
ninerays.web.ui.webcontrols.flytreeview.relitem.resources
ninerays.web.ui.webcontrols.flytreeview.resources.flytreeview.ico
ninerays.web.ui.webcontrols.flytreeview.resources.previews.windows-xp-explorer.gif
ninerays.web.ui.webcontrols.flytreeview.flynodeset.bmp
ninerays.web.ui.webcontrols.flytreeview.resources.previews.classic-explorer.gif
ninerays.web.ui.webcontrols.flytreeview.res
用记事本打开ninerays.web.ui.webcontrols.flytreeview.il,向后翻一至两页可以看到如下代码,这是用于控件签名的公钥,应将其删除,以避免破解后的控件的被gac踢出去且添加不进工具箱。
.publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 // .$…………..
00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00 // .$..rsa1……..
07 20 57 cd eb b7 1a 84 93 4b 53 79 1c 47 f2 fa // . w……ksy.g..
7e ae d6 6a d6 0f 43 77 3c dc 6c 32 89 1d 48 b2 // ~..j..cw<.l2..h.
b9 1a 9e e9 25 b2 6a 13 d9 2f 84 32 90 e8 97 44 // ….%.j../.2…d
e8 2e a2 29 6c bb dc 5a 31 c5 19 46 b9 23 72 96 // …)l..z1..f.#r.
5b d7 3f 0c 0a 2a 10 f3 0e 98 9d 28 31 12 5b 63 // [.?..*…..(1.[c
ee 08 92 7a 7a 63 f4 2e 96 47 36 79 47 ff 8d 32 // …zzc…g6yg..2
8b fa f4 af 7c 12 84 3d 0b 55 15 b1 d0 2d c2 7c // ….|..=.u…-.|
c1 29 30 41 fc 8e af 72 9c 4e 4f c6 0a a2 aa be ) // .)0a…r.no….. //应删除
在记事本中利用查找功能查找“0x7d4” (2004年),结合前面reflector反汇编时得到的有关线索,可以确定ninerays.web.ui.webcontrols.flytreeview.il中对应global()的构造函数的il汇编代码如下:.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// 代码大小 18 (0x12)
.maxstack 4
il_0000: ldsflda valuetype [mscorlib]system.datetime ninerays.web.ui.webcontrols.flytreeview.global::trial_expire_date
il_0005: ldc.i4 0x7d4
il_000a: ldc.i4.8
il_000b: ldc.i4.3
il_000c: call instance void [mscorlib]system.datetime::.ctor(int32,
int32,
int32)
il_0011: ret
} // end of method global::.cctor 将上述代码中的 0x7d4改为我们需要的年份就可以达到我们破解的目的。需要注意的是,新的年份值不可过大,否则可能超出操作系统支持的上限,那就可能出现“万年虫”了。这个值改为2050年就已经足够了,因为人们不可能在四十多年后还在使用这个版本的flytreeview,况且到那时,如果微软还侥幸存在的话,恐怕连dotnet都不知被它淘汰到哪里去了。2050对应的十六进制表示为 0x802,修改后保存ninerays.web.ui.webcontrols.flytreeview.il。
接下来就是使用汇编工具ilasm编译破解后的代码了。
在编译之前,我们对也对控件来个数字签名。(强名称不是必需的,也可以不做,但如果不想做的话请将myilasm.bat中的/key:treekey.snk指令删除)
要进行数字签名,首先要使用sn.exe产生签名密钥。在资源管理器中右击工作目录“flytreeview破解”的文件夹图标后在弹出菜单中选择“进入命令行”,然后再dos窗口键入 sn -k treekey.snk 回车。一个新的“随机密钥对”便存储到了工作目录下的treekey.snk文件中。
接下来便进入实际编译过程了。关闭dos窗口和reflector等软件,回到资源管理器,删除工作目录中的ninerays.web.ui.webcontrols.flytreeview.dll,然后双击工作目录中的批处理文件myilasm.bat,等编译工作结束,就可以看到一个新的ninerays.web.ui.webcontrols.flytreeview.dll出现在工作目录中。
至此,如果之前的工作没有失误的话,flytreeview控件的破解工作就结束了。 四、破解后的测试
启动 visual studio .net 2003,打开flytreeview示例站点samples目录中的示例项目samples.csproj,在解决方案资源管理器中将项目对ninerays.web.ui.webcontrols.flytreeview的引用删除,将对破解后的ninerays.web.ui.webcontrols.flytreeview的引用添加进来,并顺便将其添加到工具箱中。
重新生成samples项目后将系统日期向后调整数年,在浏览器中浏览示例站点,你会发现不再抛出异常。
为最后确认破解是否成功,换另外一台机器使用ip地址或域名方式访问该示例站点,一切正常。
至此,flytreeview for asp.net 3.2 的破解工作结束,如果你有兴趣的话,还可以为破解后的控件再做一个安装部署项目。这就不在本文探讨的范畴了。