第一次:破解之旅

本文记录了一次破解试用版表盘控件的过程,包括研究控件结构、使用Reflector反编译DLL、修改IL代码、处理强命名验证失败等问题。

    为了做一个设备的控制程序,在界面UI上需要用到一些“表盘”控件,最直接的想法,从网上下一个现成的拿来用呗。于是,上网,Google,跋山涉水,千辛万苦,踏破数双铁鞋,翻遍边边角角,终于在一个论坛上获得线索,一番顺藤摸瓜之后,当下来一个表盘控件的安装包。我得意的笑,我得意的笑。

笑过之后,双击Setup开始安装,一切顺利,Finish按钮之后,出来了Readme,还是English的,老眼昏花的我也没招,拿着放大镜一个字母一个字母的过了一遍,基本上了解到它的意思,就是说“本程序是试用版,提供60天试用期”,唉,心想,将就吧。

打开他的Demo,果不其然,一上来就是一个漂亮无比光芒无限极其醒目的对话框,提示说本软件为Trail版本,顺带给了个购买网址。关闭该对话框之后,进入了Demo的正文,一进去就开始高呼,这就是我想要的,呵呵,口水啊,流……

问题随之而来,我开发的这个程序,不属于商业应用范畴,但是用这个要花费892刀的第三方控件,实在是穷我所有也不能,但是又很想用,很想很想,真的,怎么办呢,忽然一个对程序员来说及其正常又特别邪恶的念头闪过——用破解的吧。呵呵,于是,继续Google,这次关键字里面加上了“破解”二字。

0.5个小时过去了,未果。

0.6个小时过去了,未果。

0.7个小时过去了,未果。

0.8个小时过去了,未果。

0.9个小时过去了,未果。

 1.0个小时过去了,未果。

……

就在失望、绝望之际,想起一句话,授人以鱼不如授人以渔,咱自己何不尝试着破解一遭呢?于是,开始破解之旅。

首先开始研究这个控件包的结构,发现其控件全部封装在一个DLL里面,而这个DLL又是专为.NET平台提供的。对这个DLL,使用VS里面的对象查看器一看,果然包含了所有的导出控件。消除顾忌若干。

接下来,就是如何查看这个DLL里面的逻辑了。这下想起了曾经下载过的大名鼎鼎的Reflector,该工具是著名的反编译工具。翻箱倒柜后,在硬盘的西南角里找到了这个东东,使用他打开这个DLL,呵呵,除了匿名函数、私有成员之外,其他公共方法的名称、参数、代码都一清二楚的展现出来了。于是又拿起放大镜,一个函数一个函数的过了之后,发现在控件的构造函数里面,有几句话很是可疑,如:

  frmPropertyPage page = new frmPropertyPage(gauge);

  if (page.ShowDialog(owner) == DialogResult.OK)

  {

       flag = true;

  }

  return flag;

然后再跟踪这里显示出的对话框,和Demo里运行前的对话框,完全一致。哈哈,找到了,心想,把这几行现实对话框的代码注释掉,直接返回true不就OK了嘛。

有了思路,那么如何修改这个已经编译好的二进制的DLL呢。首先,Reflector貌似是不行了,他可以把DLL导出成C#(或VB等其他.NET支持语言)文件及vsproj文件,但是对匿名函数、私有变量这些则无法准确还原,而其中夹杂的“$”符号,对C#编译器来说,是非法字符,但该字符对IL语言来说,确实合法字符,于是想,那能否把DLL导出成IL语言的文件然后再来修改呢——当然可以,.NET框架SDK里面就提供了一个ILDASM的工具,该工具就是来干这个的,嘿嘿,天无绝人之路……

于是,从Visual Studio Tools中运行命令行程序,键入ildasm,出现了反汇编程序的界面,使用它打开我们要破解的DLL,选择“文件-转储”,指定存放反汇编出来的IL文件的目录及文件名后,就可以顺利转出该DLL所对应的il文件。

使用文本编辑器打开该il文件,找到上述源代码所对应的il代码如下,

IL_019b:  ldloc.s    V_4

IL_019d:  newobj     instance void CSTSOFT.Win.GaugeComponent.Design.frmPropertyPage::.ctor(class CSTSOFT.Win.GaugeComponent.Gauge)

IL_01a2:  stloc.s    V_9

IL_01a4:  ldloc.s    V_9

IL_01a6:  ldarg.3

IL_01a7:  callvirt   instance valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.Form::ShowDialog(class [System.Windows.Forms]System.Windows.Forms.IWin32Window)

IL_01ac:  ldc.i4.1

IL_01ad:  bne.un.s   IL_01b1

 

IL_01af:  ldc.i4.1

IL_01b0:  stloc.0

IL_01b1:  leave      IL_02e7

Reflector反编译的代码中我们可以看出,只需要使用最后两句就可以到达目标了,对应到IL代码,也就是最后的三句,那么我们把其中不需要的部分全部nop掉,这样更改后的代码如下:

IL_019b:  nop

IL_019d:  nop

IL_01a2:  nop

