public static void Main() { if (!Native.GetModuleHandleEx(ModuleHandleFlags.UnchangedRefCount, "Inkjet.dll", out ThisModule)) { ThisModule = IntPtr.Zero; } IntPtr ExeHandle; List <string> ExportNames = new List <string>(); if (Native.GetModuleHandleEx(ModuleHandleFlags.UnchangedRefCount, null, out ExeHandle)) { IMAGE_DOS_HEADER * DosHeader = (IMAGE_DOS_HEADER *)ExeHandle; IMAGE_NT_HEADERS * Header = (IMAGE_NT_HEADERS *)(ExeHandle + (int)DosHeader->LFaNew); IMAGE_EXPORT_DIRECTORY *Exports = (IMAGE_EXPORT_DIRECTORY *)(ExeHandle + Header->OptionalHeader.ExportTable.VirtualAddress); IntPtr Names = ExeHandle + Exports->AddressOfNames; for (int i = 0; i < Exports->NumberOfNames; i++) { string Name = Marshal.PtrToStringAnsi(ExeHandle + ((int *)Names)[i]); if (Name.Trim().Length == 0) { continue; } ExportNames.Add(Name); } } File.WriteAllText("E:\\Projects\\Hackery\\bin\\HAAX.txt", string.Join("\n", ExportNames)); Process Cur = Process.GetCurrentProcess(); MessageBox.Show("Magic!", string.Format("{0} ({1})", Cur.ProcessName, Cur.Id)); }
/// <summary> /// Parses the given buffer for the header of a PEFile. If it can be parsed correctly, /// a new PEHeader object is constructed from the buffer and returned. Otherwise, null /// is returned. /// </summary> internal static PEHeader FromBuffer(PEBuffer buffer, bool virt) { byte * ptr = buffer.Fetch(0, 0x300); IMAGE_DOS_HEADER *tmpDos = (IMAGE_DOS_HEADER *)ptr; int needed = tmpDos->e_lfanew + sizeof(IMAGE_NT_HEADERS); if (buffer.Length < needed) { ptr = buffer.Fetch(0, needed); if (buffer.Length < needed) { return(null); } tmpDos = (IMAGE_DOS_HEADER *)ptr; } IMAGE_NT_HEADERS *tmpNt = (IMAGE_NT_HEADERS *)((byte *)tmpDos + tmpDos->e_lfanew); needed += tmpNt->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_SECTION_HEADER) * tmpNt->FileHeader.NumberOfSections; if (buffer.Length < needed) { ptr = buffer.Fetch(0, needed); if (buffer.Length < needed) { return(null); } } return(new PEHeader(buffer, virt)); }
private unsafe PEHeader(string path) { var data = new byte[4096]; using (var stream = File.OpenRead(path)) stream.Read(data, 0, data.Length); fixed(byte *pData = data) { IMAGE_DOS_HEADER * idh = (IMAGE_DOS_HEADER *)pData; IMAGE_NT_HEADERS32 *inhs = (IMAGE_NT_HEADERS32 *)(pData + idh->e_lfanew); // PE32 (0x10b) or PE32+ (0x20b) if (inhs->OptionalHeader.Magic == 0x20b) { m_is64Bit = true; if (((IMAGE_NT_HEADERS64 *)inhs)->OptionalHeader.DataDirectory.Size > 0) { m_isManaged = true; } } else { if (inhs->OptionalHeader.DataDirectory.Size > 0) { m_isManaged = true; } } } }
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); }
private void ValidateRawDll(Image image) { IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER *)image.BasePtr; if (image.Size < sizeof(IMAGE_DOS_HEADER)) { throw new LoadFailedException("Bad or unknown DLL format (missing DOS header)."); } if (dosHeader->e_magic_byte[0] != 'M' || dosHeader->e_magic_byte[1] != 'Z') { throw new LoadFailedException("Bad or unknown DLL format (missing DOS header 'MZ' signature)."); } if (dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32) > image.Size) { throw new LoadFailedException("Bad or unknown DLL format (missing NT header data)."); } IMAGE_NT_HEADERS32 *headers = image.Headers32; if (headers->Signature[0] != 'P' || headers->Signature[1] != 'E' || headers->Signature[2] != '\0' || headers->Signature[3] != '\0') { throw new LoadFailedException("Bad or unknown DLL format (missing NT header 'PE' signature)."); } switch (headers->FileHeader.Machine) { case MachineType.I386: if (Environment.Is64BitProcess) { throw new LoadFailedException("The DLL is compiled for 32-bit x86, but the current process is not a 32-bit process."); } break; case MachineType.x64: if (!Environment.Is64BitProcess) { throw new LoadFailedException("The DLL is compiled for 64-bit x64, but the current process is not a 64-bit process."); } break; default: throw new LoadFailedException("The DLL is compiled for an unsupported processor architecture."); } if ((headers->OptionalHeader.SectionAlignment & 1) != 0) { throw new LoadFailedException("This DLL has an unsupported section alignment of " + headers->OptionalHeader.SectionAlignment); } if (headers->OptionalHeader.SizeOfHeaders > image.Size) { throw new LoadFailedException("Bad or unknown DLL format (damaged NT header data)."); } }
private static unsafe void WriteDosHeader(byte[] buffer, uint pos, IMAGE_DOS_HEADER header) { fixed(byte *p = buffer) { IMAGE_DOS_HEADER *ptr = (IMAGE_DOS_HEADER *)(p + pos); *ptr = header; } }
static unsafe USysCall64() { UNICODE_STRING szNtdll = new UNICODE_STRING("ntdll"); UIntPtr ptrNtdll = UIntPtr.Zero; long ntstatus = LdrGetDllHandle(IntPtr.Zero, IntPtr.Zero, ref szNtdll, ref ptrNtdll); if (ntstatus != 0) { Debugger.Break(); } byte * lpNtdll = (byte *)ptrNtdll; IMAGE_DOS_HEADER * piDH = (IMAGE_DOS_HEADER *)lpNtdll; IMAGE_OPTIONAL_HEADER64 *piOH = (IMAGE_OPTIONAL_HEADER64 *)(lpNtdll + piDH->e_lfanew + 0x18); IMAGE_EXPORT_DIRECTORY * exportDir = (IMAGE_EXPORT_DIRECTORY *)(lpNtdll + piOH->ExportTable.VirtualAddress); uint * names = (uint *)(lpNtdll + exportDir->AddressOfNames); uint * functions = (uint *)(lpNtdll + exportDir->AddressOfFunctions); ushort *ordinals = (ushort *)(lpNtdll + exportDir->AddressOfNameOrdinals); var listOfNames = new List <string>(); var dictOfZwFunctions = new Dictionary <string, ulong>(); for (int i = 0; i < exportDir->NumberOfNames; i++) { var name = Marshal.PtrToStringAnsi(new IntPtr(lpNtdll + names[i])); if (!name.StartsWith("Zw")) { continue; } var fnAddr = new UIntPtr(lpNtdll + functions[ordinals[i]]); dictOfZwFunctions.Add(name, fnAddr.ToUInt64()); } var sortedByAddr = dictOfZwFunctions .OrderBy(x => x.Value) .ToDictionary(x => "Nt" + x.Key.Substring(2, x.Key.Length - 2), x => x.Value); var sysCallLookup = new Dictionary <string, uint>(); uint sysNo = 0; foreach (var entry in sortedByAddr) { sysCallLookup.Add(entry.Key, sysNo); sysNo++; } SysCallTable = sysCallLookup; }
private static bool GetLibraryInfo(IntPtr handle, out DynLibInfo lib) { lib = new DynLibInfo(); if (handle == IntPtr.Zero) { return(false); } MEMORY_BASIC_INFORMATION info; if (VirtualQuery(handle, out info, Marshal.SizeOf <MEMORY_BASIC_INFORMATION>()) == 0) { return(false); } //uintptr_t baseAddr = reinterpret_cast<uintptr_t>(info.AllocationBase); IMAGE_DOS_HEADER * dos = (IMAGE_DOS_HEADER *)info.AllocationBase; IMAGE_NT_HEADERS * pe = (IMAGE_NT_HEADERS *)(info.AllocationBase + dos->e_lfanew); IMAGE_FILE_HEADER * file = &pe->FileHeader; IMAGE_OPTIONAL_HEADER *opt = &pe->OptionalHeader; if (dos->e_magic != IMAGE_DOS_SIGNATURE) { return(false); } if (pe->Signature != IMAGE_NT_SIGNATURE) { return(false); } if (opt->Magic != MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC) { return(false); } if (file->Machine != 0x014c)// Intel 386. { return(false); } if ((file->Characteristics & 0x2000) == 0)// File is a DLL. { return(false); } lib.memorySize = opt->SizeOfImage; lib.baseAddress = info.AllocationBase; return(true); }
private static unsafe IMAGE_DOS_HEADER ReadDosHeader(byte[] buffer, uint pos) { IMAGE_DOS_HEADER dosHeader = new IMAGE_DOS_HEADER(); fixed(byte *p = buffer) { IMAGE_DOS_HEADER *ptr = (IMAGE_DOS_HEADER *)(p + pos); dosHeader = *ptr; } return(dosHeader); }
public ExportResolver(ProcessModule module) { lib = (IMAGE_DOS_HEADER *)module.BaseAddress; if (lib->e_magic != IMAGE_DOS_SIGNATURE) { throw new Exception("Invalid IMAGE_DOS_HEADER signature"); } header = (IMAGE_NT_HEADERS *)((byte *)lib + lib->e_lfanew); if (header->Signature != IMAGE_NT_SIGNATURE) { throw new Exception("Invalid IMAGE_NT_HEADERS signature"); } if (header->OptionalHeader.NumberOfRvaAndSizes == 0) { throw new Exception("Invalid NumberOfRvaAndSizes"); } exports = (IMAGE_EXPORT_DIRECTORY *)((byte *)lib + header->OptionalHeader.ExportTable.VirtualAddress); }
private static bool Is32Bit(string filePath) { filePath = Environment.ExpandEnvironmentVariables(filePath); // Read the first byte[] data = new byte[4096]; FileInfo fileInfo = new FileInfo(filePath); using (FileStream fileStream = fileInfo.Open(FileMode.Open, FileAccess.Read)) { fileStream.Read(data, 0, 4096); fileStream.Flush(); } unsafe { 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; // Now that we have the DOS header, we can get the offset // (e_lfanew) add it to the original address (p_Data) and // squeeze those bytes into a IMAGE_NT_HEADERS32 structure IMAGE_NT_HEADERS32 *inhs = (IMAGE_NT_HEADERS32 *)(idh->e_lfanew + p_Data); // Use the OptionalHeader.Magic. It tells you whether // the assembly is PE32 (0x10b) or PE32+ (0x20b). // PE32+ just means 64-bit. So, instead of checking if it is // an X64 or Itanium, just check if it's a PE32+. if (inhs->OptionalHeader.Magic == 0x20b) { // 64 bit assembly return(false); } else { // 32 bit assembly return(true); } } } }
public static Symbol[] GetExports(IntPtr Handle) { List <Symbol> Exports = new List <Symbol>(); IMAGE_DOS_HEADER * DOS = (IMAGE_DOS_HEADER *)Handle; IMAGE_NT_HEADERS * NT = (IMAGE_NT_HEADERS *)((byte *)DOS + DOS->LFaNew); IMAGE_OPTIONAL_HEADER * Optional = &NT->OptionalHeader; IMAGE_EXPORT_DIRECTORY *ExportsDir = (IMAGE_EXPORT_DIRECTORY *)((byte *)Handle + Optional->ExportTable.VirtualAddress); uint *AddrOfNames = (uint *)((byte *)Handle + ExportsDir->AddressOfNames); uint *AddrOfFuncs = (uint *)((byte *)Handle + ExportsDir->AddressOfNames); for (int j = 0; j < ExportsDir->NumberOfNames; j++) { string Name = Marshal.PtrToStringAnsi((IntPtr)((uint)Handle + AddrOfNames[j])); long Func = AddrOfFuncs[j]; Exports.Add(new Symbol(Name, (ulong)Func, 0)); } return(Exports.ToArray()); }
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; } } } } } }
/// <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(); } } }
/// <summary> /// 加载dLL /// </summary> /// <param name="pUnmanagedBuffer"></param> /// <param name="iBufferLength"></param> /// <returns></returns> private unsafe Boolean LoadDLLFromMemory(IntPtr pUnmanagedBuffer, Int32 iBufferLength) { try { if (iBufferLength < sizeof(IMAGE_DOS_HEADER)) { throw new Exception("Data is too short"); } IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)pUnmanagedBuffer; if (pDosHeader->e_magic != 0x5A4D) { throw new Exception("DOS file format error"); } if (iBufferLength < pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)) { throw new Exception("Data is short"); } IMAGE_NT_HEADERS *pPEHeader = (IMAGE_NT_HEADERS *)(pUnmanagedBuffer + pDosHeader->e_lfanew); if (pPEHeader->Signature != Win32API.IMAGE_NT_SIGNATURE) { throw new Exception("windows file Signature error"); } if ((pPEHeader->FileHeader.Characteristics & Win32API.IMAGE_FILE_DLL) != Win32API.IMAGE_FILE_DLL) { throw new Exception("Dll Not dynamic library"); } IMAGE_SECTION_HEADER *pSectionHeader = (IMAGE_SECTION_HEADER *)(pUnmanagedBuffer + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)); for (Int32 i = 0; i < pPEHeader->FileHeader.NumberOfSections; i++) { if (pSectionHeader[i].PointerToRawData + pSectionHeader[i].SizeOfRawData > iBufferLength) { throw new Exception("Section data error"); } } //计算空间 this.mModuleSize = this.CalcTotalImageSize(pPEHeader, pSectionHeader); if (this.mModuleSize == 0 || this.mModuleSize > iBufferLength * 10) { throw new Exception("unknown error"); } #if _WIN64 this.mModuleHandle = Win32API.VirtualAlloc((IntPtr)((Int64)pPEHeader->OptionalHeader.ImageBase), this.mModuleSize, Win32API.MEM_COMMIT | Win32API.MEM_RESERVE, Win32API.PAGE_EXECUTE_READWRITE); #else this.mModuleHandle = Win32API.VirtualAlloc((IntPtr)((Int32)pPEHeader->OptionalHeader.ImageBase), this.mModuleSize, Win32API.MEM_COMMIT | Win32API.MEM_RESERVE, Win32API.PAGE_EXECUTE_READWRITE); #endif if (this.mModuleHandle == IntPtr.Zero) { Int32 iLastError = Marshal.GetLastWin32Error(); this.mModuleHandle = Win32API.VirtualAlloc(IntPtr.Zero, this.mModuleSize, Win32API.MEM_COMMIT | Win32API.MEM_RESERVE, Win32API.PAGE_EXECUTE_READWRITE); } if (this.mModuleHandle == IntPtr.Zero) { throw new Exception("run out of memory?"); } this.CopyDllDatas(pUnmanagedBuffer, pPEHeader, pSectionHeader); pDosHeader = (IMAGE_DOS_HEADER *)this.mModuleHandle; pPEHeader = (IMAGE_NT_HEADERS *)(this.mModuleHandle + pDosHeader->e_lfanew); pSectionHeader = (IMAGE_SECTION_HEADER *)(this.mModuleHandle + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)); if (pDosHeader->e_magic != 0x5A4D) { throw new Exception("DOS file format error"); } if (iBufferLength < pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)) { throw new Exception("DOS file header data error"); } if (pPEHeader->Signature != Win32API.IMAGE_NT_SIGNATURE) { throw new Exception("windows file Signature error"); } if ((pPEHeader->FileHeader.Characteristics & Win32API.IMAGE_FILE_DLL) != Win32API.IMAGE_FILE_DLL) { throw new Exception("Dll Not dynamic library"); } for (Int32 i = 0; i < pPEHeader->FileHeader.NumberOfSections; i++) { if (pSectionHeader[i].PointerToRawData + pSectionHeader[i].SizeOfRawData > iBufferLength) { throw new Exception("Section data error"); } } //重定位 var baseRelocDirEntry = pPEHeader->OptionalHeader.GetDirectory(IMAGE_DIRECTORY_ENTRY.IMAGE_DIRECTORY_ENTRY_BASERELOC); if (baseRelocDirEntry.VirtualAddress > 0 && baseRelocDirEntry.Size > 0) { this.ReLocation(pPEHeader); } this.FillImportTable(pPEHeader); #if _WIN64 this.mDllMain = (DllMainHandle)Marshal.GetDelegateForFunctionPointer((IntPtr)((Int64)this.mModuleHandle + (Int64)pPEHeader->OptionalHeader.AddressOfEntryPoint), typeof(DllMainHandle)); #else this.mDllMain = (DllMainHandle)Marshal.GetDelegateForFunctionPointer(this.mModuleHandle + (Int32)pPEHeader->OptionalHeader.AddressOfEntryPoint, typeof(DllMainHandle)); #endif return(this.mDllMain.Invoke(this.mModuleHandle, Win32API.DLL_PROCESS_ATTACH, IntPtr.Zero)); } catch (Exception ex) { throw (ex); } }
/// <summary> /// 获取API函数地址 /// </summary> /// <param name="sProcName"></param> /// <returns></returns> private unsafe IntPtr GetProcAddress(String sProcName) { if (this.mModuleHandle == IntPtr.Zero) { return(IntPtr.Zero); } if (String.IsNullOrEmpty(sProcName)) { return(IntPtr.Zero); } IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)this.mModuleHandle; IMAGE_NT_HEADERS *pPEHeader = (IMAGE_NT_HEADERS *)(this.mModuleHandle + pDosHeader->e_lfanew); var exportDirectoryEntry = pPEHeader->OptionalHeader.GetDirectory(IMAGE_DIRECTORY_ENTRY.IMAGE_DIRECTORY_ENTRY_EXPORT); var iOffsetStart = exportDirectoryEntry.VirtualAddress; var iSize = exportDirectoryEntry.Size; if (iOffsetStart == 0 || iSize == 0) { return(IntPtr.Zero); } #if _WIN64 IMAGE_EXPORT_DIRECTORY *pExportDirectory = (IMAGE_EXPORT_DIRECTORY *)((IntPtr)((Int64)this.mModuleHandle + (Int64)iOffsetStart)); UInt32 *pAddressOfFunctions = (UInt32 *)((IntPtr)((Int64)this.mModuleHandle + (Int64)pExportDirectory->AddressOfFunctions)); UInt16 *pAddressOfNameOrdinals = (UInt16 *)((IntPtr)((Int64)this.mModuleHandle + (Int64)pExportDirectory->AddressOfNameOrdinals)); UInt32 *pAddressOfNames = (UInt32 *)((IntPtr)((Int64)this.mModuleHandle + (Int64)pExportDirectory->AddressOfNames)); #else IMAGE_EXPORT_DIRECTORY *pExportDirectory = (IMAGE_EXPORT_DIRECTORY *)(this.mModuleHandle + (Int32)iOffsetStart); UInt32 *pAddressOfFunctions = (UInt32 *)(this.mModuleHandle + (Int32)pExportDirectory->AddressOfFunctions); UInt16 *pAddressOfNameOrdinals = (UInt16 *)(this.mModuleHandle + (Int32)pExportDirectory->AddressOfNameOrdinals); UInt32 *pAddressOfNames = (UInt32 *)(this.mModuleHandle + (Int32)pExportDirectory->AddressOfNames); #endif UInt16 iOrdinal = 0; if (UInt16.TryParse(sProcName, out iOrdinal)) { if (iOrdinal >= pExportDirectory->Base) { iOrdinal = (UInt16)(iOrdinal - pExportDirectory->Base); if (iOrdinal >= 0 && iOrdinal < pExportDirectory->NumberOfFunctions) { var iFunctionOffset = pAddressOfFunctions[iOrdinal]; if (iFunctionOffset > iOffsetStart && iFunctionOffset < (iOffsetStart + iSize)) // maybe Export Forwarding { return(IntPtr.Zero); } else { #if _WIN64 return((IntPtr)((Int64)this.mModuleHandle + iFunctionOffset)); #else return((IntPtr)((Int32)this.mModuleHandle + iFunctionOffset)); #endif } } } } else { for (Int32 i = 0; i < pExportDirectory->NumberOfNames; i++) { #if _WIN64 var sFuncName = Marshal.PtrToStringAnsi((IntPtr)((Int64)this.mModuleHandle + (Int64)pAddressOfNames[i])); #else var sFuncName = Marshal.PtrToStringAnsi(this.mModuleHandle + (Int32)pAddressOfNames[i]); #endif if (sProcName.Equals(sFuncName)) { iOrdinal = pAddressOfNameOrdinals[i]; if (iOrdinal >= 0 && iOrdinal < pExportDirectory->NumberOfFunctions) { var iFunctionOffset = pAddressOfFunctions[iOrdinal]; if (iFunctionOffset > iOffsetStart && iFunctionOffset < (iOffsetStart + iSize)) // maybe Export Forwarding { return(IntPtr.Zero); } else { #if _WIN64 return((IntPtr)((Int64)this.mModuleHandle + iFunctionOffset)); #else return((IntPtr)((Int32)this.mModuleHandle + iFunctionOffset)); #endif } } } } } return(IntPtr.Zero); }