After reading the detailed explanations of various parts of the PE file in the Software Encryption technology book, I also had the idea of writing the PE file analyzer myself. Although a good analyzer is not a minority, some friends may not understand what it means for a heap of hexadecimal numbers. If you can convert the 01 series in the program to read and understand the information directly, you can at least save the trouble of going to the lookup table later. With this idea, I carefully studied the source code of the PEInfo analyzer in the book. I found that it does not provide the information conversion function.
Through research, we found that PEInfo obtains file information through the PE file's memory image. I was wondering if there were other ways to bypass the file image to memory step, directly read the file information. In this way, you can only directly read the PE files on the disk and find the required file information on the disk.
For the time being, I will not talk about the advantages and disadvantages of this method and the memory image method. Here I just want to find another way to solve the problem and implement it. After reading my analysis and source program, you will naturally know that the advantages and disadvantages of the solution are superior to those of the solution.
To avoid confusion, the program uses a variable name similar to the PE standard to define key data, such as file headers, optional file headers, section tables, import tables, and export tables, the detailed name definition can be found in winnt. h. The entire program is written in a process-oriented manner and appropriately integrates the object-oriented features. I encapsulate the read PE file information in a DataDump object to facilitate data management and finally output analysis reports. The Analysis of files involves a series of subprograms. The subprograms are described as follows:
// Configure //-------------------------------------------------------------------------------------------------------------------
BOOL Is_EXE_file (ifstream & PE_file) // checks whether the PE file is valid. If yes, true is returned; otherwise, false is returned.
BOOL OutReady (CHAR filename [], ofstream & fout) // prepare the output, including the output stream and output file. If yes, true is returned. Otherwise, false is returned.
VOID WriterInfo (ofstream & fout) // output the program version information
BOOL Load_EXE_Info (ifstream & PE_file) // read the PE file information. If the PE file information is successfully read, true is returned. Otherwise, false is returned.
VOID Decode_EXE_Info (CHAR filename [], BOOL IsEXE, ifstream & PE_file, ofstream & fout) // analyze PE File Information
VOID ToNumeric (LPDWORD ptr, CHAR buf [], INT start, INT size) // convert the character array from the start bit to a value, put in the DWORD type variable pointed to by ptr
VOID ToString (LPSTR ptr, CHAR buf [], INT start, INT size) // obtains the size after the start bit from the character array, put in a character array pointed to by ptr
// Configure //-------------------------------------------------------------------------------------------------------------------
Class DataDump
{
Private:
IMAGE_FILE_HEADER FILE_HEADER; // IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER32 OPTIONAL_HEADER32; // IMAGE_OPTIONAL_HEADER32
PIMAGE_SECTION_HEADER SECTION_HEADER; // PIMAGE_SECTION_HEADER
IMAGE_IMPORT_DESCRIPTOR IMPORT_DESCRIPTOR; // IMAGE_IMPORT_DESCRIPTOR
PIMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY; // PIMAGE_EXPORT_DIRECTORY
DWORD ExVRk, ImVRk; // The Difference Between the offset of the input table and the RVA in the disk file
Public: // You can get the functions of these member functions below by their names.
DataDump ();
~ DataDump ();
BOOL Set_FILE_HEADER (CHAR [], INT );
BOOL Set_OPTIONAL_HEADER32 (CHAR [], INT );
BOOL Set_SECTION_HEADER32 (CHAR [], INT );
BOOL Set_EXPORT_TABLE (CHAR [], INT );
VOID GetReady (CHAR []);
DWORD Get_OPTIONAL_HEADER_SIZE (VOID) const;
DWORD Get_SECTION_NUMBER (VOID) const;
DWORD Get_EXPORT_TABLE_RAW (VOID) const;
DWORD Get_IMPORT_TABLE_RAW (VOID) const;
VOID Set_Export_VRk (VOID );
VOID Set_Import_VRk (VOID );
BOOL Export_Table_Existed (VOID) const;
BOOL Import_Table_Existed (VOID) const;
BOOL Show_FILE_HEADER (ofstream &) const;
BOOL Show_OPTIONAL_HEADER32 (ofstream &) const;
BOOL Show_SECTION_HEADER32 (ofstream &) const;
BOOL Show_EXPORT_TABLE (ifstream &, ofstream &) const;
BOOL Show_IMPORT_TABLE (ifstream &, ofstream &) const;
};
DataDump pool;
// Configure //-------------------------------------------------------------------------------------------------------------------
The instance of the DataDump class is a global object. This facilitates the subroutine to access this object. The basic idea of the program is to open the PE file on the disk and determine whether it is a valid PE file. Otherwise, the program outputs an error message and exits. If yes, the program analyzes the file, including reading the file header, optional file headers, section tables, import tables, and export tables, store information in the DataDump class, and finally output an analysis report in the form of a txt file.
The key to the program is to "locate and read" the file information. The file header. Optional file headers and partition tables are stored in sequence on the disk. Skip the start PE flag to easily find the above segments, in addition, the exact size of each part is described in their related attributes. As you can know when the program is running, it is easy to read information. The size of the input and output tables is uncertain. Sometimes there may be no input or output tables, and the position of the input and output tables is not fixed, this makes reading the input and output tables difficult.
We know that a certain item in a PE file is generally a relative virtual address RVA, and cannot directly correspond to the physical address of the disk file. In the memory image-based method, you only need to obtain RVA and perform simple operations with ImageBase to locate the storage address of a data item in the memory. In the method of Directly Reading disk files, the conversion from RVA to RAW must be involved. Therefore, the key conversion for reading an input/output table is to locating the input/output table in a disk file.
The following is a common conversion method and example:
+ --------- +
| Segment name virtual address virtual size physical address physical size mark |
+ --------- +
| Name & nbs