analysis

呆雕浮长空,若鲤戏碧波,木林春葳蕤,鸡鸣桑树颠。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

转贴:微软.NET通用语言运行库概观

Posted on 2005-08-24 17:42  analysis  阅读(735)  评论(0)    收藏  举报
    这是出自29A的一篇文章,tankaiha把它翻译了,我便把它转载一下吧。由于出自29A,所以,他们可以让我们从另一个角度来认识.NET。里面有几句话我是非常有同感的,也是困惑许久的,呵呵。

原文:

微软.NET通用语言运行库概观

by Benny/29A

翻译:tankaiha

 

整个世界好像都在谈论微软的被称作.NET的新平台。20021月的推出的.NET FrameWork SDK版本包含了许多基本服务。并且,用在.NET下可视化开发的Microsoft Visual Studio.NET测试版也出现在网上,你可以用它创建自已的程序。我写这篇文章是因为我不能坐等别人先于我研究这个平台,你是知道的,我是个充满好奇心的人。

 

 

 MS.NET有什么新玩意儿?

......................

Microsoft .NET的体系是基于组件和平台独立的,完整给出它的定义需要太多的文字,所以我在这里尽量缩短篇幅,只谈及一些重要的内容。.NET FrameWork SDK提供了在非.NET机器上运行的必需部分。完整的.NET操作系统将随WinXP的后继版本发行。但是微软会想方设法推广他们的新平台,就像当初的Win32一样——发行Win32s,适用于Win16位系统的Win32限制版。今天,他们推出了.NET FrameWork SDK,它和.NET体系的关系就像Win32s之于完整的Win32

 

本篇文章要讨论的核心内容就是.NET通用语言运行环境(.NET Common Language Runtime environment)

 

 

回顾历史

...........................

