public static unsafe string GetPeArchitecture(byte[] fileBytes) { // GetPeArchitecture takes the file and checks the Machine Type to // make sure the file is either x86 or x64, which are the only 2 // file architectures we can deal with fixed(byte *ptr_data = fileBytes) { // Get the DOS header IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)ptr_data; // Get the NT header using e_lfanew IMAGE_NT_HEADERS64 *nt_header = (IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew); // Get the image architecture. We only want x86 and x64. if (nt_header->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { return("x64"); } else if (nt_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { return("x86"); } else { return(null); } } }
void CalcHeaders() { _dosHeader = (IMAGE_DOS_HEADER *)_address; _ntHeaders32 = (IMAGE_NT_HEADERS32 *)(_address + _dosHeader->e_lfanew); _ntHeaders64 = (IMAGE_NT_HEADERS64 *)(_address + _dosHeader->e_lfanew); _isPE64 = _ntHeaders32->OptionalHeader.Magic == (ushort)OptionalHeaderMagic.PE32Plus; _fileHeader = _isPE64 ? &_ntHeaders64->FileHeader : &_ntHeaders32->FileHeader; _header32 = &_ntHeaders32->OptionalHeader; _header64 = &_ntHeaders64->OptionalHeader; _sections = new IMAGE_SECTION_HEADER[_fileHeader->NumberOfSections]; var offset = _isPE64 ? sizeof(IMAGE_NT_HEADERS64) : sizeof(IMAGE_NT_HEADERS32); fixed(void *sections = _sections) { Buffer.MemoryCopy((byte *)_ntHeaders32 + offset, sections, _sections.Length * sizeof(IMAGE_SECTION_HEADER), _sections.Length * sizeof(IMAGE_SECTION_HEADER)); } FileHeader = new FileHeader(_fileHeader); if (IsPE64) { OptionalHeader = new OptionalHeader(_header64); } else { OptionalHeader = new OptionalHeader(_header32); } _workBuffer = Marshal.AllocCoTaskMem(1 << 12); }
public static IMAGE_SECTION_HEADER *IMAGE_FIRST_SECTION(byte *ptr_image_nt_headers) { if (Environment.Is64BitProcess) { IMAGE_NT_HEADERS64 *image_nt_headers = (IMAGE_NT_HEADERS64 *)ptr_image_nt_headers; return((IMAGE_SECTION_HEADER *)((long)image_nt_headers + (long)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS64), "OptionalHeader") + image_nt_headers->FileHeader.SizeOfOptionalHeader)); } else { IMAGE_NT_HEADERS32 *image_nt_headers = (IMAGE_NT_HEADERS32 *)ptr_image_nt_headers; return((IMAGE_SECTION_HEADER *)((long)image_nt_headers + (long)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS32), "OptionalHeader") + image_nt_headers->FileHeader.SizeOfOptionalHeader)); } }
private static uint GetEffectiveSectionSize64(IMAGE_NT_HEADERS64 *ntHeaders64, IMAGE_SECTION_HEADER *section) { if (section->SizeOfRawData != 0) { return(section->SizeOfRawData); } if ((section->Characteristics & DataSectionFlags.ContentInitializedData) != 0) { return(ntHeaders64->OptionalHeader.SizeOfInitializedData); } if ((section->Characteristics & DataSectionFlags.ContentUninitializedData) != 0) { return(ntHeaders64->OptionalHeader.SizeOfUninitializedData); } return(0); }
public static unsafe Offset RvaToOffset(IMAGE_NT_HEADERS64 *nt64, IMAGE_NT_HEADERS32 *nt32, uint rva, string friendlyName) { Offset offsets = new Offset(); if (nt64 != null) // x64 { IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION((byte *)nt64); for (int i = 1; i < nt64->FileHeader.NumberOfSections + 1; i++) { if (rva >= section->VirtualAddress && rva < section->VirtualAddress + section->SizeOfRawData) { offsets.RVA = section->VirtualAddress; offsets.RawOffset = section->PointerToRawData; } section = (IMAGE_SECTION_HEADER *)((long)section + (long)Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER))); } uint offset = offsets.RawOffset + (rva - offsets.RVA); return(offsets); } else if (nt32 != null) // x86 { IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION((byte *)nt32); for (int i = 1; i < nt32->FileHeader.NumberOfSections + 1; i++) { if (rva >= section->VirtualAddress && rva < section->VirtualAddress + section->SizeOfRawData) { offsets.RVA = section->VirtualAddress; offsets.RawOffset = section->PointerToRawData; } section = (IMAGE_SECTION_HEADER *)((long)section + (long)Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER))); } uint offset = offsets.RawOffset + (rva - offsets.RVA); return(offsets); } else { return(offsets); } }
private static IMAGE_SECTION_HEADER* IMAGE_FIRST_SECTION64(IMAGE_NT_HEADERS64* ntheader) { return (IMAGE_SECTION_HEADER*)((ulong)ntheader + 24 + ntheader->FileHeader.SizeOfOptionalHeader); }
public static void *ImageRvaToVa64([NativeTypeName("PIMAGE_NT_HEADERS")] IMAGE_NT_HEADERS64 *NtHeaders, [NativeTypeName("PVOID")] void *Base, [NativeTypeName("ULONG")] uint Rva, [NativeTypeName("PIMAGE_SECTION_HEADER *")] IMAGE_SECTION_HEADER **LastRvaSection) { return(ImageRvaToVa(NtHeaders, Base, Rva, LastRvaSection)); }
public static IMAGE_SECTION_HEADER *ImageRvaToSection64([NativeTypeName("PIMAGE_NT_HEADERS")] IMAGE_NT_HEADERS64 *NtHeaders, [NativeTypeName("PVOID")] void *Base, [NativeTypeName("ULONG")] uint Rva) { return(ImageRvaToSection(NtHeaders, Base, Rva)); }
/// <summary> /// Simple PE Parser, That Extracts The PDB Location From a PE File, which also checks for PE File Validity. /// </summary> /// <param name="path"></param> public PEFile(string path) { if (String.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } FileInfo peContainer = new FileInfo(path); if (!peContainer.Exists) { throw new FileNotFoundException(path); } m_fileInfo = peContainer; try { m_fileVersionInfo = FileVersionInfo.GetVersionInfo(path); } catch (Exception exc) { Debug.WriteLine(exc.ToString()); m_fileVersionInfo = null; } using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs)) { // Find the address of the PE Header try { br.BaseStream.Seek(PESignatureOffsetLoc, SeekOrigin.Begin); // BugFix For Bug Number 677 // After the MS DOS stub, at the file offset specified at offset 0x3c, // We must read 4 bytes to located the position of the PE Header In The Executable File // is a 4-byte signature that identifies the file as a PE format image file. // This signature is “PE\0\0” (the letters “P” and “E” followed by two null bytes). // m_PESignatureOffset = br.ReadByte(); // Thx to Microsofts mdb source code in pdb2xml this was wrongly implemented. // Should i trust their code :) // Better Writing The Code Like In Pdb Extractor myself seems to be the right way :) m_PESignatureOffset = br.ReadUInt32(); br.BaseStream.Seek(m_PESignatureOffset, SeekOrigin.Begin); // The PE Signature like defined // in Microsoft Portable Executable and Common Object File Format Specification v8.0 if (br.ReadByte() != 'P') { throw new FileLoadException("PE Signature corrupt"); } if (br.ReadByte() != 'E') { throw new FileLoadException("PE Signature corrupt"); } if (br.ReadByte() != '\0') { throw new FileLoadException("PE Signature corrupt"); } if (br.ReadByte() != '\0') { throw new FileLoadException("PE Signature corrupt"); } } catch (EndOfStreamException) { throw new FileLoadException("Read past end of file"); } } } m_ExePath = path; byte[] Data = System.IO.File.ReadAllBytes(path); //This section is unsafe so faster access is achieved :) unsafe { //First Check The Length If it is lesser then dos header + image headers if (peContainer.Length < (sizeof(IMAGE_DOS_HEADER)) + sizeof(IMAGE_NT_HEADERS32)) throw new FileLoadException("Invalid PE File"); fixed(byte *p_Data = Data) { // Get the first 64 bytes and turn it into a IMAGE_DOS_HEADER IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)p_Data; //Read Image Nt Headers IMAGE_NT_HEADERS64 *inhs64 = (IMAGE_NT_HEADERS64 *)(idh->lfanew + p_Data); //Check The PE00 signature if (inhs64->Signature != PEMAGIC) { throw new FileLoadException("PE Signature corrupt"); } // The calculated values that are different depending on // 32 vs. 64-bit. int SizeOfOptionalHeader = 0; uint rva = 0; uint DebugDirSize = 0; ushort NumberOfSections = 0; if (inhs64->OptionalHeader.Magic == PE32) { // Get all the 32-bit offsets. IMAGE_NT_HEADERS32 *inhs32 = (IMAGE_NT_HEADERS32 *)(idh->lfanew + p_Data); SizeOfOptionalHeader = (int) inhs32->FileHeader.SizeOfOptionalHeader; //Debug Section Is Always In 7th Member Of The Optional Headers Data Directory rva = inhs32->OptionalHeader.DataDirectory7.VirtualAddress; DebugDirSize = inhs32->OptionalHeader.DataDirectory7.Size; NumberOfSections = inhs32->FileHeader.NumberOfSections; } else if (inhs64->OptionalHeader.Magic == PE32PLUS) { SizeOfOptionalHeader = (int) inhs64->FileHeader.SizeOfOptionalHeader; //Debug Section Is Always In 7th Member Of The Optional Headers Data Directory rva = inhs64->OptionalHeader.DataDirectory7.VirtualAddress; DebugDirSize = inhs64->OptionalHeader.DataDirectory7.Size; NumberOfSections = inhs64->FileHeader.NumberOfSections; } //No Debug Section Found So Exit. if ((rva == 0) || (DebugDirSize == 0)) { throw new NoDebugSectionException( ); } //Find out the data section Int32 dataSectionsOffset = (idh->lfanew) + 4 + sizeof(IMAGE_FILE_HEADER) + (int)SizeOfOptionalHeader; bool found = false; //Loop through the debug sections, enumerate whole sections try to locate the type 2(CODEVIEW) section //with magical header 0x53445352 For PDB 7.0 Entries , my code won't support PDB V2.0 Entries , because none //of the .Net Assemblies Use It. for (int i = 0; i < NumberOfSections; i++) { PESectionHeader *myHeader = (PESectionHeader *)(dataSectionsOffset + p_Data); uint sectionSize = myHeader->VirtualSize; if (sectionSize == 0) { sectionSize = myHeader->RawDataSize; } if ((rva >= myHeader->VirtualAddress) && (rva < myHeader->VirtualAddress + sectionSize)) { found = true; } if (found) { found = false; int diff = (int)(myHeader->VirtualAddress - myHeader->RawDataAddress); UInt32 fileOffset = rva - (uint)diff; _IMAGE_DEBUG_DIRECTORY *debugDirectory = (_IMAGE_DEBUG_DIRECTORY *)(fileOffset + p_Data); int NumEntries = (int)(DebugDirSize / sizeof(_IMAGE_DEBUG_DIRECTORY)); for (int ix = 1; ix <= NumEntries; ix++, debugDirectory++) { if (debugDirectory->Type == 2) { UInt32 cvSignature = *(UInt32 *)(p_Data + debugDirectory->PointerToRawData); if (cvSignature == 0x53445352) { CV_INFO_PDB70 *pCvInfo = (CV_INFO_PDB70 *)(p_Data + debugDirectory->PointerToRawData); string hexAge = pCvInfo->Age.ToString("x2"); if (hexAge != "0") { hexAge = (hexAge.StartsWith("0") ? hexAge.Substring(1) : hexAge); } else { hexAge = "0"; } m_pdbAge = pCvInfo->Age.ToString(); string finalHex = String.Empty; byte[] firstHeader = BitConverter.GetBytes(pCvInfo->firstPart); byte[] secondHeader = BitConverter.GetBytes(pCvInfo->secondPart); byte[] thirdHeader = BitConverter.GetBytes(pCvInfo->thirdPart); byte[] fourthHeader = BitConverter.GetBytes(pCvInfo->fourthPart); byte[] finalGuid = new byte[16]; //Make The Byte Order Correct So We Can Construct The Right Guid Out Of It //Guid Buildup Begin finalGuid[0] = firstHeader[3]; finalGuid[1] = firstHeader[2]; finalGuid[2] = firstHeader[1]; finalGuid[3] = firstHeader[0]; //c section finalGuid[4] = secondHeader[5 - 4]; finalGuid[5] = secondHeader[4 - 4]; //d relocation finalGuid[6] = secondHeader[7 - 4]; finalGuid[7] = secondHeader[6 - 4]; for (int xx = 8; xx < 12; xx++) { finalGuid[xx] = thirdHeader[xx - 8]; } for (int x = 12; x < 16; x++) { finalGuid[x] = fourthHeader[x - 12]; } //Guid Buildup End //Get The Original Guid m_pdbGuid = new Guid(finalGuid); finalHex = Utility.ByteArrayToHex(finalGuid); m_pdbVersion = finalHex.ToUpperInvariant() + hexAge.ToUpperInvariant(); //Locate The Pdb Name Entry, it is a null terminated string. uint stringBeginLocation = debugDirectory->PointerToRawData + 24; byte stringLocator = *(p_Data + stringBeginLocation); System.Text.StringBuilder resultBuilder = new System.Text.StringBuilder(); MemoryStream stringHolder = new MemoryStream(); while (stringLocator != 0) { stringHolder.WriteByte(stringLocator); //resultBuilder.Append(Encoding.ASCII.GetString(new byte[]{stringLocator})); stringBeginLocation++; stringLocator = *(p_Data + stringBeginLocation); } ; // Buildup The String And Return It. // We assume always that it is ascii encoded. m_pdbFullName = Encoding.ASCII.GetString(stringHolder.ToArray()); //resultBuilder.ToString(); return; } } } } dataSectionsOffset += sizeof(PESectionHeader); } throw new NoPdbSectionException(); } } }
public static unsafe List <string> GetDynamicImports(byte[] fileBytes, string arch) { // This function walks the PE header to get the offset of the Delay-Load Descriptor Table // (DLDT) and then resolves the imports' names List <string> dynamicModuleNames = new List <string>(); fixed(byte *ptr_data = fileBytes) { // Initial validation UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data; if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE) { Console.WriteLine("[-] Magic bytes don't match"); return(dynamicModuleNames); } // Get the NT headers if (arch == "x64") { IMAGE_NT_HEADERS64 *nt_header = (IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(dynamicModuleNames); } // Get the offset for the delay-load import tables ulong *DataDirectory = nt_header->OptionalHeader.DataDirectory; IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); uint dldtRVA = dldt->VirtualAddress; if (dldtRVA == 0) // No delayed imports found { return(dynamicModuleNames); } Offset offsets = RvaToOffset(nt_header, null, dldtRVA, "DLDT"); uint offset = offsets.RawOffset + (dldtRVA - offsets.RVA); // Iterate over the list of delay-loaded modules IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset); while (firstModule->szName != 0) { Offset offsetToNames = RvaToOffset(nt_header, null, firstModule->szName, "szName"); uint offset2 = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA); dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2))); firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR))); } } else // x86 { IMAGE_NT_HEADERS32 *nt_header = (IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(dynamicModuleNames); } // Get the offset for the delay-load import tables ulong *DataDirectory = nt_header->OptionalHeader.DataDirectory; IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); uint dldtRVA = dldt->VirtualAddress; if (dldtRVA == 0) // No delayed imports found { return(dynamicModuleNames); } Offset offsets = RvaToOffset(null, nt_header, dldtRVA, "DLDT"); uint offset = offsets.RawOffset + (dldtRVA - offsets.RVA); // Iterate over the list of delay-loaded modules IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset); while (firstModule->szName != 0) { Offset offsetToNames = RvaToOffset(null, nt_header, firstModule->szName, "szName"); uint offset2 = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA); dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2))); firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR))); } } return(dynamicModuleNames); } }
private unsafe void PopulateHeaderStructs(FileStream fin) { byte[] Data = new byte[4096]; int iRead = fin.Read(Data, 0, 4096); fin.Flush(); fin.Close(); fixed(byte *p_Data = Data) { IMAGE_DOS_HEADER * idh = (IMAGE_DOS_HEADER *)p_Data; IMAGE_NT_HEADERS32 *inhs = (IMAGE_NT_HEADERS32 *)(idh->nt_head_ptr + p_Data); ModuleMachineType = (MachineType)inhs->FileHeader.Machine; if (ModuleMachineType == MachineType.I386) { IMAGE_NT_HEADERS32 *inhs32 = (IMAGE_NT_HEADERS32 *)(idh->nt_head_ptr + p_Data); ImageFileHeader = inhs32->FileHeader; ModuleMachineType = (MachineType)inhs32->FileHeader.Machine; ImageOptionalHeader32 = inhs32->OptionalHeader; ModuleImageBase = (IntPtr)inhs32->OptionalHeader.ImageBase; ImageNTHeaders32 = new IMAGE_NT_HEADERS32 { Signature = inhs32->Signature, FileHeader = inhs32->FileHeader, OptionalHeader = inhs32->OptionalHeader }; byte[] bytes = new byte[256]; var ret = ErcCore.ReadProcessMemory(ModuleProcess.Handle, (IntPtr)((uint)ModuleBase + ImageOptionalHeader32.LoadConfigTable.VirtualAddress), bytes, 256, out int BytesRead); if (BitConverter.ToUInt32(bytes, 58) > 0 || BitConverter.ToUInt32(bytes, 62) > 0) { ModuleSafeSEH = true; } } else if (ModuleMachineType == MachineType.x64) { IMAGE_NT_HEADERS64 *inhs64 = (IMAGE_NT_HEADERS64 *)(idh->nt_head_ptr + p_Data); ImageFileHeader = inhs64->FileHeader; ImageOptionalHeader64 = inhs64->OptionalHeader; ModuleImageBase = (IntPtr)inhs64->OptionalHeader.ImageBase; ImageNTHeaders64 = new IMAGE_NT_HEADERS64 { Signature = inhs64->Signature, FileHeader = inhs64->FileHeader, OptionalHeader = inhs64->OptionalHeader }; byte[] bytes = new byte[256]; var ret = ErcCore.ReadProcessMemory(ModuleProcess.Handle, (IntPtr)((long)ModuleBase + (long)ImageOptionalHeader64.LoadConfigTable.VirtualAddress), bytes, 256, out int BytesRead); if (BitConverter.ToUInt64(bytes, 88) > 0 || BitConverter.ToUInt64(bytes, 96) > 0) { ModuleSafeSEH = true; } } else { ModuleFailed = true; } } }
public PEFile(FileStream Fin, int BufferLength) { this.fin = Fin; this.BufferLength = BufferLength; this.bData = ReadFile(fin, BufferLength); bool b64 = false; unsafe { fixed(byte *pData = this.bData) { IMAGE_DOS_HEADER * pIdh = (IMAGE_DOS_HEADER *)pData; IMAGE_NT_HEADERS32 *pInhs32 = (IMAGE_NT_HEADERS32 *)(pIdh->e_lfanew + pData); IMAGE_NT_HEADERS64 *pInhs64 = (IMAGE_NT_HEADERS64 *)(pIdh->e_lfanew + pData); if (pInhs32->FileHeader.SizeOfOptionalHeader > 0) // check for non object file { if (pInhs32->OptionalHeader.Magic == 0x10b) { // 32 Bit } if (pInhs32->OptionalHeader.Magic == 0x20b) { // 64 Bit b64 = true; } if (pInhs32->OptionalHeader.CLRDataDirectory.Size > 0) { m_IsManaged = true; } else { m_IsManaged = false; } if ((this.bData.Length < 9192) && (pInhs32->OptionalHeader.BaseOfCode > 2048)) { iEntryPoint = 2048; } else { if (b64) { iEntryPoint = pInhs64->OptionalHeader.BaseOfCode; } else { iEntryPoint = pInhs32->OptionalHeader.BaseOfCode; } } m_BinImprint = viGetFullImprint_ByteArray(bData, iEntryPoint); iNTHeaderOffset = pIdh->e_lfanew; iOptionalHeaderOffset = iNTHeaderOffset + 4 + (int)sizeof(IMAGE_FILE_HEADER); iSectionOffset = iOptionalHeaderOffset + (int)pInhs32->FileHeader.SizeOfOptionalHeader; iOffset = iSectionOffset + (int)pData; for (int i = 0; i < pInhs32->FileHeader.NumberOfSections; i++) { IMAGE_SECTION_HEADER *pIsh = (IMAGE_SECTION_HEADER *)(iOffset + (int)(sizeof(IMAGE_SECTION_HEADER) * i)); iBaseRVA = pIsh->PointerToRawData + (uint)pData; if (MakeStringFromUTF8((byte *)&pIsh->Name) == ".rsrc") { if (pIsh->VirtualSize > 0) { iImageSectionHeaderSize = pIsh->VirtualSize; } else { iImageSectionHeaderSize = pIsh->SizeOfRawData; } if (b64) { if (pInhs64->OptionalHeader.ResourceDataDirectory.VirtualAddress >= pIsh->VirtualAddress && pInhs64->OptionalHeader.ResourceDataDirectory.VirtualAddress < pIsh->VirtualAddress + iImageSectionHeaderSize) { IMAGE_RESOURCE_DIRECTORY * pIrd = (IMAGE_RESOURCE_DIRECTORY *)(pIsh->PointerToRawData + (uint)pData); IMAGE_RESOURCE_DIRECTORY_ENTRY *pIrde = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(pIrd + 1); nEntries = (UInt16)(pIrd->NumberOfIdEntries + pIrd->NumberOfNamedEntries); for (int j = 0; j < nEntries; j++) { if (!processImageResourceDirectory(pIrd, pIrde, iBaseRVA, pIsh, pData)) { throw new Exception("Error during resource directory parsing."); } pIrde++; } } } else { if (pInhs32->OptionalHeader.ResourceDataDirectory.VirtualAddress >= pIsh->VirtualAddress && pInhs32->OptionalHeader.ResourceDataDirectory.VirtualAddress < pIsh->VirtualAddress + iImageSectionHeaderSize) { IMAGE_RESOURCE_DIRECTORY * pIrd = (IMAGE_RESOURCE_DIRECTORY *)(pIsh->PointerToRawData + (uint)pData); IMAGE_RESOURCE_DIRECTORY_ENTRY *pIrde = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(pIrd + 1); nEntries = (UInt16)(pIrd->NumberOfIdEntries + pIrd->NumberOfNamedEntries); for (int j = 0; j < nEntries; j++) { if (!processImageResourceDirectory(pIrd, pIrde, iBaseRVA, pIsh, pData)) { throw new Exception("Error during resource directory parsing."); } pIrde++; } } } } if (iOffset >= iOptionalHeaderOffset + (int)sizeof(IMAGE_OPTIONAL_HEADER32) + 8 * 16 + (int)pData) // just for savety reasons { break; } } } } } }