public ImportExportTableReader(NTHeader header) { this.header = header; image = header.assembly.peImage; LoadExports(); LoadImports(); }
internal NETHeaderReader(NTHeader header, NETHeader parent) { this.parent = parent; header._assembly._netHeader = parent; image = header._assembly._peImage; this.ntHeader = header; }
internal ResourcesReader(NTHeader header) { this.header = header; image = header.assembly.peImage; resourceDirectory = header.OptionalHeader.DataDirectories[(int)DataDirectoryName.Resource]; ReadRootDirectory(); }
internal static PEPair GetPEHeaders(String fileName) { Byte[] fileData = new Byte[0x400]; // need only the first 0x400 bytes using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (fs.Read(fileData, 0, 0x400) != 0x400) { return(null); } } //////////////////////////// IntPtr p = Marshal.AllocHGlobal(0x400); Marshal.Copy(fileData, 0, p, 0x400); DosHeader dos = (DosHeader)Marshal.PtrToStructure(p, typeof(DosHeader)); IntPtr ntp = new IntPtr(p.ToInt64() + dos.e_lfanew); NTHeader nt = (NTHeader)Marshal.PtrToStructure(ntp, typeof(NTHeader)); Marshal.FreeHGlobal(p); PEPair ret = new PEPair(dos, nt); return(ret); }
internal static MachineType GetMachineType(String fileName) { PEPair headers = GetPEHeaders(fileName); if (headers == null) { return(MachineType.Unknown); } DosHeader dos = headers.X; NTHeader nt = headers.Y; if (dos.e_magic != DosHeader.DosMagic) { return(MachineType.Unknown); } if (nt.Signature != NTHeader.NTSignature) { return(MachineType.Unknown); } MachineType type = nt.FileHeader.Machine; return(type); }
// This method writes out a PE file. internal static void PersistPEFile(ref BinaryWriter writer, ref byte[] buf) { uint i, chunkSize, fileOffset; MemoryStream memStream = new MemoryStream(buf); BinaryReader memReader = new BinaryReader(memStream); // Crack the headers. AllHeaders all = new AllHeaders(ref memReader); NTHeader nth = all.m_ntHeader; SectionHeader[] sh = all.m_sectionHeaders; // Write the headers to the file. writer.Write(buf, 0, (int)nth.m_HeaderSize); // Write each section to the file. for (i = 0; i < nth.m_NumberOfSections; i++) { fileOffset = sh[i].m_PointerToRawData; if (fileOffset != 0) { chunkSize = Roundup(sh[i].m_SizeOfRawData, nth.m_FileAlignment); writer.BaseStream.Seek(fileOffset, SeekOrigin.Begin); writer.Write(buf, (int)sh[i].m_VirtualAddress, (int)chunkSize); } } writer.Flush(); }
internal ResourcesReader(NTHeader header) { this.header = header; this.image = header._assembly._peImage; resourceDirectory = header.OptionalHeader.DataDirectories[(int)DataDirectoryName.Resource]; if (header._assembly._peImage.TrySetOffset(resourceDirectory.TargetOffset.FileOffset)) { stream = header._assembly._peImage.ReadStream((int)resourceDirectory.Size); reader = new BinaryReader(stream); ReadRootDirectory(); } }
internal AllHeaders(ref BinaryReader reader) { m_dosHeader = new DosHeader(ref reader); reader.BaseStream.Seek(m_dosHeader.m_e_lfanew, SeekOrigin.Begin); m_ntHeader = new NTHeader(ref reader); // "NumberOfSections" comes from the COFF header. if (m_ntHeader.m_NumberOfSections != 0) { m_sectionHeaders = new SectionHeader[m_ntHeader.m_NumberOfSections]; for (int i = 0; i < m_ntHeader.m_NumberOfSections; i++) { m_sectionHeaders[i] = new SectionHeader(ref reader); } } }
// This method reads a PE file, and then returns a byte array representation of the file. internal static byte[] ParsePEFile(ref BinaryReader reader) { uint i, fileOffset; byte[] buf; AllHeaders all = new AllHeaders(ref reader); NTHeader nth = all.m_ntHeader; SectionHeader[] sh = all.m_sectionHeaders; // "ImageSize" and "FileAlignment" come from Optional header - NT-specific fields. buf = new byte[nth.m_ImageSize]; #if DEBUG0 Console.WriteLine("size of image: " + nth.m_ImageSize + Environment.NewLine); #endif // Ok. Got all the info. Ready to read in the sections. Debug.Assert(nth.m_FileAlignment >= 512); reader.BaseStream.Seek(0, SeekOrigin.Begin); reader.Read(buf, 0, (int)nth.m_HeaderSize); // Read first "nth.m_HeaderSize" bytes. These are the headers. // Read each section from the file. for (i = 0; i < nth.m_NumberOfSections; i++) { fileOffset = sh[i].m_PointerToRawData; if (fileOffset != 0) { reader.BaseStream.Seek(fileOffset, SeekOrigin.Begin); reader.Read(buf, (int)sh[i].m_VirtualAddress, (int)sh[i].m_SizeOfRawData); #if DEBUG0 Console.Write("name of section " + i + ": "); for (int j = 0; j < 8; j++) { Console.Write((char)sh[i].m_Name[j]); } Console.WriteLine(); Console.WriteLine("size of section " + i + ": " + sh[i].m_SizeOfRawData + Environment.NewLine); #endif } } return(buf); }
/// <summary>When a PE is modified, even by Win32's resource functions, the checksum value in the PE header remains unchanged. This method corrects the checksum header value.</summary> public static void CorrectPEChecksum(String fileName) { // This method seems to cause some problems with file handles being invalid // when I disabled this method errors stopped being reported // but I've since changed the exception behaviour (it wasn't checking the return value of the CloseHandle functions in the }finally{} block) so I'll need to test this out // Get handle to a file with read/write access // CreateFileMapping // MapViewOfFile // Check DOS/NT Headers (optional, not needed in this case since if it's gotten this far it's going to be a Win32 PE) // CheckSumMappedFile // Close the handles Sfh sfh = null; IntPtr hMap = IntPtr.Zero; IntPtr pData = IntPtr.Zero; try { sfh = NativeMethods.CreateFile(fileName, FileAccess.ReadWrite, FileShare.None, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); if (sfh.IsInvalid) { throw new AnolisException("Invalid SafeFileHandle: " + NativeMethods.GetLastErrorString()); } hMap = NativeMethods.CreateFileMapping(sfh, IntPtr.Zero, FileMapProtection.PageReadWrite, 0, 0, null); if (hMap == IntPtr.Zero) { throw new AnolisException("Invalid File Mapping: " + NativeMethods.GetLastErrorString()); } pData = NativeMethods.MapViewOfFile(hMap, FileMapAccess.FileMapWrite, 0, 0, IntPtr.Zero); if (pData == IntPtr.Zero) { throw new AnolisException("Invalid Map View of File: " + NativeMethods.GetLastErrorString()); } // checking the PE headers for validity isn't required in this scenario UInt32 oldChecksum = 0; UInt32 newChecksum = 0; UInt32 size = NativeMethods.GetFileSize(sfh, IntPtr.Zero); // Get the NTHeader IntPtr pNTHeader = NativeMethods.CheckSumMappedFile(pData, size, ref oldChecksum, ref newChecksum); if (pNTHeader == IntPtr.Zero) { throw new AnolisException("CheckSumMappedFile Failed: " + NativeMethods.GetLastErrorString()); } NTHeader ntHeader = (NTHeader)Marshal.PtrToStructure(pNTHeader, typeof(NTHeader)); // Set the CheckSum, but as this is a new allocation by Marshal it needs to be copied back to the mapped memory ntHeader.OptionalHeader.CheckSum = newChecksum; // this overwrites the old NTHeader @ pNTHeader Marshal.StructureToPtr(ntHeader, pNTHeader, false); } finally { String errors = String.Empty; if (pData != IntPtr.Zero) { if (!NativeMethods.UnmapViewOfFile(pData)) { errors += "UnmapViewOfFile failed: " + NativeMethods.GetLastErrorString() + "\r\n"; } } if (hMap != IntPtr.Zero) { if (!NativeMethods.CloseHandle(hMap)) { errors += "CloseHandle(hMap) failed: " + NativeMethods.GetLastErrorString() + "\r\n"; } } if (sfh != null && !sfh.IsInvalid) { if (!NativeMethods.CloseHandle(sfh)) { errors += "CloseHandle(sfh) failed: " + NativeMethods.GetLastErrorString() + "\r\n"; } } } }
internal NETHeaderReader(NTHeader header, NETHeader parent) { header.assembly.netHeader = parent; image = header.assembly.peImage; this.ntHeader = header; }
internal MetaDataRoot m_mdr; // MetaData Root table /********************************************************************************************************************* * 1) Parse the MetaData Root table. * * 2) Initialize the various heaps. * * 3) Initialize "m_oldNameHash", "m_classTree", and "m_freeSpaceList". * * 4) Initialize the various BitArrays. * * 5) Set the total numbers of the elements (types, methods, fields, properties, events, and parameters). *********************************************************************************************************************/ internal MetaData(ref byte[] buf) { int i, ptHeapIndex = -1; Exception toBeThrown; m_buffer = buf; // Ok. Now we can build a reader and a writer over the memory m_buffer. MemoryStream memStream = new MemoryStream(m_buffer); BinaryReader reader = new BinaryReader(memStream); BinaryWriter writer = new BinaryWriter(memStream); AllHeaders all = new AllHeaders(ref reader); NTHeader nth = all.m_ntHeader; SectionHeader[] sh = all.m_sectionHeaders; #if DEBUG0 Console.WriteLine("Runtime Header Data Directory"); Console.WriteLine("rva: " + nth.m_DataDirectory[14].RVA + "; size: " + nth.m_DataDirectory[14].Size + Environment.NewLine); Console.WriteLine("offset to MetaData section: " + (long)(nth.m_DataDirectory[14].RVA + 8)); #endif // Read the RVA of the physical MetaData section from the Runtime Header Data Directory. reader.BaseStream.Seek((long)(nth.m_DataDirectory[14].RVA + 8), SeekOrigin.Begin); m_startPos = reader.ReadUInt64(); // Theoretically, startPos can be 64 bit long, but in practice, 32 bits are enough. // TODO : Check the docs. The following assertion will fail. // Debug.Assert((startPos >> 32) == 0); m_startPos = m_startPos & 0xffffffff; // use the least significant 4 bytes as the offset m_mdr = new MetaDataRoot(ref reader, ref m_buffer, m_startPos); // We need to initialize the #Strings heap and the #Blob heap before dealing with the #~ heap. for (i = 0; i < m_mdr.m_numStreams; i++) { if (m_mdr.m_streamHeaders[i].name.Equals("#Strings\0")) { m_strHeap = new StringHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size); } else if (m_mdr.m_streamHeaders[i].name.Equals("#Blob\0")) { m_blobHeap = new BlobHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size); } else if (m_mdr.m_streamHeaders[i].name.Equals("#~\0") || m_mdr.m_streamHeaders[i].name.Equals("#-\0")) { ptHeapIndex = i; } } if (ptHeapIndex != -1) { m_heap = new PTHeap(ref reader, ref writer, ref m_strHeap, m_startPos + m_mdr.m_streamHeaders[ptHeapIndex].offset); } else { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } }