Dotnet文件格式解析

0x0、序

  解析过程并没有介绍对pe结构的相关解析过程,网上此类相关资料很多可自行查阅,本文只介绍了网上资料较少的从pe结构的可选头中的数据目录表中获取dotnet目录的rva和size,到完全解析dotnet文件格式特有数据结构的部分。

  了解dotnet文件格式你可能需要一款名为CFF Explorer的工具;你也可能在很多时候需要查阅书籍《Expert .NET 2.0 IL Assembler》,该书籍的中文版本名为《.NET探秘MSIL权威指南》。简要的文件格式图,可以参考下面:

  分析文件的md5为:79D7AF997C9224CFF7B82E539C71FCDB。

0x1IMAGE_COR20_HEADER结构

  通过可执行文件nt头下的可选头中数据目录中最后一项获取dotnet目录的rva和size。获取的数据为:rva=0x00002008;size=0x00000048,使用stud_pe将rva地址转化为raw。得到raw地址为:0x208。读取出其中数据,数据内容如下:


00000200                            48 00 00 00 02 00 05 00           H

00000210   A0 23 00 00 58 10 00 00  03 00 02 00 06 00 00 06   ?  X

00000220   30 22 00 00 70 01 00 00  00 00 00 00 00 00 00 00   0"  p

00000230   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

00000240   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

  该长度为0x48的数据的数据结构如下:


typedef struct IMAGE_COR20_HEADER

{

ULONG         cb;

USHORT        MajorRuntimeVersion;

USHORT        MinorRuntimeVersion;

//符号表和开始信息

IMAGE_DATA_DIRECTORY    MetaData;

//信息都在这个元数据表中可以获取。

ULONG         Flags;

union{

DWORD    EntryPointToken;

DWORD    EntryPointRVA;

};

//绑定信息

IMAGE_DATA_DIRECTORY    Resource;

IMAGE_DATA_DIRECTORY    StrongNameSignature;

//常规的定位和绑定信息

IMAGE_DATA_DIRECTORY    CodeMagagerTable;

IMAGE_DATA_DIRECTORY    VTableFixups;

IMAGE_DATA_DIRECTORY    ExprotAddressTableJumps;

IMAGE_DATA_DIRECTORY    MagageNativeHeader;

}IMAGE_COR20_HEADER

  通过对结构解析,读取结构中的元数据MetaData。该结构中可以得到一个元数据的rva和size。具体数据内容为:MetaData_rva=000023a0,MetaData_size= 00001058。MetaData_rva转换成MetaData_raw后为5a0。需要注意的是后面好多数据的定位都是以这个地址为基准的相对偏移。

0x2、元数据

  MetaData_rva指向的数据结构如下:


typedef struct STORAGE_SIGNATURE

{

DWORD    lSignature;

WORD     iMajorVersion;

WORD     iMinorVersion;

DWORD    iExtraData;

DWORD    iLength;

BYTE     iVersionString[];

//字符串编译环境版本号的长度由iLength决定,包含尾部0,且按4字节对齐。

}STORAGE_SIGNATURE;

  结构的数据内容为:


000005A0   42 53 4A 42 01 00 01 00  00 00 00 00 0C 00 00 00   BSJB

000005B0   76 34 2E 30 2E 33 30 33  31 39 00 00               v4.0.30319

  紧跟存储标志结构后面的数据结构定义如下:


typedef struct STORAGE_HEADER

{

BYTE      fFlags;

BYTE      reserved;

WORD      NumberOfStreams;

}STORAGE_HEADER;

  结构的数据内容为:


000005B0                                        00 00 05 00

0x3、流描述表

  存储头结构的最后一个成员是流的个数,在该结构后面将跟的是每一个流的描述结构,该成员有几个流个数,后面就有几个流描述结构,分析的文件流个数为5,后面将跟5个流描述结构。每个结构的定义如下:


typedef struct STREAM_HEADER

