PE结构

IMAGE_DOS_HRADER_STRUCT ----- { Size 40H }   -> e_lfanew 指向PE文件头

nt!_IMAGE_NT_HEADERS
   +0x000 Signature        : Uint4B                                    /PE文件标识
   +0x004 FileHeader       : _IMAGE_FILE_HEADER
   +0x018 OptionalHeader   : _IMAGE_OPTIONAL_HEADER

 

nt!_IMAGE_FILE_HEADER
   +0x000 Machine          : Uint2B            //运行平台
   +0x002 NumberOfSections : Uint2B    //文件的区块数目
   +0x004 TimeDateStamp    : Uint4B    //文件创建日期与时间
   +0x008 PointerToSymbolTable : Uint4B    //指向符号表
   +0x00c NumberOfSymbols  : Uint4B        //符号表中符号个数
   +0x010 SizeOfOptionalHeader : Uint2B    //IMAGE_OPTIONAL_HEADER结构大小
   +0x012 Characteristics  : Uint2B              //文件属性

nt!_IMAGE_OPTIONAL_HEADER
   +0x000 Magic            : Uint2B                //标志字
   +0x002 MajorLinkerVersion : UChar      //连接器主版本号
   +0x003 MinorLinkerVersion : UChar        //连接器次版本号
   +0x004 SizeOfCode       : Uint4B                //所有含有代码区块的总大小
   +0x008 SizeOfInitializedData : Uint4B        //所有初始化数据区块总大小
   +0x00c SizeOfUninitializedData : Uint4B    //所有未初始化数据区块总大小
   +0x010 AddressOfEntryPoint : Uint4B        //程序执行入口RVA
   +0x014 BaseOfCode       : Uint4B                //代码区块起始RVA
   +0x018 BaseOfData       : Uint4B                //数据区块起始RVA
   +0x01c ImageBase        : Uint4B                //程序默认装载基地址
   +0x020 SectionAlignment : Uint4B            //内存中区块的对齐值
   +0x024 FileAlignment    : Uint4B                //文件中区块的对齐值
   +0x028 MajorOperatingSystemVersion : Uint2B    //操作系统主版本号
   +0x02a MinorOperatingSystemVersion : Uint2B    //操作系统次版本号
   +0x02c MajorImageVersion : Uint2B                    //用户自定义主版本号
   +0x02e MinorImageVersion : Uint2B                    //用户自定义次版本号
   +0x030 MajorSubsystemVersion : Uint2B            //所需要子系统的版本号
所需要子系统的次版本号
   +0x034 Win32VersionValue : Uint4B                    //保留
   +0x038 SizeOfImage      : Uint4B                            //映像装入后的总尺寸
   +0x03c SizeOfHeaders    : Uint4B                        //Dos头,Pe头部,区块表总大小
   +0x040 CheckSum         : Uint4B                        //映像效验和
   +0x044 Subsystem        : Uint2B                        //文件子系统
   +0x046 DllCharacteristics : Uint2B                    //显示DLL特征的旗标
   +0x048 SizeOfStackReserve : Uint4B                //初始化堆栈大小
   +0x04c SizeOfStackCommit : Uint4B                   //初始化实际提交堆栈大小
   +0x050 SizeOfHeapReserve : Uint4B                //初始化保留堆栈大小
   +0x054 SizeOfHeapCommit : Uint4B                //初始化实际保留堆栈大小
   +0x058 LoaderFlags      : Uint4B                    //与调试相关,通常设置0
   +0x05c NumberOfRvaAndSizes : Uint4B        //数据目录表的项数
   +0x060 DataDirectory    : [16] _IMAGE_DATA_DIRECTORY    //指向导出导入表 重定位表等.

nt!_IMAGE_DATA_DIRECTORY
   +0x000 VirtualAddress   : Uint4B    //数据块初始的RVA
   +0x004 Size             : Uint4B        //数据块的长度

