zoukankan      html  css  js  c++  java
  • 写给自己的 程序集&msil 扫盲

    嘴上不说 心里却想MD 这家伙在博客园装了这么久的高手 竟然连这都不会 ,我去噢。

    程序集签名

    .net 下 “程序集” 什么东东 ,反正就是听着挺牛x的,其实就是指“一堆程序”从我们传统的C++封装的dll 认知 就是一个dll文件名 然后一个lib文件里面有对应的函数列表,把lib文件添加进去就OK了。

    呐 现在我们来新建一个空白Asp.net网站
    打开web.config 里面就有一些默认引用的程序集

    1 <assemblies>
    2         <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>            
    3     <add assembly="System.Xml.Linq, Version=3.5.0.0,Culture=neutral,PublicKeyToken=B77A5C561934E089"/>
    4 </assemblies>

    看见那些唧唧歪歪的属性没有 System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089 这都是些啥 ,这就是程序集信息 .net下对程序集的定义已经超出我们原来对dll文件认知的那种范畴了,程序集信息指代“一堆可用程序功能”经过签名的唯一电子标签信息。

    系统目录的程序集称之为GAC ,global assembly cache,就是我们平常用的console.write()啊 messageBox.show()啊啥的 。他放在C:WINDOWSassembly 进入那个目录下后发现资源管理器的视图变得很特殊。发现只可查看属性 而不能拷走里面的文件。要拷走也可以 在dos命令行下就可以了 他是以命名空间为目录树存放的。

    我们自己的程序集也可放到GAC里 需要这样做:
    放到GAC下的程序集必须使用一个私钥进行签名(附加强名称)方式如下:

    1. 在vs命令行 sn -k d:/key.snk
    2. 写好代码 编译 csc /keyfile:d:/test.snk /target:library function.cs
    3. 会有个function.dll文件产生 使用命令gacutil /i function.dll安装
    4. 在上面空白的asp.net网站里我们平常都是右键->添加引用 然后选中dll文件。 代码中using 命名空间 然后就按常规的方式使用。现在我们不用了 只需要在web.config 的<assemblies>里添加一行就可以了,像这样:
      <addassembly="Function,Version=0.0.0.0,Culture=neutral,PublicKeyToken=6ac36eab110b624e"/>
      前几个值都知道 但是这个PublicKeyToken怎么看呢 直接在C:WINDOWSassembly就可看到:
       
      其他各种方式都可以 比如sn -t 文件名。然后代码中using 命名空间 然后就按常规的方式使用。

    普通程序集在不破坏pe文件结构的情况修改后是可以运行的。而经过强名称签名的则不可以,有效的保证了程序完整性.。
    注意在.net3.5或以上版本不论在编译时选什么版本加了强名称都还是可以更改的。因为.net认为你的程序运行在一个"受信任的环境" 所以强名称验证是被pass的。但是加到GAC应该是加不进去的 加到GAC必定会进行强名称验证。要想进行强名称验证不被pass在app.config 里添加这样的配置:

    1 <configuration>
    2    <runtime>
    3       <bypassTrustedAppStrongNames enabled="false"/>
    4    </runtime>
    5 </configuration>

    附:
    使用gacutil /i function.dll卸载
    也可在C:WINDOWSassembly目录 选中程序集点右键 卸载。
    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

    新建一个控制台程序
    写几句代码:

     1 using System;
     2 namespace test
     3 {
     4     class Program
     5     {
     6         static void Main(string[] args)
     7         {
     8             //验证不通过程序立即退出
     9             if (licence() == false)
    10             {
    11                 Console.WriteLine("invalid license");
    12                 Console.ReadKey();
    13                 return;
    14             }
    15             else//验证成功 程序继续运行
    16             {
    17                 Console.WriteLine("licence is ok");
    18                 Console.ReadKey();
    19             }
    20         }
    21         static bool licence()
    22         {
    23             //假设这里是一个硬件ID授权认证
    24             //共享软件的注册验证 根据硬盘串号通过指定加密算法得到密文 即注册码
    25             //硬盘串号加密得到的密文跟注册码进行匹配
    26             //如果不一样则认为软件已被拷到未被授权的电脑上使用 return false
    27             return false;
    28         }
    29     }
    30 }

    在项目属性上->右键->属性
    添加程序签名:

    项目上->右键->添加->新建项->应用程序配置文件
    项目下多了app.config
    编辑它

    1 <?xml version="1.0"?>
    2 <configuration>
    3   <runtime>
    4     <bypassTrustedAppStrongNames enabled="false"/>
    5   </runtime>
    6 </configuration>

    现在编译并运行

    运行输出 invalid licence

    很明显验证不通过

    呐现在我们就来对他进行破解 让他验证通过

    然后打开il dasm 工具
    如果不知道在哪里打开 就在vs命令行里输入ildasm
    然后打开我们在debug目录编译后的exe文件

    代表test命名空间
    代表program类
    咦这啥东东 咱在代码里没写这个方法啊

    咱在书上学过如果没有写构造方法 则编译时提供默认的构造方法
    看 这里就是这个意思 ctor可能全称是 constructor

    打开main函数 代码如下:

     1 .method private hidebysig static void  Main(string[] args) cil managed
     2 {
     3   .entrypoint
     4   // 代码大小       50 (0x32)
     5   .maxstack  1
     6   .locals init ([0] bool CS$4$0000)
     7   IL_0000:  nop
     8   IL_0001:  call       bool test.Program::licence()
     9   IL_0006:  stloc.0
    10   IL_0007:  ldloc.0
    11   IL_0008:  brtrue.s   IL_001e
    12   IL_000a:  nop
    13   IL_000b:  ldstr      "invalid license"
    14   IL_0010:  call       void [mscorlib]System.Console::WriteLine(string)
    15   IL_0015:  nop
    16   IL_0016:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    17   IL_001b:  pop
    18   IL_001c:  br.s       IL_0031
    19   IL_001e:  nop
    20   IL_001f:  ldstr      "licence is ok"
    21   IL_0024:  call       void [mscorlib]System.Console::WriteLine(string)
    22   IL_0029:  nop
    23   IL_002a:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    24   IL_002f:  pop
    25   IL_0030:  nop
    26   IL_0031:  ret
    27 } // end of method Program::Main

    打开licence函数 代码如下:

     1 .method private hidebysig static bool  licence() cil managed
     2 {
     3   // 代码大小       7 (0x7)
     4   .maxstack  1
     5   .locals init ([0] bool CS$1$0000)
     6   IL_0000:  nop
     7   IL_0001:  ldc.i4.0
     8   IL_0002:  stloc.0
     9   IL_0003:  br.s       IL_0005
    10   IL_0005:  ldloc.0
    11   IL_0006:  ret
    12 } // 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
    咦怎么回事 不成功

    1 未处理的异常:  System.IO.FileLoadException: 未能加载文件或程序集“test, Version=
    2 1.0.0.0, Culture=neutral, PublicKeyToken=e49d145887009c3e”或它的某一个依赖项。
    3 强名称验证失败。 (异常来自 HRESULT:0x8013141A)
    4 文件名:“test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e49d145887009c3e
    5 ” ---> System.Security.SecurityException: 强名称验证失败。 (异常来自 HRESULT:0x
    6 8013141A)
    7 失败的程序集的区域是:
    8 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;

    其实我不懂汇编语言的 有些乱说的见谅 勿喷。

  • 相关阅读:
    C#中利用iTextSharp开发二维码防伪标签(1)
    delphi 数据库中Connection与Query连接数量问题思考
    cPanel 安装方法
    招商行用卡人工服务方式
    软链接的创建和查看
    zencart低版本由php5.2.17升级PHP5.3环境下错误及解决方案
    EXCEL应用:高级筛选里的条件或和与的条件怎么写 例:不包含,包含等
    array_walk与array_map 的不同 array_filter
    zen cart global $db 这噶哒
    hdu 5655 CA Loves Stick
  • 原文地址:https://www.cnblogs.com/assassinx/p/3150573.html
Copyright © 2011-2022 走看看