IL_01a4:  nop

IL_01a6:  nop

IL_01a7:  nop

IL_01ac:  nop

IL_01ad:  nop

 

IL_01af:  ldc.i4.1

IL_01b0:  stloc.0

IL_01b1:  leave      IL_02e7

保存,退出文本编辑器。

       这下,问题又来了,如何把IL文件再编译成二进制的DLL或者EXE呢?别急,微软既然提供了ILDASM把二进制文件反汇编成IL文件,就会再提供一个工具把IL文件编译成二进制文件,这个工具就是ILASM

在命令行下,键入ILASM,使用帮助参数一看,嘿嘿,语法挺简单,基本上是一看就知道怎么用了。好,那就使用他编译吧,于是在命令行下键入:

D:\MyWorkDir\ilasm xxx.il /dll /out:xxxxxxx.dll

很快,成果出来了,ilasm顺利生成了一个DLL

       于是迫不及待的用这个DLL来构造了一个自己的Demo,在本机上运行,一切正常,心中一种窃喜:原来破解也并不太难,呵呵。

       然而,我高兴的太早。当把这个Demo拿到其他机器上运行时,出现一令人深恶痛绝咬牙切齿的经典红叉,说“强命名验证失败”。这下懵了,什么玩意儿啊,这是。

       赶紧再Google,这次运气较好,很快就得到高人的如下解释:

强名称保护用户不会使用一个被篡改的程序集。一个没有强名称的程序集只能被使用在非常小的范围内。如果你分发一个没有进行正确签名的程序集,将不能保证它没有被篡改。如果用户没有设置忽略强名称确认,CLR将会拒绝载入这个程序集。 下面任何一条都会引起这条规则校验失败:

1  这个程序集没有进行强名称签名

2  进行签名后,这个程序集被修改过。

3  程序集被设置成延迟签名

4  程序集签名失败

5  程序集需要一定的注册表设置才能通过强名称校验

看了这些,基本明白了“强命名”的用意了。说直白点就是,对于强名称验证过的dllexe等,修改将导致验证失败,不能正常运行。如果删除强名称或者用其他密钥对签名,会导致publickey不同,程序里一个AssemblyName.GetPublicKey就死翘了。

       那么如何解决这个问题呢?继续Google,发现网上有高人给出的解决方案——由于强命名是在.NET框架加载程序集时进行检查的,而进行检查的代码是在mscorlib中的三个函数,此高人说,咱把这三个函数Patch掉,不就从源头上解决了问题嘛!

       想一想,理倒是这个理,不过这未免也太因噎废食了吧,这样作了之后,对其他程序有啥子影响,还安全么?有其他更善良仁慈的做法呢?

继续猜想,既然程序发行方可以给程序集强命名,也就是一个公钥/私钥匹配的问题,那么我能否把要修改的文件中的公钥信息删除,然后自己再用自己创建的密钥进行加密呢。顺着这个思路,继续用文本编辑器打开IL文件,拿着放大镜走一遍,发现文件中程序集自身信息段中有publickey字样的一段信息,后面跟着一段二进制的字符串,如下:

.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........

           F5 66 6F 31 FB 4A 50 93 5C EC 00 D6 14 BD E5 61   // .fo1.JP.\......a

           DE 70 86 C9 45 BA FF 87 7C 51 51 D3 71 F5 D7 33   // .p..E...|QQ.q..3

           B5 FC 2A 70 D7 CA B1 E0 0C F8 B4 FB F4 19 66 D1  // ..*p..........f.

           6E 68 DC 05 1A B9 96 4E 07 EC B5 CE 76 B5 4D D8  // nh.....N....v.M.

           91 02 E8 EC 22 65 B6 5A 76 61 C8 30 D7 7E 10 25    // ...."e.Zva.0.~.%

           7F 81 0E DA 3C 46 08 65 E5 E5 25 7C C3 CC 57 D8   // ....<F.e..%|..W.

           22 11 D6 1E ED 01 0A 20 5E 9B 2A 58 6B 8D D3 94   // "...... ^.*Xk...

           F3 BD B8 B8 0C 9E B0 85 5D 4E 34 AB 4D 83 B1 A9 ) // ........]N4.M...

呵呵,我想,就他没错了。于是删除这段。保存后退出文本编辑器。

此后,使用SDK提供的SN工具,创建一个自己的snk文件,在命令行下加入:

D:\MyWorkDir\sn –k “xxx.snk”

之后,再使用ilasm工具编译IL文件,不过此时多提供了一个key参数,如下:

D:\MyWorkDir\ilasm xxx.il /dll /key:xxx.snk /out:xxxxxxx.dll

编译完成之后,再使用生成的DLL重新编译刚才写过的Demo,本机运行通过,再到其他机器上运行,没问题,呵呵,这下应该告一段落了。

 

       说明:写此文,只为记录自己一个历程,目的不再破解,而在于通过这一过程,使自己加深了对SDK中的各种工具乃至IL语言有了更深的了解。如果要构造商业软件,还是要尊重知识产权为先。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值