_IMAGE_NT_HEADERS后面紧跟着——IMAGE_SECTION_HEADER结构
 nt!_IMAGE_SECTION_HEADER
   +0x000 Name             : [8] UChar        //8个字节的块名
   +0x008 Misc             : __unnamed    //区块尺寸
   +0x00c VirtualAddress   : Uint4B        //区块的RVA地址
   +0x010 SizeOfRawData    : Uint4B    //在文件中对齐后的尺寸
   +0x014 PointerToRawData : Uint4B    //在文件中偏移
   +0x018 PointerToRelocations : Uint4B    //在OBJ文件中使用。重定位的偏移
   +0x01c PointerToLinenumbers : Uint4B    //行号表的偏移
   +0x020 NumberOfRelocations : Uint2B    //在OBJ文件中使用,重定位项数目
   +0x022 NumberOfLinenumbers : Uint2B    //行号表中行号的数目
   +0x024 Characteristics  : Uint4B            //    区块的属性
 
 

输入表
typedef struct _IMAGE_IMPORT_DESCRIPTOR {

DWORD    OriginalFirstThunk;        //它指向first thunk,IMAGE_THUNK_DATA,该thunk拥有Hint和Function name的地址。

DWORD    TimeDateStamp;        //如果那里有绑定的话它包含时间/数据戳

DWORD     ForwarderChain;        //在老版的绑定中,它引用API的第一个forwarder chain(传递器链表)。

DWORD     Name;                        //DLL 名称的相对虚地址

DWORD      FirstThunk;                //IMAGE_THUNK_DATA定义的 first thunk数组的相对地址
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; 




#define IMAGE_NT_SIGNATURE   0X00004550

"PE\0\0" 字串是PE文件头的开始

IMAGE_FILE_HEADER ---- { Size 14H }

IMAGE_OPTIONAL_HEADER ---- { Size 60H}  

IMAGE_DATA_DIRECTORY ---- { Size 80H}
 
区块 
IMAGE_SECTION_HEADER ---- { Size 28H}  
 
输入表结构
IMAGE_IMPORT_DESCRIPTOR   -- FirstThunk 包含指向输入地址表的RVA。

IMAGE_THUNK_DATA  值得最高位为1时,表示函数以序号方式输入,这时低31位被看做是一个函数富豪。当双子的最高位为0时,表示函数以字符串类型的函数名方式输入,这时双子的值是一个RVA,指向一个IMAGE_IMPORT_BY_NAME结构

IMAGE_IMPORT_BY_NAME   -   Name的大小定义为字节  它是可变长寸域。

文件偏移 = RVA(相对虚拟地址) - (Voffset(虚拟偏移)-Roffset(物理偏移))    
图片
图片
640H(文件偏移)=2040H - (2000H-600H)

图片
输入表 IID 数组 每个IID包含5个双字
OrignalFirstThunk    TimeDataStmp  ForwardChan     Name            FirstThunk
0000208C                00000000           00000000        00002174       00002010
................
Name的文件偏移 774 = 2174-1A00
图片



输入表分析


绑定输入
IMAGE_BOUND_IMPORT_DESCRIPTOR

typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
    DWORD   TimeDateStamp;//包含一个呗输入DLL的时间/日期;允许加载器快速判断绑定是不是新的
    WORD    OffsetModuleName;//包含一个指向被输入DLL的名称的偏移。这个字段是与第一个IBID结构之间的偏移.
    WORD    NumberOfModuleForwarderRefs;        //它包含紧跟在这个结构后面的IMAGE_BOUND_PORWARDER_REF结构的数目。
} IMAGE_BOUND_IMPORT_DESCRIPTOR,  *PIMAGE_BOUND_IMPORT_DESCRIPTOR;

基地址重定义
在.reloc区段
图片


资源结构
该指针具体位置是在PE文件头的88H       资源结构RVA =  PE头起始位置+88H

