PEヘッダ解析
PE実行可能ファイル形式は、Windowsのシステムの下で組織の形式です。PEファイルヘッダと対応するデータ。目標は、書き換えることなく、異なるアーキテクチャでローダとプログラミングツールです。
ベースアドレス(イメージベース)PEファイルの反対側にオフセット記録された記録位置の主要な機能の大半でPEは、不連続相対アドレス(RVA)です。プロセスは、各プロセスに関連して調製された状態のプログラムを実行するエンティティは、独自の別個のメモリ(アドレッシング)空間PEとカーネルとを有しているので、画像ベースが常に決定されないように。
構造(参考:暗号化と復号化)
データの構造
IMAGE_DOS_HEADER
参考:参考:http://www.openrce.org/reference_library/files/reference/PE%20Format.pdf
IMAGE_DOS_HEADER STRUCT
{
+0h WORD e_magic //Magic DOS signature MZ(4Dh 5Ah) DOS可执行文件标记
+2h WORD e_cblp //Bytes on last page of file
+4h WORD e_cp //Pages in file
+6h WORD e_crlc //Relocations
+8h WORD e_cparhdr //Size of header in paragraphs
+0ah WORD e_minalloc //Minimun extra paragraphs needs
+0ch WORD e_maxalloc //Maximun extra paragraphs needs
+0eh WORD e_ss //intial(relative)SS value DOS代码的初始化堆栈SS
+10h WORD e_sp //intial SP value DOS代码的初始化堆栈指针SP
+12h WORD e_csum //Checksum
+14h WORD e_ip // intial IP value DOS代码的初始化指令入口[指针IP]
+16h WORD e_cs //intial(relative)CS value DOS代码的初始堆栈入口
+18h WORD e_lfarlc //File Address of relocation table
+1ah WORD e_ovno // Overlay number
+1ch WORD e_res[4] //Reserved words
+24h WORD e_oemid // OEM identifier(for e_oeminfo)
+26h WORD e_oeminfo // OEM information;e_oemid specific
+29h WORD e_res2[10] // Reserved words
+3ch DWORD e_lfanew //Offset to start of PE header PE头相对于文件的偏移地址
} IMAGE_DOS_HEADER ENDS
DOS PEは互換16ビットプログラムされる最初であるため、今32であり、64ビット、我々は唯一(16のシステムは冗長PEヘッダとコンテンツデータである)は、2つの部材の構造を気に
e_lfanew e_magic、(最初と最後)
- e_magicはMZ 0x4D5AはPEファイル(だけでなく)かどうかを決定する符号であります
- e_lfanew PEは、ファイルの先頭アドレスに対するオフセット
図3CHは、PEの含有量はビット0000000e(小端記憶)の内容の先頭アドレスであるe_lfanew。
我々は、これは無用のためDOSスタブプログラムメモリ16、32、64ビットシステムと呼ばれるDOS PEヘッドとヘッドピース離間されている領域を見ることができます
PNTHeader = IMAGEBASE +(dosHeader-> e_lfanew)
IMAGE_NT_HEADERS
typedef struct _IMAGE_NT_HEADERS {
+0 hDWORD Signature //
+4h IMAGE_FILE_HEADER FileHeader //
+18h IMAGE_OPTIONAL_HEADER32 OptionalHeader //
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
#define IMAGE_NT_SIGNATURE 0x00004550
- 署名は0x00004550に固定されています
IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER {
+04h WORD Machine;//04h相对于_IMAGE_NT_HEADERS的,运行平台
+06h WORD NumberOfSections;//文件的区块数(*重要)
+08h DWORD TimeDateStamp;//文件创建时间 和unix时间戳一样int(secound(now-19700101))
+0cH DWORD PointerToSymbolTable;//指向符号表(主要用于调试)
+10H DWORD NumberOfSymbols;//符号表中符号个数(同上)
+14H WORD SizeOfOptionalHeader;//IMAGE_OPTIONAL_HEADER32 结构大小(*重要)IMAGE_OPTIONAL_HEADER是长度可变的。
+16H WORD Characteristics;//文件属性多,种属性通过 “或运算” 同时拥有
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
IMAGE_OPTIONAL_HEADER(*重要)
由IMAGE_FILE_HEADER的SizeOfOptionalHeader决定大小(可变长)
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
+18h WORD Magic; // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
+1Ah BYTE MajorLinkerVersion; // 链接程序的主版本号
+1Bh BYTE MinorLinkerVersion; // 链接程序的次版本号
+1Ch DWORD SizeOfCode; // 所有含代码的节的总大小
+20h DWORD SizeOfInitializedData; // 所有含已初始化数据的节的总大小
+24h DWORD SizeOfUninitializedData; // 所有含未初始化数据的节的大小
+28h DWORD AddressOfEntryPoint; // 程序执行入口RVA
+2Ch DWORD BaseOfCode; // 代码的区块的起始RVA
+30h DWORD BaseOfData; // 数据的区块的起始RVA
//
// NT additional fields.
//
+34h DWORD ImageBase; // 文件在内存中的的首选装载地址。
+38h DWORD SectionAlignment; // 内存中的区块的对齐大小
+3Ch DWORD FileAlignment; // 文件中的区块的对齐大小
+40h WORD MajorOperatingSystemVersion; // 要求操作系统最低版本号的主版本号
+42h WORD MinorOperatingSystemVersion; // 要求操作系统最低版本号的副版本号
+44h WORD MajorImageVersion; // 可运行于操作系统的主版本号
+46h WORD MinorImageVersion; // 可运行于操作系统的次版本号
+48h WORD MajorSubsystemVersion; // 要求最低子系统版本的主版本号
+4Ah WORD MinorSubsystemVersion; // 要求最低子系统版本的次版本号
+4Ch DWORD Win32VersionValue; // 莫须有字段,不被病毒利用的话一般为0
+50h DWORD SizeOfImage; // 映像装入内存后的总尺寸
+54h DWORD SizeOfHeaders; // 所有头 + 区块表的尺寸大小
+58h DWORD CheckSum; // 映像的校检和
+5Ch WORD Subsystem; // 可执行文件期望的子系统
+5Eh WORD DllCharacteristics; // DllMain()函数何时被调用,默认为 0
+60h DWORD SizeOfStackReserve; // 初始化时的栈大小
+64h DWORD SizeOfStackCommit; // 初始化时实际提交的栈大小
+68h DWORD SizeOfHeapReserve; // 初始化时保留的堆大小
+6Ch DWORD SizeOfHeapCommit; // 初始化时实际提交的堆大小
+70h DWORD LoaderFlags; // 与调试有关,默认为 0
+74h DWORD NumberOfRvaAndSizes; // 下边数据目录的项数,这个字段自Windows NT 发布以来 // 一直是16
+78h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];// 数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
ファイルは、アプリケーション・ローダーベース移転のためのこの位置を占めることになる場合IMAGEBASEファイルは、メモリアドレスにロードされました。EXEファイルの場合は、各ファイルが常に使用されているため、独立した仮想アドレス空間は、一般的に他のファイルによってプリエンプトされていません。DLLファイルの場合、DLLは、ホストアドレス空間EXEファイルの複数の全て以来ファイル、優先ロードアドレスは、他のDLLを使用していない、DLLファイルが対応する、再配置情報が含まれている必要があります保証するものではありません
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
IMAGE_FILE_HEADER ->Characteristics(可以看到下面的数字位数不同,而且都是1、2、4、8他们总共加起来就是16看看二进制就知道了他们占的不是同一位与一下就能取到相对应位,linux的文件属性1、2、4也是一样的)
EXE文件的默认优先装入地址被定为00400000h,而DLL文件的默认优先装入地址被定为10000000h
AddressOfEntryPointフィールド:プログラムコードで実行されている場合、プログラム実行エントリのRVAは、のimageBase + AddressOfEntryPointが最初に実行されます。一般的なポイント.textセクション。
SectionAlignmentは:プログラムは、メモリブロック(セクション)整列サイズにロードされ、CPUメモリページを整列させる必要があり、各セクションがメモリにロードされた後(メモリページのプロパティを設定容易にするために)最小1Kh(4キロバイト)
FileAlignment:ディスクサイズ、200H(512バイト)セクタサイズの最小値にPE文書アラインメント。
Notpad.exeと整列は、ロードされnotpadが延伸しnotpad.exe winhex、を有するメモリディスクに開くことができます。
IMAGE_DATA_DIRECTORY
何これらのテーブルには、どのように詳細に説明する必要があるので、この対応テーブルは、メモリの構造の位置と大きさです。
typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; //表首地址的RVA DWORD Size; //表长度 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
以下は、我々はより多くのインポートテーブルを懸念されているMicrosoftのドキュメント、再配置テーブルに取り込まれ(DLLなど)
サイズ フィールド 説明 8 テーブルのエクスポート エクスポートテーブルのアドレスとサイズ。詳細については、を参照.edataセクション(画像のみ)を。 8 インポート表 インポートテーブルのアドレスとサイズ。詳細については、.idataセクションを。 8 リソーステーブル リソーステーブルのアドレスとサイズ。詳細については、.rsrcセクションを。 8 例外表 例外テーブルのアドレスとサイズ。詳細については、.pdataセクションを。 8 証明書表 属性証明書テーブルのアドレスとサイズ。詳細については、属性証明書テーブル(画像のみ)を。 8 基地移転表 ベースの再配置テーブルのアドレスとサイズ。詳細については、.relocセクション(画像のみ)を。 8 デバッグ デバッグデータはアドレスとサイズを開始します。詳細については、.DEBUGセクションを。 8 建築 予約済み、0でなければなりません 8 グローバルのPtr グローバル・ポインタ・レジスタに格納される値のRVA。この構造体のサイズ部材はゼロに設定されなければなりません。 8 TLS表 スレッドローカルストレージ(TLS)テーブルアドレスとサイズ。詳細については、セクションを.tls。 8 ロードコンフィグ表 ロード・コンフィギュレーション・テーブル・アドレスとサイズ。詳細については、負荷設定構造(画像のみ)。 8 バウンドのインポート バインドされたインポートテーブルのアドレスとサイズ。 8 IAT インポートアドレステーブルのアドレスとサイズ。詳細については、インポートアドレステーブルを。 8 遅延読み込み記述子 遅延読み込みディスクリプタアドレスとサイズ。詳細については、遅延ロード表をインポート(画像のみ)を。 8 CLRランタイムヘッダー CLRランタイム先頭アドレスとサイズ。詳細については、.cormetaセクション(オブジェクトのみを)。 8 予約は、ゼロでなければなりません
ブロック
ブロックマッピングテーブルからブロックは、パーティションテーブルがIMAGE_NT_HEADERSに従っ; _IMAGE_NT_HEADERS.FileHeader.NumberOfSectionsによって指定されたどのように多くのブロックテーブル。
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //8字节的name
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;//区块RVA
DWORD SizeOfRawData;//文件对齐后的尺寸
DWORD PointerToRawData;//文件中的偏移
DWORD PointerToRelocations;//
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;//区块属性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
#define IMAGE_SIZEOF_SHORT_NAME 8
名前の8バイトは、必ずしも「\ 0」文字列表現のセクションの名前を借りていません
その他には、物理アドレスは、VirtualSizeは、前のセクションの非整列サイズが何であるかを行います(正確ではない可能性があり、変更されたすべての権利、コンパイラで生成されました)
セクションは、メモリ内のRVAをオフセットアドレス。
ファイルサイズがSizeOfRawDataセクションの配置
PointerToRawDataセクション安いディスクファイル、あなたは自分のPEをロードする必要があります(ないオペレーティングシステムがロードされていない)場合、この値は、多くの用途があります。
特性のセクションの属性(コード/データ、読み取り/書き込み)
常用 #define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. #define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. #define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. #define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. #define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. #define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. #define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
ブロック上に整列
ブロックを読み取るために、整列SectionAlignmentファイル及びメモリを表す、二つの部分、FileAlignmentに整列し、効果的な所定の特性、FileAlignment SectionAlignment今や多くのプログラムと同じサイズを設定します。メモリ内SectionAlignmentアライメント値は、典型的には、4kBの(1000H)はx64で8キロバイト(2000H)は、メモリページサイズのx86です。
変換ファイルは、仮想アドレスのオフセット
FileAlignment、SectionAlignmentディスク上のPEファイルのさまざまなニーズにストレッチ。
FileOffset = VA RVA K
参考:暗号化と復号化
https://docs.microsoft.com/zh-cn/windows/win32/debug/pe-format