写给自己的 程序集&msil 扫盲
嘴上不说 心里却想MD 这家伙在博客园装了这么久的高手 竟然连这都不会 ,我去噢。
程序集签名
.net 下 “程序集” 什么东东 ,反正就是听着挺牛x的,其实就是指“一堆程序”从我们传统的C++封装的dll 认知 就是一个dll文件名 然后一个lib文件里面有对应的函数列表,把lib文件添加进去就OK了。
呐 现在我们来新建一个空白Asp.net网站
打开web.config 里面就有一些默认引用的程序集
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Xml.Linq, Version=3.5.0.0,Culture=neutral,PublicKeyToken=B77A5C561934E089"/>
</assemblies>
看见那些唧唧歪歪的属性没有 System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089 这都是些啥 ,这就是程序集信息 .net下对程序集的定义已经超出我们原来对dll文件认知的那种范畴了,程序集信息指代“一堆可用程序功能”经过签名的唯一电子标签信息。
系统目录的程序集称之为GAC ,global assembly cache,就是我们平常用的console.write()啊 messageBox.show()啊啥的 。他放在C:\WINDOWS\assembly 进入那个目录下后发现资源管理器的视图变得很特殊。发现只可查看属性 而不能拷走里面的文件。要拷走也可以 在dos命令行下就可以了 他是以命名空间为目录树存放的。
我们自己的程序集也可放到GAC里 需要这样做:
放到GAC下的程序集必须使用一个私钥进行签名(附加强名称)方式如下:
- 在vs命令行 sn -k d:/key.snk
- 写好代码 编译 csc /keyfile:d:/test.snk /target:library function.cs
- 会有个function.dll文件产生 使用命令gacutil /i function.dll安装
- 在上面空白的asp.net网站里我们平常都是右键->添加引用 然后选中dll文件。 代码中using 命名空间 然后就按常规的方式使用。现在我们不用了 只需要在web.config 的<assemblies>里添加一行就可以了,像这样:
<addassembly="Function,Version=0.0.0.0,Culture=neutral,PublicKeyToken=6ac36eab110b624e"/>
前几个值都知道 但是这个PublicKeyToken怎么看呢 直接在C:\WINDOWS\assembly就可看到:
其他各种方式都可以 比如sn -t 文件名。然后代码中using 命名空间 然后就按常规的方式使用。
普通程序集在不破坏pe文件结构的情况修改后是可以运行的。而经过强名称签名的则不可以,有效的保证了程序完整性.。
注意在.net3.5或以上版本不论在编译时选什么版本加了强名称都还是可以更改的。因为.net认为你的程序运行在一个"受信任的环境" 所以强名称验证是被pass的。但是加到GAC应该是加不进去的 加到GAC必定会进行强名称验证。要想进行强名称验证不被pass在app.config 里添加这样的配置:
<configuration>
<runtime>
<bypassTrustedAppStrongNames enabled="false"/>
</runtime>
</configuration>
附:
使用gacutil /i function.dll卸载
也可在C:\WINDOWS\assembly目录 选中程序集点右键 卸载。
csc命令的各种使用方式:
生成dll的签名文件:
D:\>sn -k keyfor_function.snk
附加签名编译为dll:
D:\>csc /keyfile:keyfor_function.snk /t:library function.cs
附加dll编译主调程序源码:
D:\>csc /reference:function.dll kit.cs
msil
.net运行时东西大部分的人是不会去刻意学他的,啥CLR 啊 JIT 啊 我也不懂 不能装高手 更不能拿出来吹。 入门的还是得给自己普及下。.net的exe是中间语言代码 这不得不说ilasm 跟ildasm,一个是编译 一个是反编译。先来演示一下怎样简单“破解”一个小程序。顺便我们也来玩玩ildsam
新建一个控制台程序
写几句代码:
using System;
namespace test
{
class Program
{
static void Main(string[] args)
{
//验证不通过程序立即退出
if (licence() == false)
{
Console.WriteLine("invalid license");
Console.ReadKey();
return;
}
else//验证成功 程序继续运行
{
Console.WriteLine("licence is ok");
Console.ReadKey();
}
}
static bool licence()
{
//假设这里是一个硬件ID授权认证
//共享软件的注册验证 根据硬盘串号通过指定加密算法得到密文 即注册码
//硬盘串号加密得到的密文跟注册码进行匹配
//如果不一样则认为软件已被拷到未被授权的电脑上使用 return false
return false;
}
}
}
在项目属性上->右键->属性
添加程序签名:
项目上->右键->添加->新建项->应用程序配置文件
项目下多了app.config
编辑它
<?xml version="1.0"?>
<configuration>
<runtime>
<bypassTrustedAppStrongNames enabled="false"/>
</runtime>
</configuration>
现在编译并运行
运行输出 invalid licence
很明显验证不通过
呐现在我们就来对他进行破解 让他验证通过
然后打开il dasm 工具
如果不知道在哪里打开 就在vs命令行里输入ildasm
然后打开我们在debug目录编译后的exe文件
代表test命名空间
代表program类
咦这啥东东 咱在代码里没写这个方法啊
咱在书上学过如果没有写构造方法 则编译时提供默认的构造方法
看 这里就是这个意思 ctor可能全称是 constructor
打开main函数 代码如下:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 (0x32)
.maxstack
.locals init ([] bool CS$4$0000)
IL_0000: nop
IL_0001: call bool test.Program::licence()
IL_0006: stloc.
IL_0007: ldloc.
IL_0008: brtrue.s IL_001e
IL_000a: nop
IL_000b: ldstr "invalid license"
IL_0010: call void [mscorlib]System.Console::WriteLine(string)
IL_0015: nop
IL_0016: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_001b: pop
IL_001c: br.s IL_0031
IL_001e: nop
IL_001f: ldstr "licence is ok"
IL_0024: call void [mscorlib]System.Console::WriteLine(string)
IL_0029: nop
IL_002a: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_002f: pop
IL_0030: nop
IL_0031: ret
} // end of method Program::Main
打开licence函数 代码如下:
.method private hidebysig static bool licence() cil managed
{
// 代码大小 (0x7)
.maxstack
.locals init ([] bool CS$1$0000)
IL_0000: nop
IL_0001: ldc.i4.
IL_0002: stloc.
IL_0003: br.s IL_0005
IL_0005: ldloc.
IL_0006: ret
} // end of method Program::licence
然后单击文件菜单->转储
保存为il 文件
我们只需要在main函数中更改条件判断 让他验证通过就可以了
用记事本打开保存的il文件
找到这一行 看到没有
IL_0008: brtrue.s IL_001e
如果改成这样呢
IL_0008: brfalse.s IL_001e
试下吧
改完后在vs命令行使用ilasm test.il 把il文件重新编译成exe文件
这时我们再次运行test.exe
咦怎么回事 不成功
未处理的异常: System.IO.FileLoadException: 未能加载文件或程序集“test, Version=
1.0.0.0, Culture=neutral, PublicKeyToken=e49d145887009c3e”或它的某一个依赖项。
强名称验证失败。 (异常来自 HRESULT:0x8013141A)
文件名:“test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e49d145887009c3e
” ---> System.Security.SecurityException: 强名称验证失败。 (异常来自 HRESULT:0x
8013141A)
失败的程序集的区域是:
MyComputer
因为有程序签名,所以我们还得把强名称去掉。
再次打开il文件
看到有这样3处开始的地方:
.publickeytoken
.publickey
.hash
把他们删除
然后再用ilasm编译 并运行发现验证成功
注意:
如果程序集加了强名称 改了pe文件的任何内容后都是无法启动的 就像有绑定的MD5校验一样。为了保护程序 都会使用混淆器进行处理 ,而混淆器正好又会更改文件内容。
另外:
说俗点高级语言也无非就
int var1=123
if(){
}
else{}
for(){}
这些之类的
看了下网上il的代码解析 以及以前看过一些对汇编的理解 虽然不用汇编做开发。
汇编是基于堆栈的 流水线 似的操作 ,事先初始化的变量在编译时都是确定好的 入栈出栈操作 ,每次都进行一个指令 对寄存器赋值 或者进行运算 地址跳转 等。
仔细想想有了这些基础特征就够了 高级语言的那些语法基本上都可以实现只不过要麻烦些
int var1=123
这个不说了
if(){
}
else{}
在汇编里估计是通过条件 地址跳转啥的来实现
for(){}
其实也很简单
看了一点il的代码 发现也就是一个连续if的过程 条件达不到跳转到前面的地址继续n++
像这样
int n=1;
loop:
n++;
console.writeline("hi");
if(n<50)
goto loop;
其实我不懂汇编语言的 有些乱说的见谅 勿喷。
写给自己的 程序集&msil 扫盲的更多相关文章
- C#程序集使用强名字(Strong Name)签名/强名称签名
强名称签名的方法: 强签名: 1. 可以将强签名的dll注册到GAC,不同的应用程序可以共享同一dll. 2. 强签名的库,或者应用程序只能引用强签名的dll,不能引用未强签名的dll,但是未强签名的 ...
- .NET核心代码保护策略-隐藏核心程序集
经过之前那个道德指责风波过后也有一段时间没写博客了,当然不是我心怀内疚才这么久不写,纯粹是程序员的通病..怎一个懒字了得,本来想写一些长篇大论反讽一下那些道德高人的.想想还是算了,那样估计会引来新一波 ...
- 今天写了一个简单的新浪新闻RSS操作类库
今天,有位群友问我如何获新浪新闻列表相关问题,我想,用正则表达式网页中取显然既复杂又不一定准确,现在许多大型网站都有RSS集合,所以我就跟他说用RSS应该好办一些. 一年前我写过一个RSS阅读器,不过 ...
- GAC的理解及其作用
转:http://www.cnblogs.com/smallstone/archive/2010/06/29/1767508.html 一.GAC的作用 全称是Global Assembly Cach ...
- 去掉ILDasm的SuppressIldasmAttribute限制
原文:去掉ILDasm的SuppressIldasmAttribute限制 今天本打算汉化一个.Net程序的,当用ILDasm打开的时候,出现了"受保护模块—无法进行反汇编"的错误 ...
- 【WCF】授权策略详解
所谓授权者,就是服务授予客户端是否具有调用某个服务操作的权限. 授权过程可以通过一系列授权策略来进行评估,即每个特定的授权策略都按照各自的需求,衡量一下调用方是否具备访问服务操作的权限.在默认情况下, ...
- Rafy 框架 - 使用 SqlTree 查询
本文介绍如何使用 Rafy 框架中的 Sql Tree 查询: 除了开发者常用的 Linq 查询,Rafy 框架还提供了 Sql 语法树的方式来进行查询. 这种查询方式下,开发者不需要直接编写真正的 ...
- WebConfig自定义节点并读取
最近是遇到了一个需求,需要自定义WebConfig节点,然后进行读取,网上有很多博客,写的非常好,但是笔者在实现的过程中还是遇到了点问题,现在写一篇文章来总结下. 首先推荐大家看http://www. ...
- 基于Quqrtz.NET 做的任务调度管理工具
基于Quqrtz.NET 做的任务调度管理工具 国庆前,需求让我看了一下任务调度的数据表设计.和之前一样,有100多个字段,p1 ~ p100, 我说这是干嘛啊!按这写,写死去了! 然后在网上搜了一下 ...
随机推荐
- android知识杂记(二)
记录项目中的android零碎知识点,用以备忘. AsyncQueryHandler 继承与handler,可以用于处理增删改(ContentProvider提供的数据) 例如:query = new ...
- Nunit工具做C#的单元测试
Nunit工具做C#的单元测试 学习心得 编写人:罗旭成 时间:2013年9月2日星期一 1.开发人员如何做单元测试 单元测试是针对最小的可测试软件元素(单元)的,它所测试的内容包括单元的内部结构 ...
- Unity3D热更新全书-脚本(一) 初识脚本
开篇之前还是要先说明,这是一份给经验并不丰富的程序员阅读的文字. 有需求.有疑惑,往下看. 第一个问题什么是脚本?程序和脚本如何区分?我们给Unity编写的组件是程序还是脚本? 这些问题本文无意去解答 ...
- 2、CC2541芯片中级教程-OSAL操作系统(进一步了解-OLED && 普通按键和5方向按键-中断!!!)这个系统驱动层和应用层不一样~
本文根据一周CC2541笔记汇总得来—— 适合概览和知识快速索引—— 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...
- 【OpenGL(SharpGL)】支持任意相机可平移缩放的轨迹球实现
[OpenGL(SharpGL)]支持任意相机可平移缩放的轨迹球 (本文PDF版在这里.) 在3D程序中,轨迹球(ArcBall)可以让你只用鼠标来控制模型(旋转),便于观察.在这里(http://w ...
- 细说.NET中的多线程 (六 使用MemoryBarrier,Volatile进行同步)
上一节介绍了使用信号量进行同步,本节主要介绍一些非阻塞同步的方法.本节主要介绍MemoryBarrier,volatile,Interlocked. MemoryBarriers 本文简单的介绍一下这 ...
- Linux内核TCP/IP参数分析与调优
转载于:http://www.itxuexiwang.com/a/liunxjishu/2016/0225/167.html?1456482565 如下图展示的是TCP的三个阶段.1,TCP三次握手. ...
- fir.im Weekly - 聊聊让人向往的远程开发工作
6月30 日,苹果开发者后台贴出一封关于广电总局的醒目通知,申报一个游戏 APP 上架AppStore,你需要文网文+ICP证+软著+版号,审批难度将越来越大,不禁让人感慨中国独立开发者的成长 &qu ...
- bootstrap实现嵌入的button
bootstrap实现嵌入的button 如下的效果: <div class="form-inline"> <div class="input-grou ...
- Java基础-继承-编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。
#29.编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight.小车类Car是Vehicle的子类,其中包含的属性有载人数 loader.卡车类T ...