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の構造はこうです.
if((my dos header.eumagic==IMAGEudoScut_ATURE)& (sig==IMAGE_UNT_GNATURE) printf(「有効なPEファイル/n」) else printf(「無効なPEファイル/n」) return 0;
以下は完全なプログラムです.
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;
}