[>] Number of Sections: 10
[>] Size of Optional Header: 240
[>] File is an EXE
[>] Architecture: x64
[>] Image Base: 0x0000000140000000
[>] Image Size: 0x00026000
[>] Section Alignment: 0x00001000
[>] File Alignment: 0x00000200
[>] Subsystem: 0x0003
[>] Number of Data Directories: 16
[>] Size of Stack Reserve: 0x0000000000100000 bytes
[>] Size of Stack Commit: 0x0000000000001000 bytes
[>] Size of Heap Reserve: 0x0000000000100000 bytes
[>] Size of Heap Commit: 0x0000000000001000 bytes
Unknown optional header size
Failed to read NT headers
是的,我未能阅读可选标题和NT标题
我为RVA用于提交偏移的功能:
uint32_t rva_to_offset(uint32_t rva, IMAGE_SECTION_HEADER* sections, int numberOfSections) {
for (int i = 0; i < numberOfSections; i++) {
uint32_t sectionStartRVA = sections[i].VirtualAddress;
uint32_t sectionEndRVA = sectionStartRVA + sections[i].Misc.VirtualSize;
if (rva >= sectionStartRVA && rva < sectionEndRVA) {
// calculate and return the offset
uint32_t offset = sections[i].PointerToRawData + (rva - sectionStartRVA);
printf("RVA 0x%08X maps to offset 0x%08X in section %d\n", rva, offset, i);
return offset;
}
}
return 0xFFFFFFFF; // err
}
then parse标题:
PIMAGE_NT_HEADERS ParseHeaders(FILE* pefile, OUT uint16_t* architecture) {
IMAGE_DOS_HEADER DOSHeader;
if (fread(&DOSHeader, sizeof(IMAGE_DOS_HEADER), 1, pefile) != 1) {
printf("Failed to read DOS header \n");
return NULL;
}
// Move the file pointer to the NT headers location
if (fseek(pefile, DOSHeader.e_lfanew, SEEK_SET) != 0) {
printf("Failed to seek to NT headers \n");
return NULL;
}
PIMAGE_NT_HEADERS NtHeaders = (PIMAGE_NT_HEADERS)malloc(sizeof(IMAGE_NT_HEADERS));
if (NtHeaders == NULL) {
printf("Failed to allocate memory for NT headers \n");
return NULL;
}
if (fread(NtHeaders, sizeof(IMAGE_NT_HEADERS), 1, pefile) != 1) {
printf("Failed to read NT headers \n");
return NULL;
}
// Check the signature
if (NtHeaders->Signature != IMAGE_NT_SIGNATURE) {
printf("Invalid NT headers signature \n");
return NULL;
}
// File header
IMAGE_FILE_HEADER* FileHeader = &NtHeaders->FileHeader;
printf("\t[>] Number of Sections: %u\n", FileHeader->NumberOfSections);
printf("\t[>] Size of Optional Header: %u\n", FileHeader->SizeOfOptionalHeader);
// Check if DLL or EXE
if (FileHeader->Characteristics & IMAGE_FILE_DLL) {
printf("\t[>] File is a DLL \n");
}
if (FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) {
printf("\t[>] File is an EXE \n");
}
if (NtHeaders->OptionalHeader.OptionalHeader32.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
printf("\t[>] Architecture: x86 \n");
*architecture = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
// Access 32-bit optional header fields
i print parsed PE stuff here, i wont include it bc its long
}
else if (NtHeaders->OptionalHeader.OptionalHeader64.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
printf("\t[>] Architecture: x64 \n");
*architecture = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
// Access 64-bit optional header fields
i print parsed PE stuff here, i wont include it bc its long
}
else {
printf("\t[>] Architecture: ?");
*architecture = 0;
free(NtHeaders);
return NULL;
}
return NtHeaders;
}
I使用RVA来抵消解析部分的函数(此处出现“未知的可选标题大小”):
PIMAGE_SECTION_HEADER ParseSections(FILE* pefile, IN IMAGE_NT_HEADERS* NtHeaders) {
// Calculate offset from the start of the file
size_t sizeOfHeaders = 0;
if (NtHeaders->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)) {
sizeOfHeaders = NtHeaders->OptionalHeader.OptionalHeader32.SizeOfHeaders;
}
else if (NtHeaders->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64)) {
sizeOfHeaders = NtHeaders->OptionalHeader.OptionalHeader64.SizeOfHeaders;
}
else {
printf("Unknown optional header size \n");
return NULL;
}
// Calculate the offset to the section headers
if (fseek(pefile, sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + sizeOfHeaders, SEEK_SET) != 0) {
printf("Failed to seek to section headers \n");
return NULL;
}
// Allocate memory for section headers
PIMAGE_SECTION_HEADER SectionHeaders = (PIMAGE_SECTION_HEADER)malloc(NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
if (SectionHeaders == NULL) {
printf("Allocation failed (section headers) \n");
return NULL;
}
// Read section headers from the file
size_t readCount = fread(SectionHeaders, sizeof(IMAGE_SECTION_HEADER), NtHeaders->FileHeader.NumberOfSections, pefile);
if (readCount != NtHeaders->FileHeader.NumberOfSections) {
printf("Failed to read section headers \n");
free(SectionHeaders);
return NULL;
}
return SectionHeaders;
}
thressing IAT(“未能读取nt标题”在这里发生)
void ParseIAT(FILE* pefile, uint16_t architecture) {
if (!pefile) {
printf("Invalid PE file\n");
return;
}
if (architecture != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
printf("Error: Not x64 but trying to parse x64.\n");
return;
}
// Seek to the start of the NT headers to read them properly
fseek(pefile, 0, SEEK_SET);
IMAGE_NT_HEADERS NtHeaders;
if (fread(&NtHeaders, sizeof(IMAGE_NT_HEADERS), 1, pefile) != 1) {
printf("Failed to read NT headers \n");
return;
}
PIMAGE_SECTION_HEADER SectionHeaders = ParseSections(pefile, &NtHeaders);
if (SectionHeaders == NULL) {
printf("Failed to parse sections \n");
return;
}
IMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NtHeaders.OptionalHeader.OptionalHeader64;
// Get import directory RVA
IMAGE_DATA_DIRECTORY ImportDirectory = OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
uint32_t ImportDirectoryRVA = ImportDirectory.VirtualAddress;
uint32_t ImportDirectorySize = ImportDirectory.Size;
if (ImportDirectoryRVA == 0) {
printf("No import directory \n");
return;
}
printf("\t[>] Import Directory Address: 0x%08X - Size: 0x%08X\n\n", ImportDirectoryRVA, ImportDirectorySize);
// Convert import directory RVA to a file offset
uint32_t ImportDirectoryOffset = rva_to_offset(ImportDirectoryRVA, SectionHeaders, NtHeaders.FileHeader.NumberOfSections);
if (ImportDirectoryOffset == 0xFFFFFFFF) {
printf("Invalid import directory offset\n");
return;
}
// Seek to the import directory
if (fseek(pefile, ImportDirectoryOffset, SEEK_SET) != 0) {
printf("Failed to seek to import directory\n");
return;
}
IMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
while (fread(&ImportDescriptor, sizeof(ImportDescriptor), 1, pefile) == 1) {
if (ImportDescriptor.Name == 0) {
break; // end of descriptors
}
// Get module name
uint32_t moduleNameRVA = ImportDescriptor.Name;
uint32_t moduleNameOffset = rva_to_offset(moduleNameRVA, SectionHeaders, NtHeaders.FileHeader.NumberOfSections);
if (moduleNameOffset == 0xFFFFFFFF) {
printf("Invalid module name offset\n");
return;
}
char moduleName[256];
fseek(pefile, moduleNameOffset, SEEK_SET);
if (fread(moduleName, 1, sizeof(moduleName) - 1, pefile) <= 0) {
printf("Failed to read module name\n");
return;
}
moduleName[sizeof(moduleName) - 1] = '\0';
printf("[+] Module: %s\n", moduleName);
uint32_t iatRVA = ImportDescriptor.FirstThunk;
uint32_t iatOffset = rva_to_offset(iatRVA, SectionHeaders, NtHeaders.FileHeader.NumberOfSections);
if (iatOffset == 0xFFFFFFFF) {
printf("Invalid IAT offset\n");
return;
}
if (fseek(pefile, iatOffset, SEEK_SET) != 0) {
printf("Failed to seek IAT offset\n");
return;
}
// Read and print addresses to all functions in this module's IAT
uint32_t iatEntry;
printf("[+] Import Address Table Offset: 0x%08X\n", iatOffset);
while (fread(&iatEntry, sizeof(iatEntry), 1, pefile) == 1) {
if (iatEntry == 0) {
break; // end of entries
}
printf("\t[>] Function Address: 0x%08X ", iatEntry);
if (iatEntry & 0x80000000) {
uint16_t ordinal = (uint16_t)(iatEntry & 0xFFFF); // extract ordinal
printf("\t\t[>] Function imported by ordinal: %u\n", ordinal);
}
else {
uint32_t functionNameOffset = rva_to_offset(iatEntry, SectionHeaders, NtHeaders.FileHeader.NumberOfSections);
if (functionNameOffset == 0xFFFFFFFF) {
printf("Invalid function name offset\n");
return;
}
fseek(pefile, functionNameOffset, SEEK_SET);
IMAGE_IMPORT_BY_NAME functionName;
if (fread(&functionName, sizeof(functionName), 1, pefile) != 1) {
printf("Failed to read function name\n");
return;
}
printf("\t\t[>] Name: %s\n", functionName.Name);
}
}
}
}
我怎么称它们为主要:
PE pe;
pe.FilePath = argv[1];
FILE* pefile = fopen(pe.FilePath, "rb");
uint16_t architecture;
PIMAGE_NT_HEADERS NtHeaders = ParseHeaders(pefile, &architecture);
PIMAGE_SECTION_HEADER SectionHeaders = ParseSections(pefile, NtHeaders);
// PE32+ (x64)
if (architecture == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
ParseEAT(pefile, architecture);
ParseIAT(pefile, architecture);
}
我对很多代码表示歉意,我只是不知道这个问题是什么
the toge a Gook for for
为什么说Image_optional_header没有固定尺寸?
为什么您会比较
SizeOfOptionalHeader
而不是使用OptionalHeader.Magic