{

DWORD    iOffset;

//相对于MetaData_raw的偏移

DWORD    iSize;

BYTE     rcName[];

//流名称字符串得长度由iSize决定,包含尾部0,且按4字节对齐。

}STREAM_HEADER;

  结构数据(不同的数据流之间已经用不同的颜色区分)为:


000005C0   6C 00 00 00 44 05 00 00  23 7E 00 00 B0 05 00 00   l   D   #~  ?

000005D0   8C 07 00 00 23 53 74 72  69 6E 67 73 00 00 00 00   ?  #Strings

000005E0   3C 0D 00 00 88 00 00 00  23 55 53 00 C4 0D 00 00   <   ?  #US ?

000005F0   10 00 00 00 23 47 55 49  44 00 00 00 D4 0D 00 00       #GUID   ?

00000600   84 02 00 00 23 42 6C 6F  62 00 00 00               ?  #Blob

  流名称字符串中的名称是由微软定义好的字符串,不会出现非定义的字符串。已经定义的流名称有:


名称


含义


#~


存储压缩(优化)后的元数据信息,存在#~流后不会出现#-流。


#-


存储未压缩(优化)的元数据信息,存在#-流后不会出现#~流。


#Strings


存储元数据的各种字符串,比如类名称,方法名称,成员名称,参数名称等。字符串格式为UTF8格式。该流数据首部会存在一个空字符串;且此处定义的字符串最大长度不超过1024。


#Blob


存储程序中的非字符串信息,包括常量值,方法的签名,强名称等。每个数据的长度由数据的前1-3位决定:0表示1字节;10表示2字节;110表示4字节。


#GUID


存储所有GUID


#US


存储IL代码中使用的各种字符串,字符串格式为Unicode格式。

0x4、元数据信息流

  微软定义的六个数据流中,除去一个互斥的元数据信息流外,其他的流都是可能存在的。而其他的流信息都是通过元数据信息流中的结构对其进行引用的。并且紧跟流表结构的也是元数据信息流,该地址可以通过流表中的元数据信息流流表中的相对便移地址计算得到:该流数据内容的地址相对元数据起始地址偏移为0x6c。和metadata_raw相加得到的地址为:0x60c。该地址数据结构如下:


typedef struct METADATA_HEADER

{

DWORD    Reserved;

BYTE     Major;

BYTE     Minor;

BYTE     Heaps;

BYTE     Rid;

QWORD    MaskValid;

QWORD    Sorted;

}METADATA_HEADER;

  结构下的数据内容为:


00000600                                        00 00 00 00

00000610   02 00 00 01 57 15 A2 15  09 01 00 00 00 FA 25 33       W ?     ?3

00000620   00 16 00 00

  结构中有两个域需要说明,分别是Heaps域和MaskValid域。

  结构中MaskValid是一个位向量,每一个二进制位表示某一个特定的表存在。该域所占大小为64位。但对应的表个数为45个,所有只有低45位有意义,其他位没有含义。位和表的对应关系如下:


位数


表名


位数


表名


0


Module


23


Property


1


TypeRef


24


MethodSemantics


2


TypeDef


25


MethodImpl


3


FiledPtr


26


ModuleRef


4


Filed


27


TypeSpec


5


MethodPtr


28


ImplMap


6


MethodDef


29


FiledRVA


7


ParamPtr


30


ENCLog


8


Param


31


ENCMap


9


MethodImpl


32


AssemblyRef


10


MemberRef


33


AssemblyProcessor


11


Constant


34


AssemblyOS


12


CustomAttribute


35


Assembly


13


FieldMarshal


36


AssemblyRefProcessor


14


DeclSecurity


37


AssemblyRefOS


15


ClassLayout


38


File


16


FieldLayout


39


ExportedType


17


StandAloneSig


40


ManifestResource


18


EventMap


41


NestedClass


19


EventPtr


42


GenericParam


20


Event


43


