public static unsafe List <uint> GetStaticImportNameOffsets(byte[] fileBytes, string arch) { // This function walks the PE header to get the offset of the Import Address Table // (IAT) and then resolves the imports' names fixed(byte *ptr_data = fileBytes) { // Initial validation UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data; if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE) { Console.WriteLine("[-] Magic bytes don't match"); return(null); } // We'll split here because much of the work we need to do uses offsets from the NT headers if (arch == "x64") { UnsafeHelpers.IMAGE_NT_HEADERS64 *nt_header = (UnsafeHelpers.IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != UnsafeHelpers.IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(null); } IMAGE_DATA_DIRECTORY *DataDirectory = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]); // Safety check in case others fail. This will happen on x86 EXEs and some .NET assemblies. uint itRVA = DataDirectory->VirtualAddress; if (itRVA == 0) { Console.WriteLine("[!] Import Table RVA is 0. Something is wrong..."); return(null); } // Do the conversion from the RVA to the offsets we'll need to do some math Offset iatOffsets = RvaToOffset(nt_header, null, itRVA, "IAT"); // Math to get the true offset to the name of the DLL // https://ired.team/miscellaneous-reversing-forensics/pe-file-header-parser-in-c++#pimage_import_descriptor uint offset = iatOffsets.RawOffset + (itRVA - iatOffsets.RVA); UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *)(ptr_data + offset); List <uint> nameOffsets = new List <uint>(); while (firstModule->Name != 0) { uint trueOffset = 0 + iatOffsets.RawOffset + (firstModule->Name - iatOffsets.RVA); nameOffsets.Add(trueOffset); firstModule++; } return(nameOffsets); } else // x86 { UnsafeHelpers.IMAGE_NT_HEADERS32 *nt_header = (UnsafeHelpers.IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != UnsafeHelpers.IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(null); } UnsafeHelpers.IMAGE_DATA_DIRECTORY *DataDirectory = (UnsafeHelpers.IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[UnsafeHelpers.IMAGE_DIRECTORY_ENTRY_IMPORT]); // Safety check in case others fail. This will happen on x86 EXEs and some .NET assemblies. uint itRVA = DataDirectory->VirtualAddress; if (itRVA == 0) { Console.WriteLine("[!] Import Table RVA is 0. Something is wrong..."); return(null); } // Do the conversion from the RVA to the offsets we'll need to do some math Offset iatOffsets = RvaToOffset(null, nt_header, itRVA, "IAT"); // Math to get the true offset to the name of the DLL // https://ired.team/miscellaneous-reversing-forensics/pe-file-header-parser-in-c++#pimage_import_descriptor uint offset = iatOffsets.RawOffset + (itRVA - iatOffsets.RVA); UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *)(ptr_data + offset); //uint nameOffset = 0 + rdataRawOffset + (firstModule->Name - rdataRVA); List <uint> nameOffsets = new List <uint>(); while (firstModule->Name != 0) { uint trueOffset = 0 + iatOffsets.RawOffset + (firstModule->Name - iatOffsets.RVA); nameOffsets.Add(trueOffset); firstModule++; } return(nameOffsets); } } }
public static unsafe List <string> GetDynamicImports(byte[] fileBytes, string arch) { // This function walks the PE header to get the offset of the Delay-Load Descriptor Table // (DLDT) and then resolves the imports' names List <string> dynamicModuleNames = new List <string>(); fixed(byte *ptr_data = fileBytes) { // Initial validation UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data; if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE) { Console.WriteLine("[-] Magic bytes don't match"); return(dynamicModuleNames); } // Get the NT headers if (arch == "x64") { IMAGE_NT_HEADERS64 *nt_header = (IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(dynamicModuleNames); } // Get the offset for the delay-load import tables ulong *DataDirectory = nt_header->OptionalHeader.DataDirectory; IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); uint dldtRVA = dldt->VirtualAddress; if (dldtRVA == 0) // No delayed imports found { return(dynamicModuleNames); } Offset offsets = RvaToOffset(nt_header, null, dldtRVA, "DLDT"); uint offset = offsets.RawOffset + (dldtRVA - offsets.RVA); // Iterate over the list of delay-loaded modules IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset); while (firstModule->szName != 0) { Offset offsetToNames = RvaToOffset(nt_header, null, firstModule->szName, "szName"); uint offset2 = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA); dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2))); firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR))); } } else // x86 { IMAGE_NT_HEADERS32 *nt_header = (IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(dynamicModuleNames); } // Get the offset for the delay-load import tables ulong *DataDirectory = nt_header->OptionalHeader.DataDirectory; IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); uint dldtRVA = dldt->VirtualAddress; if (dldtRVA == 0) // No delayed imports found { return(dynamicModuleNames); } Offset offsets = RvaToOffset(null, nt_header, dldtRVA, "DLDT"); uint offset = offsets.RawOffset + (dldtRVA - offsets.RVA); // Iterate over the list of delay-loaded modules IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset); while (firstModule->szName != 0) { Offset offsetToNames = RvaToOffset(null, nt_header, firstModule->szName, "szName"); uint offset2 = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA); dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2))); firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR))); } } return(dynamicModuleNames); } }