/// <summary> /// Retrieve PE header information from the module base pointer. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> /// <param name="pModule">Pointer to the module base.</param> /// <returns>PE.PE_META_DATA</returns> public static Data.PE.PE_META_DATA GetPeMetaData(IntPtr pModule) { var peMetaData = new Data.PE.PE_META_DATA(); try { var e_lfanew = (uint)Marshal.ReadInt32((IntPtr)((ulong)pModule + 0x3c)); peMetaData.Pe = (uint)Marshal.ReadInt32((IntPtr)((ulong)pModule + e_lfanew)); if (peMetaData.Pe != 0x4550) { throw new InvalidOperationException("Invalid PE signature."); } peMetaData.ImageFileHeader = (Data.PE.IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((ulong)pModule + e_lfanew + 0x4), typeof(Data.PE.IMAGE_FILE_HEADER)); var optHeader = (IntPtr)((ulong)pModule + e_lfanew + 0x18); var peArch = (ushort)Marshal.ReadInt16(optHeader); switch (peArch) { case 0x010b: peMetaData.Is32Bit = true; peMetaData.OptHeader32 = (Data.PE.IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(optHeader, typeof(Data.PE.IMAGE_OPTIONAL_HEADER32)); break; case 0x020b: peMetaData.Is32Bit = false; peMetaData.OptHeader64 = (Data.PE.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(optHeader, typeof(Data.PE.IMAGE_OPTIONAL_HEADER64)); break; default: throw new InvalidOperationException("Invalid magic value (PE32/PE32+)."); } var sectionArray = new Data.PE.IMAGE_SECTION_HEADER[peMetaData.ImageFileHeader.NumberOfSections]; for (var i = 0; i < peMetaData.ImageFileHeader.NumberOfSections; i++) { var sectionPtr = (IntPtr)((ulong)optHeader + peMetaData.ImageFileHeader.SizeOfOptionalHeader + (uint)(i * 0x28)); sectionArray[i] = (Data.PE.IMAGE_SECTION_HEADER)Marshal.PtrToStructure(sectionPtr, typeof(Data.PE.IMAGE_SECTION_HEADER)); } peMetaData.Sections = sectionArray; } catch { throw new InvalidOperationException("Invalid module base specified."); } return(peMetaData); }
/// <summary> /// Retrieve PE header information from the module base pointer. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> /// <param name="pModule">Pointer to the module base.</param> /// <returns>PE.PE_META_DATA</returns> public static Data.PE.PE_META_DATA GetPeMetaData(IntPtr pModule) { Data.PE.PE_META_DATA PeMetaData = new Data.PE.PE_META_DATA(); try { UInt32 e_lfanew = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + 0x3c)); PeMetaData.Pe = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + e_lfanew)); // Validate PE signature if (PeMetaData.Pe != 0x4550) { throw new InvalidOperationException("Invalid PE signature."); } PeMetaData.ImageFileHeader = (Data.PE.IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((UInt64)pModule + e_lfanew + 0x4), typeof(Data.PE.IMAGE_FILE_HEADER)); IntPtr OptHeader = (IntPtr)((UInt64)pModule + e_lfanew + 0x18); UInt16 PEArch = (UInt16)Marshal.ReadInt16(OptHeader); // Validate PE arch if (PEArch == 0x010b) // Image is x32 { PeMetaData.Is32Bit = true; PeMetaData.OptHeader32 = (Data.PE.IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(OptHeader, typeof(Data.PE.IMAGE_OPTIONAL_HEADER32)); } else if (PEArch == 0x020b) // Image is x64 { PeMetaData.Is32Bit = false; PeMetaData.OptHeader64 = (Data.PE.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(OptHeader, typeof(Data.PE.IMAGE_OPTIONAL_HEADER64)); } else { throw new InvalidOperationException("Invalid magic value (PE32/PE32+)."); } // Read sections Data.PE.IMAGE_SECTION_HEADER[] SectionArray = new Data.PE.IMAGE_SECTION_HEADER[PeMetaData.ImageFileHeader.NumberOfSections]; for (int i = 0; i < PeMetaData.ImageFileHeader.NumberOfSections; i++) { IntPtr SectionPtr = (IntPtr)((UInt64)OptHeader + PeMetaData.ImageFileHeader.SizeOfOptionalHeader + (UInt32)(i * 0x28)); SectionArray[i] = (Data.PE.IMAGE_SECTION_HEADER)Marshal.PtrToStructure(SectionPtr, typeof(Data.PE.IMAGE_SECTION_HEADER)); } PeMetaData.Sections = SectionArray; } catch { throw new InvalidOperationException("Invalid module base specified."); } return(PeMetaData); }