MethodSpec


21


PropertyMap


44


GenericParamConstraint


22


PropertyPtr

  分析文件的MaskValid值转换成二进制数值如下:


MaskValid值(16进制)


MaskValid值(2进制)


0000010915A21557


10000100100010101101000100001010101010111

  分析MaskValid的二进制数值,可以发现共有17个二进制位被置1,所以该文件的元数据流中存在17个类型的表。根据位对应编号得到存在的各个类型的表的序号分别为:0、1、2、4、6、8、10、12、17、21、23、24、26、28、32、35、40。查找上面的序号名称关系表可以查到对应的表名称。再通过紧跟其后的4字节数组确定表中有多少个记录。记录的个数可以确定表的长度。4字节数组内容如下:


00000620               01 00 00 00  31 00 00 00 05 00 00 00           1

00000630   05 00 00 00 0D 00 00 00  04 00 00 00 36 00 00 00               6

00000640   16 00 00 00 01 00 00 00  02 00 00 00 03 00 00 00

00000650   04 00 00 00 01 00 00 00  01 00 00 00 01 00 00 00

00000660   04 00 00 00 02 00 00 00

  4字节数组后将是按照数组各个元素对应的记录表,各个记录表的顺序和4字节数组的中顺序相同,也是按照结构编号从小到大排列。但每个表里每个元素的结构可能并不相同。以第一个表Module表为例,如果文件存在该结构,由于该结构序号为0,所以必然为第一个结构。其记录结构如下:


typedef struct Module_Struct

{

WORD          Generation;

WORD/DWORD    Name;         //(在#String流中的偏移量)大小可能是word也可能是dword

WORD/DWORD    Mvid;         //(在#GUID流中的偏移量)大小可能是word也可能是dword

WORD/DWORD    EncId;        //(在#GUID流中的偏移量)大小可能是word也可能是dword

WORD/DWORD    EncBaseId;    //(在#GUID流中的偏移量)大小可能是word也可能是dword

}METADATA_HEADER;

  需要说明的是结构中后4个便宜量才用DWORD还是WORD由METADATA_HEADER结构中的Heaps域决定。

  结构中Heaps的含义为:元数据信息流中引用其他流中数据时,索引值的大小。


Heaps数值


含义


0


所有索引值均采用16位索引值


0x01


表示引用#String流时,索引值均为32位


0x02


表示引用#GUID流时,索引值均为32位


0x04


表示引用#Blob流时,索引值均为32位

  从上面的METADATA_HEADER结构中我们可以看到heaps的数值为0,索引均采用WORD类型大小,而通过4字节数组可以确定Module记录表的长度为1,所以具体的Module数据内容如下:


00000660                            00 00 0A 00 01 00 00 00

00000670   00 00

  其他记录数据同样通过该方式进行查询。

  其他表中元素结构相关信息可以查阅相关资料文档《.NET探秘MSIL权威指南》或《Expert .NET 2.0 IL Assembler》附录B。

文章pdf版本、分析文件、简要文件格式图 打包下载

时间: 2024-10-27 19:40:53

Dotnet文件格式解析的相关文章

CSV文件格式解析器的实现:从字符串Split到FSM

本文分为5小节,基本上就是我刚接触CSV文件到思考.实践做一个CSV解析器的过程的还原.希望我的思路也能带领你一步步从浅到深认识CSV文件格式. 1.简单的CSV解析器实现. 2.简单实现的CSV解析器的问题 3. CSV格式的定义 4.用FSM(有限状态机)来做CSV格式解析. 5.为什么使用CSV格式 1.简单的CSV解析器实现. 最近有一个需求,读取CSV格式的配置.CSV是CommaSeparated Value(逗号分隔值)的缩写,通常用文本表示数据.CSV格式数据的结构类似表格,不同

ArcGIS三大文件格式解析

