Dotnet文件格式解析
0x0、序
解析过程并没有介绍对pe结构的相关解析过程,网上此类相关资料很多可自行查阅,本文只介绍了网上资料较少的从pe结构的可选头中的数据目录表中获取dotnet目录的rva和size,到完全解析dotnet文件格式特有数据结构的部分。
了解dotnet文件格式你可能需要一款名为CFF Explorer的工具;你也可能在很多时候需要查阅书籍《Expert .NET 2.0 IL Assembler》,该书籍的中文版本名为《.NET探秘MSIL权威指南》。简要的文件格式图,可以参考下面:
分析文件的md5为:79D7AF997C9224CFF7B82E539C71FCDB。
0x1、IMAGE_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版本、分析文件、简要文件格式图 打包下载
Dotnet文件格式解析的更多相关文章
- ArcGIS三大文件格式解析
原文:ArcGIS三大文件格式解析 Shape数据 Shapefile是ArcView GIS 3.x的原生数据格式,属于简单要素类,用点.线.多边形存储要素的形状,却不能存储拓扑关系,具有简单.快速 ...
- Android init.rc文件格式解析
/***************************************************************************** * Android init.rc文件格式 ...
- mp4文件格式解析(转载)
mp4文件格式解析 原作:http://blog.sina.com.cn/s/blog_48f93b530100jz4b.html 目前MP4的概念被炒得很火,也很乱.最开始MP4指的是音频(MP3的 ...
- C++PE文件格式解析类(轻松制作自己的PE文件解析器)
PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
- 解析prototxt文件的python库 prototxt-parser(使用parsy自定义文件格式解析)
解析prototxt文件的python库 prototxt-parser https://github.com/yogin16/prototxt_parser https://test.pypi.or ...
- mp4文件格式解析(转)
mp4文件格式解析 MP4文件格式带数据详解 MP4文件格式的解析,以及MP4文件的分割算法
- Qt的.pro文件格式解析
Qt的.pro文件格式解析 在Qt中用qmake生成makefile文件,它是由.pro文件生成而来的,.pro文件的具体格式语法如下: 1.注释 .pro文件中注释采用#号,从"#&quo ...
- flv文件格式解析!!!
flv头 FLV header 总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成. Signature: FLV 文件的前3个字 ...
- (转)AVI文件格式解析+AVI文件解析工具
AVI文件解析工具下载地址:http://download.csdn.net/detail/zjq634359531/7556659 AVI(Audio Video Interleaved的缩写)是一 ...
随机推荐
- [LeetCode] Implement Queue using Stacks 用栈来实现队列
Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...
- 编写轻量ajax组件03-实现(附源码)
前言 通过前两篇的介绍,我们知道要执行页面对象的方法,核心就是反射,是从请求获取参数并执行指定方法的过程.实际上这和asp.net mvc框架的核心思想很类似,它会解析url,从中获取controll ...
- Can't find any matching row in the user table
原因 更改mysql.user表之后,没有使用flush privileges命令来更新权限. 解决方案 使用flush privileges命令更新一下. 问题描述 配置mysql远程登录时,只需要 ...
- Java jdbc访问sqlserver,oracle数据库
1.JDBC访问Oracle数据库 public class Jdbc_Oracle { // 静态代码块,只会执行一次,类似C#静态构造方法 static { try { // 加载数据库驱动一次 ...
- mybatis返回数据类型为map,值为null的key没返回
创建mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...
- windows 10专业版14393.447 64位纯净无广告版系统 基于官方稳定版1607制作 更新于20161112
系统特点: 447更新日志(Win10 PC一周年更新正式版14393.447 32位/64位更新补丁KB3200970下载 Flash补丁Kb3202790下载): 1.通过网友的反馈,保留了Edg ...
- thusc2016游记&&滚粗记&&酱油记
#include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.com/w ...
- 修改.net mvc中前端验证信息的显示方式
最近一直在学习.net core的用法.想法是通过写一个新闻系统来熟悉一下这个最新的技术.其实,我以前一直对.net技术都是浅尝辄止,最主要原因是没有动力.平时写企业站因为时间原因,不是使用php的框 ...
- bzoj 1146 [CTSC2008]网络管理Network
很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...
- word中公式居中标号没有右对齐
打开视图-标尺,调整右侧标尺就行了.