zoukankan      html  css  js  c++  java
  • CLR和JIT的理解、.NET反汇编学习

    CLR:通用语言运行时(Common Language Runtime)的简称,CLR是.NET框架的核心内容之一,可以把它看为一套标准资源,可以呗任何.NET程序使用。它包括:面向对象的编程模型、安全模型、类型系统(CTS)、所有.NET基类、程序执行及代码管理等。

    我们可以这样理解,CLR是托管程序运行的环境,就像Windows是普通的PE程序的运行环境一样。
    在Windows中,整个CLR系统的实现基本其实就是几个关键的DLL,比如mscorwks.dll、mscorjit.dll,它们共同的特点就是前缀均为mscor。

    在win32中,可执行文件在开始运行时,有操作系统载入到内存中,然后运行文件中的.text代码,结束时有操作系统负责卸载。而在.NET下,这个过程却不大一样。用PE结构查看工具(这里使用PEiD)载入一个实例文件,观察导入表,可以发现整个表只引入了一个mscoree.dll中的一个方法:_CorExeMain。而这个方法,真是该可执行文件在win32意义上的入口点。

    和win32程序一样,.NET可执行程序在运行初始,首先有Windows将PE载入内存,然后跳至_CorExeMain中执行。分水岭就在这,当代码跳至_CorExeMain中之后,程序运行进入了.NET的初始化阶段,经过一番准备工作,.NET框架便正式接管程序的运行了。

     

    *********************************************************************

    JIT:即时编译(Just In-Time compile),这是.NET运行可执行程序的基本方式,也就是在需要运行的时候,才将对应的IL代码编译为本机指令。传入JIT的是IL代码,输出的是本机代码,所以部分加密软件通过挂钩JIT来进行IL加密,同时又保证程序正常运行。同解释执行的代码相比,JIT的执行效率要高很多。

    说到这,我们先来了解下IL代码是从哪一个步骤得到的。

    MSIL是将.NET代码转化为机器语言的一个中间过程。它是一种介于高级语言和基于Intel的汇编语言的伪汇编语言。当用户编译一个.NET程序时,编译器将源代码翻译成Microsoft 中间语言 (MSIL),它是一组可以有效地转换为本机代码且独立于CPU的指令。当执行这些指令时,实时(JIT)编译器将它们转化为CPU特定的代码。

    也就是说,MSIL是一个中间语言,是由编译器编译而来的,属于第一个步骤(编译)的产物。

    而当我们需要执行时,再将MSIL通过JIT即时编译成所需的机器指令来执行。

    下面我们来看看MSIL的样子:

    我们先用vs2012编写一个简单的控制台程序,hello world。

    然后打开ildasm,具体步骤是这样的

    输入命令后出现

    我们将编译好的exe程序拖拽进ildasm中。

    我们将程序进行转储,也就是传说中的dump

    选择一些选项,然后保存

    我们用记事本将保存的il文件打开,文件内容如下:

    View Code
    //  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.17929
    
    
    
    
    // Metadata version: v4.0.30319
    .assembly extern mscorlib
    {
      .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
      .ver 4:0:0:0
    }
    .assembly '观察导入表'
    {
      .custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
                                                                                                            2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 01 00 54   // ,Version=v4.5..T
                                                                                                            0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C   // ..FrameworkDispl
                                                                                                            61 79 4E 61 6D 65 12 2E 4E 45 54 20 46 72 61 6D   // ayName..NET Fram
                                                                                                            65 77 6F 72 6B 20 34 2E 35 )                      // ework 4.5
      .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0F E8 A7 82 E5 AF 9F E5 AF BC E5 85 A5 E8 
                                                                                                  A1 A8 00 00 ) 
      .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0F E8 A7 82 E5 AF 9F E5 AF BC E5 85 A5 E8 
                                                                                                    A1 A8 00 00 ) 
      .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ...Copyright .. 
                                                                                                      20 32 30 31 32 00 00 )                            //  2012..
      .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 66 36 62 34 31 32 31 63 2D 64 37 63 37   // ..$f6b4121c-d7c7
                                                                                                      2D 34 30 33 35 2D 62 36 34 34 2D 35 30 36 34 38   // -4035-b644-50648
                                                                                                      63 62 34 33 30 34 63 00 00 )                      // cb4304c..
      .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..
    
      // --- 下列自定义特性会自动添加,不要取消注释 -------
      //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 ) 
    
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                                 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
      .hash algorithm 0x00008004
      .ver 1:0:0:0
    }
    .module '观察导入表.exe'
    // MVID: {287A4077-C19B-4F87-B42E-88C0B8CE6A6E}
    .imagebase 0x00400000
    .file alignment 0x00000200
    .stackreserve 0x00100000
    .subsystem 0x0003       // WINDOWS_CUI
    .corflags 0x00020003    //  ILONLY 32BITPREFERRED
    // Image base: 0x01720000
    
    
    // =============== CLASS MEMBERS DECLARATION ===================
    
    .class private auto ansi beforefieldinit '观察导入表'.Program
           extends [mscorlib]System.Object
    {
      .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        // 代码大小       17 (0x11)
        .maxstack  8
        .language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
        .line 13,13 : 13,47 'd:\\Pro\\CLR和JIT的理解\\观察导入表\\Program.cs'
        IL_0000:  ldstr      "hello world!"
        IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
        .line 14,14 : 13,31 ''
        IL_000a:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
        IL_000f:  pop
        .line 15,15 : 9,10 ''
        IL_0010:  ret
      } // end of method Program::Main
    
      .method public hidebysig specialname rtspecialname 
              instance void  .ctor() cil managed
      {
        // 代码大小       7 (0x7)
        .maxstack  8
        IL_0000:  ldarg.0
        IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
        IL_0006:  ret
      } // end of method Program::.ctor
    
    } // end of class '观察导入表'.Program
    
    
    // =============================================================
    
    // *********** 反汇编完成 ***********************
    // 警告: 创建了 Win32 资源文件 D:\Pro\CLR和JIT的理解\反编译.res

    MSIL:微软中间语言(Microsoft Intermediate Language),也被称作MSIL汇编。别看.NET框架很智能,其实它只认IL。无乱程序采用什么高级语言编写,都将被编译器编译为IL并保存在PE文件中。虽被称作汇编,但相比win32汇编语言,IL可谓是名副其实的高级语言:它支持面向对象,通常不直接操作内存地址,以堆栈机的方式运行。由于运行完全受.NET监控,因此IL属于托管(Managed)代码,与之对应的是本机代码,被称为非托管代码。

    元数据:描述.NET程序运行说必需的一切信息的数据,包括版本、类型的各个成员(方法、字段、属性、事件)等。一个文件要称为有效的.NET可执行程序,必须包含正确的元数据定义。

    我们来看看对应的hello world对应的元数据

    // =============== CLASS MEMBERS DECLARATION ===================
    
    .class private auto ansi beforefieldinit '观察导入表'.Program
           extends [mscorlib]System.Object
    {
      .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        // 代码大小       17 (0x11)
        .maxstack  8
        .language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
        .line 13,13 : 13,47 'd:\\Pro\\CLR和JIT的理解\\观察导入表\\Program.cs'
        IL_0000:  ldstr      "hello world!"
        IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
        .line 14,14 : 13,31 ''
        IL_000a:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
        IL_000f:  pop
        .line 15,15 : 9,10 ''
        IL_0010:  ret
      } // end of method Program::Main
    
      .method public hidebysig specialname rtspecialname 
              instance void  .ctor() cil managed
      {
        // 代码大小       7 (0x7)
        .maxstack  8
        IL_0000:  ldarg.0
        IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
        IL_0006:  ret
      } // end of method Program::.ctor
    
    } // end of class '观察导入表'.Program
    
    
    // =============================================================

    上面的代码中,首先通过.class关键字定义了Program类,于是编译器会在PE文件中保存Program类的元数据。接着,定义了Program类的两个方法.ctor和Main,元数据中也会体现这种隶属关系。

    public hidebysig static void 限定了Main方法中的执行方式为公共、静态、无返回值(hidebysig暂时不讨论),这些限定也将被保存在元数据中。

    Main方法中调用了System.Console的静态方法WirteLine用于输出字符串,元数据中必须体现这种调用。

    以上内容来自:《微软.NET程序的加密与解密》,学习这些内容只是为了能更好的理解所学的C#内容,暂时不涉及逆向的问题。

  • 相关阅读:
    e666. 创建缓冲图像
    e670. 缓冲图像转换为图像
    e680. 使三元色图像变明变暗
    e659. 缩放,剪取,移动,翻转图形
    e656. 创建基本图形
    e657. 用直线和曲线绘制图形
    e658. 组合图形
    e655. 混合风格的文本
    e654. 获得文本的缩略图
    e652. Getting the Font Faces for a Font Family
  • 原文地址:https://www.cnblogs.com/tk091/p/2666810.html
Copyright © 2011-2022 走看看