利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还可以修改已有的程序集,并且它支持多个运行时框架上例如:.net2.0/3.5/4.0,以及silverlight程序
官方地址:http://www.mono-project.com/Cecil
首先,我先假想有一个这样的商业组件,该组件满足了以下条件:
1. 该程序集的代码被混淆过了
2. 该程序集被强命名签名过了
3. 该程序集的UI界面被加上了版权信息,例如水印等等
这里我引用的是之前写的一篇文章中的用户登录的组件(http://www.cnblogs.com/liping13599168/archive/2010/05/07/1729357.html),并将其进行改造成一个Silverlight组件,项目结构如图:
其中BusinessComponent类库作为选定的”商业组件",这里编写一个CopyRight类,作为水印的打印信息:
internal sealed class Copyright
{
internal void SetRightInfo(TextBlock textBlock)
{
textBlock.Text = "This is a watermark.";
}
}
运行效果为:
可以看到组件上面附带一个版权信息效果
接着,要对BusinessComponent进行强命名签名,选择项目右键,如下设置:
新建一个snk文件,这个文件利用RSA加密包含着公钥和私钥的信息,对该组件编译会把它编译进去了。
这个snk到底做什么用的呢?一会儿大家看着就知道了。
最后,我要利用Dotfuscator混淆工具,对于BusinessComponent.dll进行代码混淆
由于我这里的Dotfuscator使用的老版本的4.2,所以不支持对于Sliverlight程序集的混淆,有兴趣的朋友可以自己下载试试,官方地址是:http://www.preemptive.com
好了,到这里,一个BusinessComponent商业组件的雏形设计好了。现在拿起手上的工具——Mono.Cecil去改造它了。
首先官方下载了一个mono.cecil的项目,打开工程主动去编译一下,在目录Silverlight_Release就能够获取Mono.Cecil.dll
那么,把它引入到项目中来,在页面中加入一个按钮,点击触发事件程序:
var entryPointPart = Deployment.Current.Parts.First(asmPart => asmPart.Source == "BusinessComponent.dll");
var entryPointResourceInfo = Application.GetResourceStream(new Uri(entryPointPart.Source, UriKind.Relative));
var module = ModuleDefinition.ReadModule(entryPointResourceInfo.Stream);
var type = module.Types.FirstOrDefault(o => o.Name == "Copyright");
var method = type.Methods.FirstOrDefault(o => o.Name == "SetRightInfo");
Instruction instruction = method.Body.Instructions[];
instruction.Operand = "";
module.Write("C:\\BusinessComponent.dll");
其中module获取程序集中的Module模块,module.Types可以得到程序集中的所有类型:
选择Type的类型名称为Copyright,通过type.Methods可以得到该类型得到的所有方法:
选择Method的名称为SetRightInfo,method.Body.Instructions可以得到该方法里面的IL堆栈调用信息:
我们看到索引2这行的信息,ldstr是定义一个字符串常量的方式,而索引3通过索引2行的值,赋值给TextBlock中,请查看Copyright的代码就可以知道。于是:
Instruction instruction = method.Body.Instructions[];
instruction.Operand = "";
这样就可以把该水印信息去除了,是不是很简单呢:)
最后一行module.Write("C:\\BusinessComponent.dll");就是将修改过后的程序集重新写入到一个新的程序集中;
执行程序,在C盘就得到一个BusinessComponent的新程序集了。
现在,我重新引入该新的程序集,看是否水印信息会被去掉,重新编译,发现编译出错:
这是为什么?这就是我上面提到的利用snk的强命名签名了,它的目的是为了防止你的程序集被非法篡改而设置的,而需要破解它就需要它的私钥了,可是作为一个真正的商业组件,我们是没有办法得到它的私钥,那是不是意味着没办法破解了呢。
那么我重新通过sn.exe进行重新签名:
sn –R BusinessComponent.dll mykey.snk
显示公钥不配对。这个是显然的,因为之前通过VS的Sign标签人工设置business.snk,它采用的是这个文件的公钥,而mykey.snk就要采用它自己的公钥了。
既然无法破解,那我就去改掉它的签名,利用我自定义的公钥和私钥去做签名,而恰恰好,Mono.Cecil就可以满足你的需要。
打开VS2010命令提示窗口,在C盘上输入:
sn -k mykey.snk
这样就随机产生了一条包含公钥和私钥的RSA文件,接着要抽取出它的公钥,输入:
sn –p mykey.snk mykey.PublicKey
紧接着输入:
sn –tp mykey.PublicKey
就可以得到公钥的数据,例如publicKey以及publicKeyToken
得到了两串字符串,把它们都复制出来,继续在刚才的按钮代码中补充:
var entryPointPart = Deployment.Current.Parts.First(asmPart => asmPart.Source == "BusinessComponent.dll");
var entryPointResourceInfo = Application.GetResourceStream(new Uri(entryPointPart.Source, UriKind.Relative));
var module = ModuleDefinition.ReadModule(entryPointResourceInfo.Stream);
module.Assembly.Name.PublicKey = this.GetPublicKey();
module.Assembly.Name.PublicKeyToken = this.GetPubliKeyToken();
private byte[] GetPublicKey()
{
string s = "0024000004800000940000000602000000240000525341310004000001000100c5f2c7d8057257ea3640b93b7a98b1a5501718196589973b09b94cf47fb246c8ad86ae688caa36959d9793702c27ce198a447d69ba0ddac70075fab16748999f066795de472dfb5cd9347a10f967e750ca388aaa9a66619291003345b0176dec0008d3d88986c4605c0d60e3b6563f96984c6d28aeb4bf2d672e8d2d2123c394";
return this.StrToHexBytes(s);
}
private byte[] GetPubliKeyToken()
{
string s = "d2850434514ae5ca";
return this.StrToHexBytes(s);
}
private byte[] StrToHexBytes(string hexString)
{
hexString = hexString.Replace(" ", "");
if ((hexString.Length % ) != )
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / ];
for (int i = ; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * , ), );
return returnBytes;
}
其中StrToHexBytes方法,将字符串转换为十六进制的字节数组
重新编译执行,它的公钥信息就已经编译进去了,同样在C盘生成BusinessComponent.dll新程序集
这个时候,先不着急引入程序集,先对新程序集通过私密对其进行重新签名,输入命令:
OK,现在就可以重新引入了,这个时候再重新编译代码:
编译通过了。
现在运行下程序(这里要注意,你必须将SilverlightApp程序切换到OOB模式,才可以修改程序集):
水印信息已经被去除了:)
Mono.Cecil还可以用来做很多东西,比如说可以在一个方法中增加其他代码,能够细到IL中的每一个执行步骤,所以通过它可以做很多有意思的东西,比如说单元测试中的Mock对象以及性能上更佳的反射功能。
附上本文源代码:SilverlightMonoCecilDemo.rar
利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)的更多相关文章
- 教你怎么用Mono Cecil - 动态注入 (注意代码的注释)
原文 教你怎么用Mono Cecil - 动态注入 (注意代码的注释) 使用 Mono Cecil 进行反编译:using Mono.Cecil; using Mono.Cecil.Cil; //.. ...
- 使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入 用于写Log) [此文报考 xxx is declared in another module and needs to be imported的解决方法]-摘自网络
目录 一:普通写法 二:注入定义 三:Weave函数 四:参数构造 五:业务编写 六:注入调用 7. 怎么调用别的程序集的方法示例 8. [is declared in another module ...
- Mono.Cecil
Mono Cecil十分强大,强大到可以静态注入程序集(注入后生成新的程序集)和动态注入程序集(注入后不改变目标程序集,只在运行时改变程序集行为),它甚至可以用来调试PDB MDB调试符号格式文件. ...
- 基于Mono.Cecil的静态注入
Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...
- 编译时MSIL注入--实践Mono Cecil(1)
原文:编译时MSIL注入--实践Mono Cecil(1) 紧接上两篇浅谈.NET编译时注入(C#-->IL)和浅谈VS编译自定义编译任务—MSBuild Task(csproject),在第一 ...
- C# 动态修改dll的签名 以及修改引用该dll文件的签名
在读取RedisSessionStateProvider配置 提到用mono ceil 来修改程序集以及它的签名,里面GetPublicKey 和GetPubliKeyToken 方法里面那个字符串的 ...
- 运用Mono.Ceci类库修改.NET程序集 走上破解软件的道路
代码注入在C++时代很流行,主要是对现有的程序做一些修改,以达到预期的目的.一部分的破解程序,注册机也是借助于此方法,让被注入的程序绕过验证,达到破解的目录.在.NET中,借助于Mono.Cecil程 ...
- 运用Mono.Cecil 反射读取.NET程序集元数据
CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...
- Mono.Cecil 修改目标.NET的IL代码保存时报异常的处理。
使用Mono.Cecil对目标.NET的DLL程序进行IL修改后保存时报“Failed to resolve assembly: ' xxxxxx, version=xxxxx,Culture=xxx ...
随机推荐
- java程序错误类型及异常处理
一.程序的错误类型 在程序设计中,无论规模是大是小,错误总是难免的.程序的设计很少有能够一次完成,没有错误的(不是指HelloWorld这样的程序,而是要实现一定的功能,具备一定实用价值的程序),在编 ...
- 删除input或textarea输入框在移动版显示的阴影(Safari/iPhone)
移动端浏览网页元素时,自动给input和textarea添加了内部阴影的效果,只需加入样式即可去除 input,textarea{-webkit-appearance: none;} input[ty ...
- MVC Razor中 如何截断字符串
有时候显示的内容过长,使用MVC编程时,如何截断显示的内容呢.我知道你肯定有很多办法这样做的,但是在学习MVC时,还是使用一些新的办法做吧> Razor 标记语法编程. @helper Trun ...
- 表单验证插件 jquery.validata 使用方法
参考资料:http://www.runoob.com/jquery/jquery-plugin-validate.html 下载地址 jquery.validate插件的文档地址http://docs ...
- 浅谈JSP(一)
一.JSP引言 JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计.它是在传统的网页HTML文件(*.htm,*.html)中插入Java ...
- BZOJ 1296: [SCOI2009]粉刷匠( dp )
dp[ i ][ j ] = max( dp[ i - 1 ][ k ] + w[ i ][ j - k ] ) ( 0 <= k <= j ) 表示前 i 行用了 j 次粉刷的机会能正 ...
- Linux学习之Shell编程基础
转自:http://my.oschina.net/itblog/blog/204410 1 语法基本介绍1.1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来 ...
- PHP解析和生成xml(DOMDocument版)
上次和大家分享了SimpleXML操作xml的一些知识,但是php中除了simplexml还有DOMDocument,这次就着重来看看DOMDocument的用法,还是把生成xml和解析xml分开写 ...
- win7 64位的PHP5.4安装redis扩展
先看phpinfo.php信息 可以看是 PHP5.4 VC9 TS Architecture x86 说明是x86的PHP,虽然系统是64位的,所以还是要下载x86的redis 然后Github下载 ...
- linux里source、sh、bash、./有什么区别
在linux里,source.sh.bash../都可以执行shell script文件,那它们有什么不同吗? ----------- 1.source source a.sh 在当前shell内去读 ...