public static unsafe NTHeaders64 *GetNtHeaders64(byte *pBin) { // Bin is binary btw. Imo clearer than using peFile. MS_DOS_Stub *stub = (MS_DOS_Stub *)(pBin); if (stub->e_magic != IMAGE_DOS_SIGNATURE) { throw new FormatException("Error, Invalid file. DOS Signature is incorrect."); } NTHeaders64 *ntHeaders = (NTHeaders64 *)(pBin + stub->e_lfanew); if (ntHeaders->MagicNumber != IMAGE_NT_PEHEADER_SIGNATURE) { throw new FormatException("Error, Invalid file. PE File signature incorrect."); } if (ntHeaders->optnHeader.magic == Magic.PE32) { throw new FormatException("Error, Invalid file. 32 Bit DLL's are not supported."); } else if (ntHeaders->optnHeader.magic != Magic.PE64) { throw new FormatException("Error, Invalid file. Optional header signature is incorrect."); } return(ntHeaders); }
public static unsafe Dictionary <string, UInt32> DumpSymbolsFromFile64(byte *pBin) { Dictionary <string, UInt32> ExportTable = new Dictionary <string, UInt32>(); NTHeaders64 *ntHeaders = GetNtHeaders64(pBin); ImageExportDirectory *exportDir = (ImageExportDirectory *)(pBin + RVAtoOffset64(ntHeaders->optnHeader.exportTable.VirtualAddress, ntHeaders, pBin)); if (ntHeaders->optnHeader.numberOfRvaAndSizes <= 0) { throw new ArgumentException("Error, This file has no exports."); } for (UInt32 i = 0; i < exportDir->NumberOfNames; i++) { UInt32 offset = (UInt32)RVAtoOffset64((*(UInt32 *)(pBin + RVAtoOffset64(exportDir->AddressOfFunctions, ntHeaders, pBin) + (i * sizeof(UInt32)))), ntHeaders, pBin); UInt32 nameOffset = (UInt32)RVAtoOffset64((UInt32)exportDir->AddressOfNames, ntHeaders, pBin) + (i * sizeof(UInt32)); string methodName = Marshal.PtrToStringAnsi((IntPtr) (pBin + RVAtoOffset64((*(UInt32 *)(pBin + nameOffset)), ntHeaders, pBin))); ExportTable.Add(methodName, offset); } return(ExportTable); }
// The offset is where the data is located in the file // The RVA (Relative Virtual Address) is where the data is located relative to the start of the file when loaded into memory. // The VA (Virtual Address) is the address of something in its own sandbox. // // These can be calculated by: // VA = Offset + SectionHeader.VirtualAddress // RVA = Offset + (SectionHeader.VirtualAddress - SectionTable.PointerToRawData) // public static unsafe UInt64 RVAtoOffset64(UInt64 rva, NTHeaders64 *ntHeaders, byte *pBin) { MS_DOS_Stub *stub = (MS_DOS_Stub *)(pBin); for (int i = 0; i < ntHeaders->FileHeader.numberOfSections; i++) { section_table *secTable = (section_table *)(pBin + stub->e_lfanew + sizeof(NTHeaders64) + sizeof(section_table) * i); if (secTable->virtualAddress <= rva && rva < secTable->virtualAddress + secTable->virtualSize) { return((UInt64)(rva) + secTable->pointerToRawData - secTable->virtualAddress); } } throw new Exception("Erorr: Could not map RVA to Offset."); }