PEフォーマットのMS-DOS MZ headerを解読することを学びます.

11710 ワード

from:http://www.2cto.com/Article/201203/123125.html
PEの意味はこのthe Proteble Executable(PE)file formatマイクロソフトが作ったもので、字面は移植可能という意味ですが、実際の使用では彼がどれほど移植できるかは見られませんでした.PE形式はUNIXシステムのCOFF(Common Object File Format)格を参考にしました.また、PEはMS-Dosの互換性があり、MS-Dosのヘッドを保持しています.dosで開くと、「これはwin 32プログラムです.dosでは走れません.」MS-DOS MZ headerの構造はこうです.
typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header 
    WORD   e_magic;                     // Magic number 
    WORD   e_cblp;                      // Bytes on last page of file 
    WORD   e_cp;                        // Pages in file 
    WORD   e_crlc;                      // Relocations 
    WORD   e_cparhdr;                   // Size of header in paragraphs 
    WORD   e_minalloc;                  // Minimum extra paragraphs needed 
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed 
    WORD   e_ss;                        // Initial (relative) SS value 
    WORD   e_sp;                        // Initial SP value 
    WORD   e_csum;                      // Checksum 
    WORD   e_ip;                        // Initial IP value 
    WORD   e_cs;                        // Initial (relative) CS value 
    WORD   e_lfarlc;                    // File address of relocation table 
    WORD   e_ovno;                      // Overlay number 
    WORD   e_res[4];                    // Reserved words 
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo) 
    WORD   e_oeminfo;                   // OEM information; e_oemid specific 
    WORD   e_res2[10];                  // Reserved words 
    LONG   e_lfanew;                    // File address of new exe header 
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; 
その中で重要なメンバーはこれです.lfanewは、PEファイルヘッダのPEファイルにおける相対的な仮想アドレスRAVを指し、e_magicの値は0 x 5 A 4 Dに等しいはずです.MS-DOS MZ headerのマークMZはプログラマの名前の略称のようです.他のメンバーはほとんど使われていません.一部のシェルソフトはメンバーが自分の節のために空間を作ったり、追加節の形式で感染した時に表の末尾の隙間が足りないので、新しいテーブル構造を書く時にIMAGE_を書きます.DOS_HEADEとIMAGE_NTうHEADER融合.自分で小さなプログラムを書いてIMAGE_を出力してもいいです.DOS_HEADEIMAGE_DOS_HEADEという構造体はwindows.hにPE形式のファイルをロードする場合、IMAGE_を先にロードすると定義されています.DOS_HEADEという構造体は、また構造体のe_によってlfanewが提供する相対的なオフセットは、PEファイルヘッダを見つける. c言語でIMAGE_を直接読み出すことができます.DOS_HEADEという構造体は、次から書き始めます.ファイルの開始位置からIMAGE_を読みだします.DOS_HEADE構造体[cpp]view plincopyfread(&mydosheader,sized); ファイルポインタをe_に移動します.lfanewの相対的なオフセットとは、PEファイルヘッダ[cpp]view plincopyfseek(p,mydosheader.eulfanew,SEEKuSET)である. PEファイルフラグを読み、このPE SignatureはPE\0\0という値であり、PEフォーマットのアイデンティティであることを証明する.[cpp]view plincopyfread(&sig,4,1,p); この判断における大文字の変数は、windows.hの定数IMAGE_である.NTうSIGNATUREの値はPE\0\0 IMAGE_です.DOS_SIGNATUREの値はMZの具体的な定義です.自分でwindows.hを見に行きます.
if((my dos header.eumagic==IMAGEudoScut_ATURE)& (sig==IMAGE_UNT_GNATURE) printf(「有効なPEファイル/n」) else printf(「無効なPEファイル/n」) return 0; 
以下は完全なプログラムです.
#include "windows.h" 
#include "stdio.h" 
 
int main(int argc, char* argv[]) 
{ 
    FILE *p; 
    IMAGE_DOS_HEADER mydosheader; 
    unsigned long sig; 
 
    p = fopen("test1.exe","r+b"); 
    if(p == NULL)return -1; 
 
    fread(&mydosheader,sizeof(mydosheader),1,p); 
    fseek(p,mydosheader.e_lfanew,SEEK_SET); 
    fread(&sig,4,1,p); 
    fclose(p); 
 
    printf("IMAGE_DOS_HEADER dump:/n"); 
    printf("e_magic : %04x/n",mydosheader.e_magic); 
    printf("e_cblp  : %04x/n",mydosheader.e_cblp); 
    printf("e_cp   : %04x/n",mydosheader.e_cp); 
    printf("e_crlc  : %04x/n",mydosheader.e_crlc); 
    printf("e_cparhdr : %04x/n",mydosheader.e_cparhdr); 
    printf("e_minalloc: %04x/n",mydosheader.e_minalloc); 
    printf("e_maxalloc: %04x/n",mydosheader.e_maxalloc); 
    printf("e_ss   : %04x/n",mydosheader.e_ss); 
    printf("e_sp   : %04x/n",mydosheader.e_sp); 
    printf("e_csum  : %04x/n",mydosheader.e_csum); 
    printf("e_ip   : %04x/n",mydosheader.e_ip); 
    printf("e_cs   : %04x/n",mydosheader.e_cs); 
    printf("e_lfarlc : %04x/n",mydosheader.e_lfarlc); 
    printf("e_ovno  : %04x/n",mydosheader.e_ovno); 
    printf("e_res[0] : %04x/n",mydosheader.e_res[0]); 
    printf("e_oemid : %04x/n",mydosheader.e_oemid); 
    printf("e_oeminfo : %04x/n",mydosheader.e_oeminfo); 
    printf("res2[0] : %04x/n",mydosheader.e_res2[0]); 
    printf("lfanew  : %08x/n",mydosheader.e_lfanew); 
 
 
    if((mydosheader.e_magic ==IMAGE_DOS_SIGNATURE) && 
        (sig == IMAGE_NT_SIGNATURE)) 
       printf("   PE  /n"); 
    else 
      printf("   PE  /n"); 
    return 0; 
}