逆-PEヘッダ解析

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

おすすめ

転載: www.cnblogs.com/wan-xiang/p/11858748.html