Resco MobileForms Toolkit 2010的破解(转)
五
一期间哪也没去,潜心研究了一下C#.
以前写Win程序一直在用C+SDK,程序小而快,但写起来太麻烦,80%的时间都用在了UI上。MFC不对我的胃口,看过一眼就扔掉了。我最早接触的是
VB,画图一样的编程和简洁明快的语法让我一直很怀念,MFC既没有VB的开发效率又没有SDK的运行效率,在这种情况下我宁可用SDK.
反正我又不是IT专业的,不需要写太大的win程序。
经典VB在VB6之后断档,变成了VB.NET,当初觉得变化太大无法适应(主要是不能用API了)所以转向了VC.
这次心血来潮学C#,看了一下简介就顿生“this is
it”之感——我要的就是这个!作为编程语言家族中的晚辈,C#继承了前辈的各种优点,语法相当优雅,比如我一直无比怀念的Property
Let和Property
Get终于在C-like语言中得以实现,不必再使用丑陋的get_a()和set_a()这种东西了。从C++转向C#也不用费太多力气,现用现学都来
得及。
以前写程序片面追求效率,现在想开了,对非运算密集型的Win应用程序而言,花在UI上的执行时间远大于数据运算,在这种情况下
productivity才是最重要的,现在用VC#终于找到了当年用VB写程序的感觉。中间用C+SDK的几年也不算浪费,毕竟了解系统的底层运作方式
还是挺有用处的。
本文仅限于.NET学习研究目的,严禁用于商业用途。本人不会以任何形式传播RMT破解后的二进制版本,请勿留言或来信索要;本人不为本文提供任何形式的技术支持。
最
近在写一个用于WM6的.NET CF程序,希望能够实现指划操作。这种功能如果用native code实现是要死人的,.NET
CF下倒是有不少好办法。一个开源的实现见Codeproject上的Fluid(作者已将控件部分放到fluid.codeplex.com),不过由
于是强大的作者自娱自乐的产品,虽然能用,但文档几乎没有,用起来很麻烦。在网上找来找去,发现Resco MobileForms
Toolkit(下简称RMT)这个神器,但是最新的2010版只有evaluation,看了一下的确不错,但是最便宜的license也要将近一千
刀……Google倒是能找到不少结果,不过都是各类下载网站骗流量的。无奈之下只好自己动手丰衣足食,尝试crack一下,顺便了解一下.NET的工作
机理。
RMT
2010的保护方式是:设计器只能用30天,控件不限时间,但是每次运行时都有消息框提示。设计器的时间限制比较简单,信息就存放在注册表
HKCU\Software\Resco\Resco MobileForms
Toolkit的默认值中,只要在新安装后将其保存起来,定期导回注册表即可。重点在于控件的crack,具体说来就是消除evaluation消息框。
.NET
程序的托管代码被“编译”为伪汇编代码(MSIL),由实时编译器(JIT)在运行时进一步翻译为本机代码。MSIL与原程序几乎是一一对应的,有很多强
大的反汇编工具, 如著名的Reflector. 用Reflector打开RMT的dll一看,程序并没有混淆,Resco实在太厚道了。
以
AdvancedList为例,用Reflector导出其C#代码,搜索消息框中的Evaluation字样,很容易确定“罪魁祸首”是
RescoLicenseMessage::ShowEvaluationMessage(),下面用反汇编方法修改其内容,去掉弹出的消息框。
以下操作以.NET CF 3.5版本(\NET35\CF目录下)为例,均在“Visual Studio 命令提示”环境(在开始菜单里找)中完成。
用ildasm反汇编Resco.AdvancedList.CF3.dll:
ildasm /utf8 /out=Resco.AdvancedList.CF3.il Resco.AdvancedList.CF3.dll
找个文本编辑器打开生成的Resco.AdvancedList.CF3.il,定位到上面的函数:
.method assembly hidebysig static void ShowEvaluationMessage(class [mscorlib]System.Type 'type', string text) cil managed
{
// 代码大小 29 (0x1d)
.maxstack 8
IL_0000: ldsfld string Resco.Controls.AdvancedList.RescoLicenseMessage::MsgEval
IL_0005: ldarg.0
IL_0006: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
IL_000b: ldarg.1
IL_000c: call string [mscorlib]System.String::Format(string,
object,
object)
IL_0011: ldsfld string Resco.Controls.AdvancedList.RescoLicenseMessage::MsgEvalVersion
IL_0016: call valuetype
[System.Windows.Forms]System.Windows.Forms.DialogResult
[System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string, string)
IL_001b: pop
IL_001c: ret
} // end of method RescoLicenseMessage::ShowEvaluationMessage
这个就是MSIL,看起来很像汇编吧?前面的IL_0000等都是标号,用于跳转,不写也可以。要不弹出消息框,让子程序直接返回即可,也就是只留一句ret:
.method assembly hidebysig static void ShowEvaluationMessage(class [mscorlib]System.Type 'type', string text) cil managed
{
// 代码大小 29 (0x1d)
.maxstack 8
IL_0000: ret
} // end of method RescoLicenseMessage::ShowEvaluationMessage
保存文件,下面将其重新编译为dll. 由于原dll用了强命名(strong name),需要自己生成一个密钥对:
sn -k key.snk
并用此密钥对给编译得到的dll签名,否则生成的dll将不可用:
ilasm /dll /key=key.snk /res=Resco.AdvancedList.CF3.res Resco.AdvancedList.CF3.il
用在.NET CF中的dll还需要额外签几个dll,即DesignerMetadata目录中以asmmeta结尾的三个dll. 对于AdvancedList而言是以下三个:
Resco.AdvancedList.CF3.PocketPC.asmmeta.dll
Resco.AdvancedList.CF3.SmartPhone.asmmeta.dll
Resco.AdvancedList.CF3.WindowsCE.asmmeta.dll
用ildasm反汇编后用ilasm重新编译,用前面生成的密钥对签名。VS中的工具箱可能没有AdvancedList,重置一下工具箱即可。现在AdvancedList应该可用了,运行时不弹出消息框。
用这种方法可破解所有控件。可以用循环语句批量反汇编:
for %i in (*.dll) do ildasm /utf8 /out=%~ni.il %i
注意有几个native dll无法反汇编(文件名中有Native字样),记得删掉生成的il.
逐
个修改生成的MSIL,大部分控件的crack方法与AdvancedList一样,在
RescoLicenseMessage::ShowEvaluationMessage()函数体中留一句ret即可。Audio、Zip和
ImageBox控件不太一样,ImageBox似乎没有保护(未验证),Zip的修改点在ZipArchive::.cctor()和
ZipStream::.cctor(),Audio控件的修改点在Evaluation::.cctor(),总之盯着“evaluation”和
“MessageBox::Show”字样就没错,都不是很难改。
全部搞定以后批量编译:
for %i in (*.il) do ilasm /dll /key=key.snk /res=%~ni.res %i /quiet
cd DesignerMetadata
for %i in (*.asmmeta.dll) do ildasm /utf8 /out=%~ni.il %i
for %i in (*.il) do ilasm /dll /key=key.snk /res=%~ni.res %i /quiet
注意有几个dll无法通过PEVerify,不用担心,原来的dll也通不过……
到VS里重置一下工具箱应该就能用了。
总
结一下.NET程序的破解,整体上来说要比native程序容易一些,因为可以用Reflector方便地定位再反汇编破解,即使有名称混淆也要比直接读
汇编容易得多。虽然强命名带来了一些麻烦,但重新签名的难度也不是很大。像RMT这种弹出消息框的应该属于最容易crack的,盯着消息框的文字和
MessageBox::Show就行了;如果有license认证,一般都能找到验证license的函数如bool
IsValid()这种,将其函数体改成ldc.i4.1; ret两句MSIL(即return
true)即可。对付这种破解的方法也很简单,只需要在.NET程序中加入一些native代码,这种混合模式的程序可以用ildasm反汇编,但结果无
法用ilasm编译。不过很显然,这是防不住keygen的。