在过去,创建组件真他妈麻烦!如果你的组件是用C++写的,那VB就不能调用,反之亦然——这是因为一种语言写的程序尽然需要另一咱语言写的运行时来支持。(原句:that's becoz application written in one specific language used another runtime environment than the application written in another language)微软使用了很多方法来解决这个问题:DDEOLECOM1.0DCOMCOM+等等)让我们看一下COM——在过去,使用COM显得非常有效,所以也很成功,所以它被高级语言编程者广泛使用。但有个小问题:C++中调用COM非常麻烦(至今仍是这样)。VB中虽然比较方便,但难以发挥COM的全部功能,而让不同语言编写的程序进行合作又总是存在这样那样的问题。现在也还是这样。

 

 

“全新”的架构

...........................

微软又一次偷窃了别人的成果,并用来提高自已的技术MS.NET就是例子.NET环境中只存在一种代码,就是微软自已的中间语言(元代码、伪代码以及类似JAVA的类),还有一个运行时环境(CLR)和库(Frameworks)。

 

 

微软的通用语言运行时

...........................

通用的模型提供了所有的服务,你可以使用任何一种语言来访问它们。当然,你也可以编写自已的服务供所有的.NET语言使用。因为,无论你使用何种编程语言,最后都将被编译成与语言无关的元代码。程序都是在运行的时候被CLR即时编译成可执行代码的,可以看出.NET整体上看就是JAVA,没什么新东西。

 

 

本机语言

...........................

我不是要吓唬谁:C++VB都可以在.NET中使用。甚至JAVA也可以被当作.NET本机语言。微软还设计了两种全新的语言:C#J#(读作C SharpJ Sharp)。

 

 

1C#是一种全新的且非常高效的语言,用来编写.NET应用程序。当初我刚开始学习它时,充满了兴趣。微软设计了一种超级语言:它和C++很像,但又包含了很多别的语言的优点(VBJAVA等)。我不得不承认,即使不算上代码良好的可读性这条优点(因为许多别的语言也具有这个优点,比如C++JAVAPERL),微软设计的C#是世界上最好的语言之一。真的!

 

2J#是为JAVA程序员设计的。它和JAVA很像,JAVA程序员可以很容易地将代码移植到.NET上来。还有一些著名的语言(比如PERL),不久也会被移植到.NET的。

 

 

装配件

...........................

嗯,装配件对于程序员来说是个新名词。好像微软的本能就是挑战一切现有标准,还记得吗:Program->Application, Directory->Folder, Link->Shortcut等等等等。但是,装配件不是普通的可执行文件——它是一个完整的程序体(原文:application comple)。装配件包含了程序需要的所有信息。你可以将它想像为一个可执行文件,且包含了所有的元代码、数据和其它运行时必需的信息。每个装配件都有其包含的所有部件的列表,这被称作MANIFEST

 

 

微软中间语言

...........................

我已经简短地概述了.NET CLR的相关知识,下面给你演示一些元代码(又叫MSIL)。

 

这是我编写的很简单的程序(simple.cs

 

<------------------ cut ------------------>

 

using System;

 

class Sample {

 

       public static void Main () {

              Console.WriteLine("Hello world");

       }

}

 

<------------------ cut ------------------>

 

通过命令行“CSC simple.cs”来编译它,随后生成了新的文件simple.exe用相关工具打开,你会发现它和普通的PE文件不同:它不含可执行代码,还有一些很奇怪的结构。是的,它是MSIL PE文件。

 

ILDASM.EXE将它反汇编成IL代码,我们可以看到如下的树状结构。

<------------------ cut ------------------>

 

___[MOD] D:\!!work\.net\sample.exe

   |      M A N I F E S T

   |___[CLS] Sample

   |   |     .class private auto ansi beforefieldinit

   |   |___[MET] method .ctor : void()

   |   |___[STM] method Main : void()

   |

 

<------------------ cut ------------------>

 

除去所有不必要的信息(注释、资源、垃圾代码...),你就得到了simple.il

<------------------ cut ------------------>

 

assembly extern mscorlib

{

  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )

  .ver 1:0:2411:0

}

.assembly sample

{

  .hash algorithm 0x00008004

  .ver 0:0:0:0

}

.module sample.exe

.imagebase 0x00400000

.subsystem 0x00000003

.file alignment 512

.corflags 0x00000001

.class private auto ansi beforefieldinit Sample

       extends [mscorlib]System.Object

{

  .method public hidebysig static

          void  Main() cil managed

  {

    .entrypoint

    // Method begins at RVA 0x2050

    // Code size       11 (0xb)

    .maxstack  8

    IL_0000:  /* 72   | (70)000001 */ ldstr      "Hello world"

    IL_0005:  /* 28   | (0A)000001 */ call       void [mscorlib]System.Console::WriteLine

(string)

    IL_000a:  /* 2A   |            */ ret

  }

 

}

 

<------------------ cut ------------------>

 

看到了没?这些就是元代码。它看上去很容易理解,特别是对于ASM程序员,甚至不需要任何注释。也许有人会问“mscorlib”是什么?事实上它是存储在你机器上某处的一个DLL文件,里面包含了所有的类库

 

现在,删除所有MS编译器添加的代码,再利用ILASM.EXE将它编译成可执行文件ILASM sample.il

 

我们得到了2KB大小的“Hello World”可执行文件。现在做什么?让我们来看看它的结构,它和普通的PE文件有什么不同。

 

<------------------ cut ------------------>

 

File type: WINDOWS EXECUTABLE

 

File Header:

  Machine:                    0x014C (Intel x86)

  Number of Sections:          2

  Time Date Stamp:            0x3C3886C7 (6. 1. 2002 18:17:59)

  Pointer to Symbol Table:       0x00000000

  Number of Symbols:          0

  Size of Optional Header:       0x00E0 (224)

  Characteristics:               0x010E

    File is executable.

    Line numbers stripped from file.

    Local symbols stripped from file.

    32 bit word machine.

 

Optional Header:

  Magic:                        0x010B

  Linker Version:                   6.00

  Size of Code:                    0x00000400 (1024)

  Size of Initialized Data:              0x00000200 (512)

  Size of Uninitialized Data:            0x00000000 (0)

  Adress of Entry Point:              0x0000229E

  Base of Code:                  0x00002000

  Base of Data:                    0x00004000

  Image Base:                    0x00400000

  Section Align:                    0x00002000

  File Align:                      0x00000200

  Operating System Version:          4.00

  Image Version:                   0.00

  Subsystem Version:               4.00

  Size of Image:                   0x00006000 (24576)

  Size of Headers:                  0x00000200 (512)

  Checksum:                     0x00000000

  Subsystem:                     0x0003 (Windows character subsytem)

  DLL Characteristics:                0x0000

  Size of Stack Reserve:              0x00100000 (1048576)

  Size of Stack Commit:             0x00001000 (4096)

  Size of Heap Reserve:              0x00100000 (1048576)

  Size of Heap Commit:             0x00001000 (4096)

  Loader Flags:                    0x00000000

  Number of Rva and Sizes:       16

 

<------------------ cut ------------------>

 

文件头正常,我们继续

 

<------------------ cut ------------------>

 

Data Directory:

  Export directory:                 VA: 0           Size: 0

  Import directory:                 VA: 0x00002250  Size: 0x0000004B (75)

  Resource directory:               VA: 0           Size: 0

  Exception directory:               VA: 0           Size: 0

  Security directory:                VA: 0           Size: 0

  Base relocation table:               VA: 0x00004000  Size: 0x0000000C (12)

  Debug directory:                VA: 0           Size: 0

  Architecture-specific data:            VA: 0           Size: 0

  RVA of global pointer:             VA: 0           Size: 0

  Thread local storage directory:         VA: 0           Size: 0

  Load configuration directory:         VA: 0           Size: 0

  Bound import directory:           VA: 0           Size: 0

  Import address table:               VA: 0x00002000  Size: 0x00000008 (8)

  Delay load import descriptors:        VA: 0           Size: 0

  COM run-time descriptor:          VA: 0x00002008  Size: 0x00000048 (72)

  (unknown directory entry):          VA: 0           Size: 0

 

Import Table:

  mscoree.dll

    Import Adress Table:           0x00002000

    Import Name Table:           0x00002278

    Time Date Stamp:             0x00000000

    Index of first forwarder reference: 0x00000000

 

    0x00002280         0   _CorExeMain

 

Section Table:

  Section Header #1

    Name:                             .text

    Virtual Size:                       0x000002A4 (676)

    Virtual Address:                    0x00002000

    Size of Raw Data:                 0x00000400 (1024)

    File Pointer to Raw Data:             0x00000200

    File Pointer to Relocation Table:         0x00000000

    File Pointer to Line Numbers:          0x00000000

    Number of Relocations:            0

    Number of Line Numbers:          0

    Characteristics:                      0x60000020

      Section contains code.

      Section is executable.

      Section is readable.

 

  Section Header #2

    Name:                             .reloc

    Virtual Size:                       0x0000000C (12)

    Virtual Address:                    0x00004000

    Size of Raw Data:                  0x00000200 (512)

    File Pointer to Raw Data:             0x00000600

    File Pointer to Relocation Table:         0x00000000

    File Pointer to Line Numbers:          0x00000000

    Number of Relocations:            0

    Number of Line Numbers:          0

    Characteristics:                     0x42000040

      Section contains initialized data.

      Section can be discarded.

      Section is readable.

 

<------------------ cut ------------------>

 

就是这儿!大体上看去,.NET可执行文件只包含一个必须的段“.text”。程序只导入了一个叫作

_CorExeMain”的函数,且程序入口是40229Eh

 

:0040229E FF2500204000   jmp    [SAMPLE.00402000]

 

这句就是跳转到MSCOREE.DLL中的代码。我们可以把它看作.NET运行可执行文件中的元代码的调度员,每个程序开始都是这样调用.text段的开始8个字节是_CorExeMainAPI虚拟地址virtual address),随后的72个字节是CLR头。第一个字节是CLR头的大小:72。后面是一些其它的数据(flagz, version of compiler, entrypoint token),再后面是数据目录,和PE文件头一样。其中有效的数据目录包括:元数据目录、资源目录、强名称目录、CodeManager表、VTableFixups目录、导出地址目录和预编译头。目录中还包含了入口的相对虚拟地址RVA和它的大小。通常,元数据从第80个字节开始(402050h)——其中的第一条数据402010h就是元数据和它的地址。(译者:建议结合.NETPE文件结构看)

 