typedef struct _IMAGE_RESOURCE_DIRECTORY {
    DWORD   Characteristics;//理论上是资源的属性标志,但通常为0
    DWORD   TimeDateStamp;//资源建立的时间
    WORD    MajorVersion;//理论上放置资源的版本,但通常为0
    WORD    MinorVersion;
    WORD    NumberOfNamedEntries;//使用名字的资源条目的个数
    WORD    NumberOfIdEntries;//使用ID数字资源条目的个数
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
    union {
//该字段目录项的名称字符串指针或ID。当结构用于第一层目录时,定义的是资源类型;
//当结构用于第二层目录时,定义的是资源的名称;当结构用于第三层目录时,定义的是代码
//页编码,当最高位是0时,表示字段的值作为ID使用;而最高位为1时,字段的地位作为指针
//使用,资源名称字符串是食用UNICODE编码,这个指针并不是直接指向字符串,而是指向一个
//IMAGE_RESOURCE_DIR_STRING_U结构.
        struct {
            DWORD NameOffset:31;
            DWORD NameIsString:1;
        };
        DWORD   Name;
        WORD    Id;
    };
    union {
        DWORD   OffsetToData;//资源数据偏移地址或目录偏移地址
                //该字段是一个指针,最高位为1时,低位数据指向下一层目录块的起始地址;而最高位为1
//时,指针指向IMAGE_RESOURCE_DATA_ENTRY结构. 
        struct {
            DWORD   OffsetToDirectory:31;
            DWORD   DataIsDirectory:1;
        };
    };
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
 
typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
    WORD    Length;//字符串长度
    WCHAR   NameString[ 1 ];//UNICODE字符串,字对其的,长度是可变的,由Length指明长度.
} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;
 
图片
下一10H   _IMAGE_RESOURCE_DIRECTORY_ENTRY  分别是 800000A8
表示下面有资源  继续进入第三层
分别指向  资源的地址 和 大小


TLS初始化
typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD   StartAddressOfRawData;//内存起始地址,用于初始化一个新线程的TLS
    DWORD   EndAddressOfRawData;//内存终止地址,用于初始化一个新线程的TLS
    PDWORD  AddressOfIndex;//运行库使用这个索引来定位线程局部变量
    PIMAGE_TLS_CALLBACK *AddressOfCallBacks;//PIMAGE_TLS_CALLBACK函数指针数组的地址
    DWORD   SizeOfZeroFill;//后面跟零个数
    DWORD   Characteristics;//保留
} IMAGE_TLS_DIRECTORY32;
AddressOfCallBack是iancheng简历和退出iho的回调函数,包括主线程哦其他线程。当一个线程诶创建或销毁时,在列表中的每一个函数被调用,一般程序都没有回调函数,这个列表是空的。有一点特别注意,程序运行时,TLS数据初始化和TLS回调函数都在入口点之前执行,也就是说,TLS是程序最开始运行的ifa那个,许多病毒或外壳程序就是利用这点执行一些特殊操作,程序退出时,TLS回调函数再次被执行一次。
在IMAGE_TLS_DIRECTORY结构中的中的地址是虚拟地址,而不是RVA。这样,如果可执行文件不是从基地址装入,那么这些地址就会用过基址定位来修改,而且,IMAGE_TLS_DIRECTORY本身并不在.TLS区块中,它存在与.rdata区块中.
 


输出表结构
typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;//未使用,总是未0 
    DWORD   TimeDateStamp;//文件生成时间
    WORD    MajorVersion;//主版本号
    WORD    MinorVersion;//次版本号
    DWORD   Name;//模块的真是名称
    DWORD   Base;//基数,加上学术就是函数地址数组的索引值
    DWORD   NumberOfFunctions;//AddressOfFunctions阵列中的元素个数
    DWORD   NumberOfNames;//AddressOfNames阵列中的元素个数
    DWORD   AddressOfFunctions;     //指向函数地址数组
    DWORD   AddressOfNames;         //函数名字的指针地址
    DWORD   AddressOfNameOrdinals;  //指向输出序列号数组
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

 





PE结构  结构分布
IMAGE_FILE_HEADER   从 50 45 00 00   开始   Size 14H
图片

IMAGE_OPTIONAL_HEADER   从IMAGE_FILE_HEADER    尾部开始   Size 60H
图片

IMAGE_DATA_DIRECTORY  从IMAGE_OPTIONAL_HEADER    尾部开始  Size 80H
图片

区块    前8个字节为块名     IMAGE_SECTION_HEADER
图片



posted @ 2020-11-30 11:30  adobase  阅读(104)  评论(0)    收藏  举报