原文 ArcGIS三大文件格式解析 Shape数据 Shapefile是ArcView GIS 3.x的原生数据格式,属于简单要素类,用点.线.多边形存储要素的形状,却不能存储拓扑关系,具有简单.快速显示的优点.一个shapefile是由若干个文件组成的,空间信息和属性信息分离存储,所以称之为“基于文件”. 每个shapefile,都至少有这三个文件组成,其中: *.shp 存储的是几何要素的的空间信息,也就是XY坐标 *.shx 存储的是有关*.shp存储的索引信息.它记录了在*.shp中,空

FLV文件格式解析

FLV文件格式解析 媒体格式分析之flv -- 基于FFMPEG

(转)AVI文件格式解析+AVI文件解析工具

AVI文件解析工具下载地址:http://download.csdn.net/detail/zjq634359531/7556659 AVI(Audio Video Interleaved的缩写)是一种RIFF(Resource Interchange File Format的缩写)文件格式,多用于音视频捕捉.编辑.回放等应用程序中.通常情况下,一个AVI文件可以包含多个不同类型的媒体流(典型的情况下有一个音频流和一个视频流),不过含有单一音频流或单一视频流的AVI文件也是合法的.AVI可以算是

C++PE文件格式解析类(轻松制作自己的PE文件解析器)

PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣的能够參看之后列出的參考资料及其它相关内容. 近期我也在学习PE文件格式,參考了很多资料.用C++封装了一个高效方便的PE文件格式解析的类. 该类对想学PE文件结构的朋友可算一份可贵的资料.代码均非常易懂,考虑较全面,具有一定的通用性. 同一时候该类也能够让想创建自己的PE文件解析软件的朋能够轻松在

解析prototxt文件的python库 prototxt-parser(使用parsy自定义文件格式解析)

解析prototxt文件的python库 prototxt-parser https://github.com/yogin16/prototxt_parser https://test.pypi.org/project/prototxt-parser1.yield让函数执行支持分段,让函数支持了记忆和状态,能够让一个函数变成状态机,这样一个状态机的执行流程可能直接表达在一个函数中,让整个处理流程更加顺畅.2.parsy的optional,Returns a parser that expects

PDF文件格式解析(1)- 了解PDF的语法格式

PDF文件格式解析(1)- 了解PDF的语法格式 PDF格式 由Adobe Systems Incorporated开发的PDF(便携式文档格式)被Adobe描述为一种通用的文档表示语言.PDF代表格式化的,面向页面的文档.这些文档可以是结构化的或简单的.它们可能包含文本,图像,图形和其他多媒体内容,例如视频和音频.支持注释,元数据,超文本链接和书签.更高版本提供了其他功能,例如,将地理空间信息嵌入到代表地图或其他地理空间图像(例如卫星照片)的文档中. PDF的核心是源自PostScript页面

http协议请求规则与dotNet的解析

请求方法URI协议/版本 请求的第一行是"方法URL议/版本":GET/sample.jsp HTTP/1.1 以上代码中"GET"代表请求方法,"/sample.jsp"表示URI,"HTTP/1.1代表协议和协议的版本. 根据HTTP标准,HTTP请求可以使用多种请求方法.例如:HTTP1.1支持7种请求方法:GET.POST.HEAD.OPTIONS.PUT.DELETE和TARCE.在Internet应用中,最常用的方法是GET

IP流量重放与pcap文件格式解析

(作者:燕云   出处:http://www.cnblogs.com/SwordTao/ 欢迎转载,但也请保留这段声明,谢谢!)   君不见 黄河之水 天上来 奔流到海不复回   君不见 高堂明镜 悲白发 朝如青丝暮成雪   人生得意须尽欢 莫使金樽空对月 --将进酒 pcap文件格式,为多数的tcpdump.wireshark等重量级的数据包抓取.分析应用程序所直接支持,所以,为我们的程序中嵌入此类文件的解析与生成功能,很是值得. 具体信息请看wireshark wiki:http://wik