(下面就是我个人的猜测了。我不敢确定,只是凭经验断点,如果你知道,请一定告诉我!)

看来第一条数据(402050h)是关于方法/模块的记录,后面跟着元数据,因为我发现元数据总是紧跟着元代码存储。424A5342h(“BSJB”)看来是元数据目录的标识(MAGIC NUMBER),后面是一些标记(flag)和内部记录(类中的方法、属性、性质等记录的名称和令牌)

 

我希望有一天网络上会出现一些关于MSILCLR内部结构的文档,让我们研究得更深入一些。(译者:现在已经有了Inside Microsoft .NET IL Assembler,网上还有一些不错的文章。)

 

 

最后

...........................

好了,我知道的暂时就这么多。我们能利用这些已掌握的信息做些什么呢?微软不会改变代码的形式,所以我们能进行更深入的研究。并且,借助MSDN和一些.NET工具的帮助,我们能够编写出覆盖式的MSIL PE病毒,以上述内容为基础。如果有人搞出了CLR头的结构,我确定很快便会有第一个.NET附着式的病毒出现——既然有JAVA病毒,.NET CLR为什么不行呢?

 

大家有福了,你可以在29A6期杂志中找到世界上第一只由我编写的.NET病毒,名叫.NET.dotNET(或是Win32.Donut)。

 

好了,就这么多了。如果你了解我所不知道的信息,希望多多指教!谢谢!

 

....................................................

.                    Benny / 29A

.                    benny@post.cz

.                    http://benny29a.cjb.net

... perfectionist, maximalist, idealist, dreamer ...

 

 

译者后记:翻译文章太累了,不过翻译完经典的文章后总有一些成就感!.NET的知识我也刚学不久,也许连入门都谈不上,所以尽管是2年前的老文,翻译中仍难免出现BUG,大家不要向我扔鸡蛋就行了。让我们共同在.NET的世界中享受virus coding的乐趣吧!

 

tankaiha

2005.2.4