In layman's language PE file format --- yourself to build PE Show Author: // and clean opening ///// Hello everyone! I have a rookie, learning and encrypting decryption has been a period of time, but I always understand that it is not understanding for the shell, and my heart is very uncomfortable. So starting from the PE structure, I found that I have to really understand the PE file structure in the process of learning, I can only understand him, I feel him until you apply him ................ this is my point. I hope everyone will not be troublesome. Here is my study notes, I hope to bring you a little prompt. If you have any places in the text, please ask your prawn to correct. Thank you! //// Prepare /// I want to at least you have to start: 1. ICZelion's Win32 Assembly Tutorial We are mainly to achieve our function function around his PE tutorial. (In fact, Win32ASM Tutorial Resource Kit v1.00 colled and packed by DreamTheater contains these or translated. Downloads www.pediy.com) Download, I hope you can look at it, so everyone will communicate :-)
2. A development environment. (I use VC 6.0) 3. A environment that suits you research. // body //////
"PE means portable executable. It is the implementation body file format of the Win32 environment itself. Its features inherited from Unix's Coff (Common Object File Format file format." Portable Executable (Portable Executive) means that this file format is crosswin32 platform: even if Windows runs on a non-Intel's CPU, all Win32 platform PE loaders can identify and use this file format. Of course, transplanting to different The PE executives on the CPU must have some changes. All Win32 executives (in addition to VXD and 16-bit DLL) use PE file format, including NT's kernel mode driver (Kernel ModedRivers). Therefore, research PE file format gives us It is a good opportunity for Windows structures. "Well, the above words are why we study the PE file structure. Look at Figure 1,
This picture I believe everyone is not strange, the first piece is DOS MZ HEADER? What is this? What does every piece of this picture mean? From programming this, each of the drawings represents a structure, which contains different sub-blocks and some structures. Every small piece has his own function, I believe that ICZelion's tutorial has been understood very well. Then let's start your hands. We want to design our own PE Tools ---- PE SHOW main function: 1 Judge whether the file is a PE file. 2 Display information about the PE file.
1. Open the file code as follows: if (false == pefile.open (m_filename, cfile :: typebinary | cfile :: sharedenynne)) {MessageBox ("file can't open!"); Return;} How to use the CFILE class Big and yourself look for MSDN2. Document We opened and opened in a binary method, what should we do below? Write the first function ---- Test the validity of the PE file There is such a paragraph in the tutorial of ICZelion's: "1. First verify that the value of the first word of the file header is equal to image_dos_signature, the DOS MZ HEADER is effective 2. Once the DOS Header of the document is proved, you can locate the Pe Header with E_LFANew. 3. Compare the value of the first word of Pe Header equal to image_nt_header. If the two values are matched before and after, then we think that The file is an effective PE file. This is the process of verifying the validity of the PE file. From above, we see the key to the judgment is whether the value of the first word of Pe Header is equal to Image_NT_HEADER until these we will find it. What is the value of the first word of the PE header is just what I look IMAGE_NT_HEADERS structure :( View WINNT.H to find) typedef struct _IMAGE_NT_HEADERS? {DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader;} IMAGE_NT_HEADERS32, * PIMAGE_NT_HEADERS32; Signature One DWORD type, the value is 50h, 45H, 00H, 00h (PE / 0/0). The domain is a PE tag, we can identify if a given file is a valid PE file. FileHeader This domain contains the PE file Information of physical distribution, such as the number of times, file execution machine, etc. OptionalHeader This domain contains information about the logic distribution of PE files, although the domain name is "optional", but in fact this structure always exists. Our purpose is very clear. If IMAGE_NT_HEADERS the signature field value is equal to "PE / 0/0", then it is a valid PE file. in fact, for more convenient, Microsoft has defined a constant IMAGE_NT_SIGNATURE for .IMAGE_DOS_SIGNATURE equ 5A4Dh IMAGE_OS2_SIGNATURE equ 454Eh IMAGE_OS2_SIGNATURE_LE equ 454Ch we use Image_vxd_signature EQU 454ch image_nt_signature EQU 455 0H
The problem of judgment us solved, the new problem has come to how we locate the image of the Image_nt_Headers structure.
MS is definitely a way, what is the beginning of the PE file? DOS MZ Header structure, let's take a look at his definition: type_dos_header {// dos .exe header word e_magic; // magic number word e_cblp; // bytes on la cast 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; look at the last item! ! ! ! ! Did you find it? What he pointed to PE Header then is the location of DOS MZ HEADER? Oh, he is the beginning of the document: pefile.read (& sttedosheader); if (_image_dos_header)); if (stpedosheader.e_magic! = Image_dos_signature) // "MZ" {MessageBox ("DOS MZ HEADER is invalid!"); Pefile. Close (); Return;
} Else {// --------------------- // Show dos header // --------------- ------- Updatedata (TRUE); m_magicnumber.format (_t ("0x% .4x"), stpedosheader.e_magic; m_cblp.format (_t ("0x% .4x"), stpedosheader.e_cblp) ; M_cp.format (_t ("0x% .4x"), stpedosheader.e_cp); m_crc.format (_t ("0x% .4x"), stpedosheader.e_crlc); m_cparhdr.format (_t ("0x% .4x "), stpedosheader.e_cparhdr); m_minalloc.format (_t (" 0x% .4x "), stpedosheader.e_minalloc); m_maxalloc.format (_t (" 0x% .4x "), stpedosheader.e_maxalloc); m_ss.format ( _T ("0x% .4x"), stpedosheader.e_ss); m_sp.format (_t ("0x% .4x"), stpedosheader.e_sp); m_csum.format (_t ("0x% .4x"), StPedosheader. E_CSUM); m_ip.format (_t ("0x% .4x"), stpedosheader.e_ip); m_cs.format (_t ("0x% .4x"), stpedosheader.e_cs); m_lfarlc.format (_t ("0x% .4x "), stpedosheader.e_lfarlc); m_ovno.format (_t (" 0x% .4x "), stpedosheader.e_ovno; m_oemid.format (_t (" 0x% .4x "), stpedosheader.e_oemid; m_oemfo. Format (_t ("0x% .4x"), stpedosheader.e_oeminfo; m_lfanew.format (_t ("0x% .8x"), stpedosheader.e_lfanew; Updateda Ta (false);} buf = stpedosheader.e_lfaNew; // Determine _Image_dos_header offset try {pefile.seek;} catch (...) {messagebox ("_ image_dos_header.e_lfanew is wrong!" ); Pefile.close (); return;} pefile.read (& stpeheader, sizeof (_IMAGE_NT_HEADERS)); // ---------- NT header if (stpeheader.signature! = Image_nt_signature) // "PE / 0/0 "{MessageBox (" This file is not a PE format! "); Pefile.close (); return;} else {MessageBox (" This file is PE format! "); Pefile.close (); return;}
Ok, now we have determined whether the file is a valid PE file. By the way, we have displayed the structural members of Image_DOS_HEADER. We have written a feature. Below we will continue to look down: Image_dos_header structure ends that image_nt_headers start. In front of the member of the structure, we have already introduced the following we have to extract them: // ------------------------- // Display Image_File_Header Structure // ------------------------- Updatedata (TRUE); m_machine.format (_t ("0x% .4x"), StpeHeader .FileHeader.Machine); m_NumberOfSections.Format (_T ( "0x% .4X"), stPEHeader.FileHeader.NumberOfSections); m_TimeDateStamp.Format (_T ( "0x% .8X"), stPEHeader.FileHeader.TimeDateStamp); m_PointerToSymbolTable. Format (_T ( "0x% .8X"), stPEHeader.FileHeader.PointerToSymbolTable); m_NumberOfSymbols.Format (_T ( "0x% .8X"), stPEHeader.FileHeader.NumberOfSymbols); m_SizeOfOptionalHeader.Format (_T ( "0x%. 4X "), stPEHeader.FileHeader.SizeOfOptionalHeader); m_Characteristics.Format (_T (" 0x% .4X "), stPEHeader.FileHeader.Characteristics); UpdateData (false); it is a member of IMAGE_FILE_HEADER FileHeader, we have extracted from them . Look at the tutorial we continue to look for members of Image_Optional_Header, he is the structure in the structure, we will follow. typedef struct _IMAGE_OPTIONAL_HEADER {// // Standard fields // WORD Magic;. BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData;
/// Nt Additional fields. //
DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit ; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES];} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32; see these members will be displayed them all
// -------------------------------- // Display image_optional_header // ---------- --------------------- Updatedata (true); m_magic.format (_t ("0x% .4x"), stpehead.OptionalHeader.magic; m_majorlinkerversion. Format (_T ("0x% .2x"), stpehead.optionalHeader.majorlinkerversion); m_minorlinkerversion.format (_t ("0x% .2x"), stpehead.optionalHeader.minorlinkerversion; m_sizeofcode.format (_t ("0x%. 8X "), stPEHeader.OptionalHeader.SizeOfCode); m_SizeOfInitializedData.Format (_T (" 0x% .8X "), stPEHeader.OptionalHeader.SizeOfInitializedData); m_SizeOfUninitializedData.Format (_T (" 0x% .8X "), stPEHeader.OptionalHeader. SizeOfUninitializedData); m_AddressOfEntryPoint.Format (_T ( "0x% .8X"), stPEHeader.OptionalHeader.AddressOfEntryPoint); m_BaseOfCode.Format (_T ( "0x% .8X"), stPEHeader.OptionalHeader.BaseOfCode); m_BaseOfData.Format (_T ("0x% .8X"), stpeheader.optionalheader.baseofdata); m_imagebase.format (_t ("0x% .8x"), stpehead.OptionalHeader.ImageBase; m_sectionalignment.format (_t ("0x% .8x") STPEHEADER.OPTIONALHEADER.S ectionAlignment); m_FileAlignment.Format (_T ( "0x% .8X"), stPEHeader.OptionalHeader.FileAlignment); m_MajorOperatingSystemVersion.Format (_T ( "0x% .4X"), stPEHeader.OptionalHeader.MajorOperatingSystemVersion); m_MinorOperatingSystemVersion.Format (_T ( "0x% .4X"), stPEHeader.OptionalHeader.MinorOperatingSystemVersion); m_MajorImageVersion.Format (_T ( "0x% .4X"), stPEHeader.OptionalHeader.MajorImageVersion); m_MinorImageVersion.Format (_T ( "0x% .4X") STPEHEADER.OPTIONALHEADER.MINORIMAGEVERSION; M_MAJORSUBSYSTEMVERSION.FORMAT (_t ("0x% .4x"), StpeHeader.OptionalHeader.majorsubsystemVersion;
m_MinorSubsystemVersion.Format (_T ( "0x% .4X"), stPEHeader.OptionalHeader.MinorSubsystemVersion); m_Win32VersionValue.Format (_T ( "0x% .8X"), stPEHeader.OptionalHeader.Win32VersionValue); m_SizeOfImage.Format (_T ( "0x % .8x "), stpeheader.optionalheader.sizeofimage; m_sizeofheaders.Format (_t (" 0x% .8x "), stpeheader.OptionalHeader.sizeOfheaders; m_checksum.format (_t (" 0x% .8x "), StpeHeader. OptionalHeader.CheckSum); m_Subsystem.Format (_T ( "0x% .4X"), stPEHeader.OptionalHeader.Subsystem); m_DllCharacteristics.Format (_T ( "0x% .4X"), stPEHeader.OptionalHeader.DllCharacteristics); m_SizeOfStackReserve.Format (_T ( "0x% .8X"), stPEHeader.OptionalHeader.SizeOfStackReserve); m_SizeOfStackCommit.Format (_T ( "0x% .8X"), stPEHeader.OptionalHeader.SizeOfStackCommit); m_SizeOfHeapReserve.Format (_T ( "0x% .8X "), stPEHeader.OptionalHeader.SizeOfHeapReserve); m_SizeOfHeapCommit.Format (_T (" 0x% .8X "), stPEHeader.OptionalHeader.SizeOfHeapCommit); m_LoaderFlags.Format (_T (" 0x% .8X "), stPEHeader.OptionalHeader.LoaderFlags ); M_numberofrv Aandsizes.Format (_t ("0x% .8x"), stpeheader.optionalheader.NumberofrvaAndsizes; Updatedata (false);
We have learned a lot about DOS HEADER and PE HEADER. Next, it will be the step Table. The section table is actually an array of structures next to PE Header. The number of members of the array is determined by the domain value of the NumberOfSections domain in the file header (Image_file_Header). The knot structure is named image_section_header. typedef struct _IMAGE_SECTION_HEADER {BYTE Name [IMAGE_SIZEOF_SHORT_NAME]; union {DWORD PhysicalAddress; DWORD VirtualSize;} Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics;} IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADERName The section of this is not more than 8 bytes. Remember that the name is just a tag, we choose any name or even empty, pay attention to the end of NULL. Name is not an ASCIIZ string, so you don't have to end with NULL. VirtualAddress's RVA (relative virtual address) in this section. The PE loader reads this value when it is mapped to memory, so if the domain value is 1000h, the PE file is installed at 400000H, then this section is contained in 401000h. The SIZEOFRAWDATA is aligned with the post size, and the PE loader extracts the domain value to understand the number of the number of personns that need to be mapped into the memory. (Translator Note: Suppose a file's file alignment size is 0x200, if the previous VirtualSize domain indicates that this section is 0x388 bytes, the domain value is 0x400, indicating that this section is 0x400 byte length). PointertorawData This is a section of the file, and the PE loader finds the location of the data in the file via this domain value. Characteristics contains tags to indicate feature properties, such as whether the festival contains executable code, initialized data, not initial data, can be writable, readable, and so on.
Now we have known the image_section_header structure, and then simulate the work of the PE loader:
1 Read image_file_header's NumberOfSections domain, know the number of files. 2 SIZEOFHEADERS domain values As the file offset of the section table, and locate the section table. 3 Traverse the entire structure array to check each member value. 4 For each structure, we read the PointertorawData domain value and locate the file offset. Then read the SIZEOFRAWDATA domain value to determine the number of bytes that map the memory. Plus the VirtualAddress domain value plus the imagebase domain value equal to the virtual address starting. Then you will refill the section into the memory and set the properties according to the CHARACTERISTICS domain value. 5 Trail through the entire array until all sections have been processed. The code is as follows: // ----------------------------- // Display section structure // -------- ---------------------- nSECTION = stpeheader.fileHeader.Numberofsections; StSECTIONHEADER = New _Image_section_header [nSECTION]; m_listctrl.deleteallItems (); for (int i = 0 ; i {
Pefile.read (& StSECTIONHEADER [I], SIZEOF (_IMAGE_SECTION_HEADER); // ----- Section Table
// NO
SzTemp.format (_t ("%. 2D"), i 1);
M_ListCtrl.insertItem (i, sztemp, i);
// sectionname
Strcpy (chsectionname, (lpcstr) StSECTIONHEADER [i] .name);
M_ListCtrl.SetItemText (i, 1, chsectionname);
// virtualsize
SzTemp.Format (_t ("0x% .8x"), stsectionheader [i] .misc.virtualsize;
M_ListCtrl.SetItemText (i, 2, sztemp);
// VirtualAddress
SzTemp.Format (_t ("0x% .8x"), StSECTIONHEADER [I] .virtualAddress;
M_ListCtrl.SetItemText (i, 3, sztemp);
// sizeofrawdata
SzTemp.Format (_t ("0x% .8x"), StSECTIONHEADER [i] .sizeofrawdata);
M_ListCtrl.SetItemText (i, 4, sztemp);
// SizeOffset
SzTemp.Format (_t ("0x% .8x"), StSECTIONHEADER [i] .pointertorawdata);
M_ListCtrl.SetItemText (i, 5, sztemp);
// Characteristics
Sztemp.format (_t ("0x% .8x"), StSECTIONHEADER [i] .Characteristics;
M_ListCtrl.SetItemText (i, 6, sztemp);
}
Delete StSECTIONHEADER;
Ok, the two functions we plan have been written, let's take a look at the operation.
figure 2
Not too early, I am going to sleep (2003-12-18 2:02) Other functions Next, the next one is mainly to extract the Import Table first look at the tutorial
Haha, I almost forgotten.
All complete code I put it in the compressed file. I have a probably understanding of PE, and I will send you a PE structure map I collected online. Don't forget to do it when you write.
Sleeping, sleeping ,,, it is dying!
886
Inexpensive
2003-12-18 2:07
// Thank Lao Luo corrects the CHSECTIONNAME array definition error causes the bug that is terminated. / / Please download the brothers of the excessive code from the new download
Program and source code download: http://winRoot.shyper.com/bbs/attachment.php? AID = 5