PE basic training
#include <windows.h> #include <stdio.h> struct TypeOffset { WORD Offset : 12; WORD Type : 4; }; // Save the file size DWORD FileSize = 0 ; // Save the file base address DWORD FileBase; // Save DOS head PIMAGE_DOS_HEADER DosHeader = nullptr; PIMAGE_NT_HEADERS NtHeader = nullptr; DWORD RVAtoFOA(DWORD rva) { @ 1 acquires the section table Auto SectionTables = IMAGE_FIRST_SECTION (NtHeader); // 2. Get the number of zones WORD = NtHeader- the Count> FileHeader.NumberOfSections; // 3. The traversing sections for ( int I = 0 ; I <the Count; ++ I) { // 4 determines whether or not present in the zone IF (RVA> = SectionTables [I] && .VirtualAddress RVA <(SectionTables [I] + .VirtualAddress SectionTables [I] .SizeOfRawData)) { // calculate the location and returns the value 5. After Found return RVA - SectionTables [I] + .VirtualAddress SectionTables [I] .PointerToRawData; } } // 6. not found return -1 return - . 1 ; } VOID OpenPeFile(LPCSTR FileName) { // Open the file HANDLE the Handle = CreateFileA (FileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // 2. Get File Size FileSize = GetFileSize (the Handle, NULL); // 3. The read file data DWORD OperSize = 0 ; FileBase = (DWORD)new BYTE[FileSize]; ReadFile(Handle, (LPVOID)FileBase, FileSize, &OperSize, NULL); // 4. Analyzing is not a valid PE file // 4.1 DOS header and determines acquisition is not a valid DOS file DosHeader = (PIMAGE_DOS_HEADER) FileBase; IF (! DosHeader-> e_magic = IMAGE_DOS_SIGNATURE) { MessageBox (NULL, " is not a valid DOS file " , " tips " , MB_OK); system("pause"); exit(0); } // 4.2 NT header and determines acquisition is not a valid PE file NtHeader = (PIMAGE_NT_HEADERS) (+ FileBase DosHeader-> e_lfanew which); IF (! NtHeader-> the Signature = named IMAGE_NT_SIGNATURE) { MessageBox (NULL, " not a valid PE file " , " tips " , MB_OK); system("pause"); exit(0); } // 4.3 Analyzing file is not a 32-bit IF (NtHeader-> OptionalHeader.Magic! = 0x010B ) { The MessageBox (NULL, " is not a valid 32-bit file " , " prompt " , MB_OK); system("pause"); exit(0); } CloseHandle(Handle); } // iterate relocation table VOID FixReloc () { DWORD base = NtHeader->OptionalHeader.ImageBase; // 1. Get the relocation table RVA DWORD RelocRVA = NtHeader-> OptionalHeader.DataDirectory [ . 5 ] .VirtualAddress; // 2. Get the relocation table Auto Reloc = (PIMAGE_BASE_RELOCATION) (+ FileBase RVAtoFOA (RelocRVA)); // 3. traversing relocation block relocation table, 0 to end the while (Reloc-> SizeOfBlock! = 0 ) { // 3.1 paging group address output the printf ( " PAGE_BASE:% 08X \ n- " , Reloc-> the VirtualAddress); // 3.2 relocation entries found Auto Offset = (TypeOffset *) (+ Reloc . 1 ); // number of 3.3 is calculated relocation entries // Reloc-> Saved SizeOfBlock relocation entire size of the block structure + relocation entry array // Reloc-> SizeOfBlock - the sizeof (IMAGE_BASE_RELOCATION) obtained array size // above results \ number, reason = 2 relocation entry is the size of the relocation entries is two bytes DWORD = size (Reloc-> SizeOfBlock - the sizeof (IMAGE_BASE_RELOCATION)) / 2 ; // 3.4 traverse all relocation entries for ( int I = 0 ; I <Size; ++ I) { // Get relocation type, only 3 of the type concerned DWORD the Type = Offset [I] .Type; // Get relocation offset DWORD pianyi = Offset [I] .offset; // Get RVA be relocated address is located: offset + VirtualAddress DWORD RVA = pianyi Reloc- +> the VirtualAddress; // Get be relocated address is located FOA DWORD FOA = RVAtoFOA (RVA); // Get be relocated address is located FA DWORD = FA + FOA FileBase; // Get address to be relocated DWORD * addr = (DWORD * ) FA; // Calculation data relocation: addr - oldbase + newbase DWORD to new_addr = addr - Base + 0x1500000 ; // The relocation data write back buffer (file) IF (Offset [I] .Type == . 3 ) * (DWORD *) FA = to new_addr; // printf("\tT(%d)%08X->%08X: %08X[%08X]\n", Type, rva, foa, addr, new_addr); } // find the next relocation block Reloc = (PIMAGE_BASE_RELOCATION) ((DWORD)Reloc + Reloc->SizeOfBlock); } NtHeader->OptionalHeader.ImageBase = 0x1500000; // Open the file HANDLE the Handle = CreateFileA ( " newfile.exe " , GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // 3. writing file data DWORD OperSize = 0 ; WriteFile(Handle, (LPVOID)FileBase, FileSize, &OperSize, NULL); CloseHandle(Handle); } VOID Import() { // 1. From the index data directory table to find an entry for the RVA DWORD RAV = NtHeader-> OptionalHeader.DataDirectory [ 1 ] .VirtualAddress; // 2. Locate the import table structure Auto ImportTable = (PIMAGE_IMPORT_DESCRIPTOR) (RVAtoFOA (RAV) + FileBase); // 3. traversing the import table array, the array to the end of the all-zero the while (ImportTable-> the Name) { // name corresponding to the output of the DLL 4 CHAR * DllName = (CHAR *) (RVAtoFOA (ImportTable-> the Name) + FileBase); printf("DLLName: %s\n", DllName); // 5. 找到 iat auto Iat = (PIMAGE_THUNK_DATA)(RVAtoFOA(ImportTable->FirstThunk) + FileBase); // 6. traversal iat, all 0s ends the while (Iat-> u1.Ordinal! = 0 ) { // 7. determine whether the name IF (Iat-> u1.AddressOfData & 0x80000000 ) { // number introduced directly outputs the printf ( " \ T [% HD]: None \ n- " , the LOWORD (Iat-> u1.AddressOfData)); } else { // find the name of the structure Auto the Name = (PIMAGE_IMPORT_BY_NAME) (RVAtoFOA (Iat-> u1.AddressOfData) + FileBase); printf("\t[%hd]: %s\n", Name->Hint, Name->Name); } ++ Here; } // points to the next structure ImportTable ++ ; } } VOID Export() { // 1. From the index data directory table entry is found 0 RVA DWORD RAV = NtHeader-> OptionalHeader.DataDirectory [ 0 ] .VirtualAddress; // 2. Locate the import table structure Auto ExportTable = (PIMAGE_EXPORT_DIRECTORY) (RVAtoFOA (RAV) + FileBase); // 3. Get function with the name and number of the total number DWORD NameCount = ExportTable-> NumberOfNames; DWORD FunctionCount = ExportTable->NumberOfFunctions; // 4. Get three tables, the table number is WORD DWORD * address = (DWORD *) (RVAtoFOA (ExportTable-> the AddressOfFunctions) + FileBase); DWORD* 名称表 = (DWORD*)(RVAtoFOA(ExportTable->AddressOfNames) + FileBase); WORD* 序号表 = (WORD*)(RVAtoFOA(ExportTable->AddressOfNameOrdinals) + FileBase); // 5. traverses the address table for ( int I = 0 ; I <FunctionCount; ++ I) { bool HaveName = FALSE; // 6 determines whether or not there is the name, it has a name, there will be the subscript number table for ( int J = 0 ; J <NameCount; ++ J) { // There name IF (I == number table [j]) { HaveName = TRUE; // corresponding to subject name table stored in the table is the name of the number CHAR * Name = (CHAR *) (RVAtoFOA ( table name [J]) + FileBase); the printf ( " [HD%]:% P% S \ n- " , I + ExportTable-> Base, address [I], the Name); BREAK ; } } // If you have not finished all looking for the name of IF (HaveName == FALSE) { the printf ( " [% HD]: None P% \ n- " , I + ExportTable-> Base, address [I]); } } } int main () { OpenPeFile("test.dll"); // FixReloc(); // Import(); // Export(); return 0; }