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); }
//[FieldOffset(96)] public IMAGE_DATA_DIRECTORY DataDirectory0; //[FieldOffset(104)] public IMAGE_DATA_DIRECTORY DataDirectory1; //[FieldOffset(112)] public IMAGE_DATA_DIRECTORY DataDirectory2; //[FieldOffset(120)] public IMAGE_DATA_DIRECTORY DataDirectory3; //[FieldOffset(128)] public IMAGE_DATA_DIRECTORY DataDirectory4; //[FieldOffset(136)] public IMAGE_DATA_DIRECTORY DataDirectory5; //[FieldOffset(144)] public IMAGE_DATA_DIRECTORY DataDirectory6; //[FieldOffset(152)] public IMAGE_DATA_DIRECTORY DataDirectory7; //[FieldOffset(160)] public IMAGE_DATA_DIRECTORY DataDirectory8; //[FieldOffset(168)] public IMAGE_DATA_DIRECTORY DataDirectory9; //[FieldOffset(176)] public IMAGE_DATA_DIRECTORY DataDirectory10; //[FieldOffset(284)] public IMAGE_DATA_DIRECTORY DataDirectory11; //[FieldOffset(292)] public IMAGE_DATA_DIRECTORY DataDirectory12; //[FieldOffset(300)] public IMAGE_DATA_DIRECTORY DataDirectory13; //[FieldOffset(308)] public IMAGE_DATA_DIRECTORY DataDirectory14; //[FieldOffset(316)] public IMAGE_DATA_DIRECTORY DataDirectory15; public static unsafe IMAGE_DATA_DIRECTORY *GetDataDirectory(IMAGE_OPTIONAL_HEADER32 *header, int zeroBasedIndex) { return((&header->ExportTable) + zeroBasedIndex); }
/// <summary> /// Locates version resource in a PE image /// </summary> /// <param name="FileData">Pointer to raw or mapped exe or dll</param> /// <param name="ResourceSize">Returns size of found resource</param> /// <returns>Pointer to located version resource or null if none found</returns> public unsafe static VS_VERSIONINFO *GetRawFileVersionResource(void *FileData, out int ResourceSize) { ResourceSize = 0; var dos_header = (IMAGE_DOS_HEADER *)FileData; var header = (IMAGE_NT_HEADERS *)((byte *)FileData + dos_header->e_lfanew); if (header == null || header->Signature != 0x4550 || header->FileHeader.SizeOfOptionalHeader == 0) { SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); return(null); } IMAGE_DATA_DIRECTORY *resource_header; if (header->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)) { IMAGE_OPTIONAL_HEADER32 *optional_header = (IMAGE_OPTIONAL_HEADER32 *)&header->OptionalHeader; var data_directory = (IMAGE_DATA_DIRECTORY *)&optional_header->DataDirectory[0]; resource_header = data_directory + 2; } else if (header->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64)) { IMAGE_OPTIONAL_HEADER64 *optional_header = (IMAGE_OPTIONAL_HEADER64 *)&header->OptionalHeader; var data_directory = (IMAGE_DATA_DIRECTORY *)&optional_header->DataDirectory[0]; resource_header = data_directory + 2; } else { SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); return(null); } var section_table = (IMAGE_SECTION_HEADER *)((BYTE *)&header->OptionalHeader + header->FileHeader.SizeOfOptionalHeader); IMAGE_SECTION_HEADER *section_header = null; for (int i = 0; i < header->FileHeader.NumberOfSections; i++) { if (section_table[i].Name != _rsrc_id) { continue; } section_header = section_table + i; break; } if (section_header == null) { SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); return(null); } var raw = (BYTE *)FileData + section_header->PointerToRawData; var resource_section = (IMAGE_RESOURCE_DIRECTORY *)(raw + (resource_header->VirtualAddress - section_header->VirtualAddress)); var resource_dir_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resource_section + 1); for (int i = 0; i < resource_section->NumberOfNamedEntries + resource_section->NumberOfIdEntries; i++) { if (!resource_dir_entry[i].NameIsString && resource_dir_entry[i].Id == RT_VERSION && resource_dir_entry[i].DataIsDirectory) { var found_entry = resource_dir_entry + i; var found_dir = (IMAGE_RESOURCE_DIRECTORY *)((BYTE *)resource_section + found_entry->OffsetToDirectory); if ((found_dir->NumberOfIdEntries + found_dir->NumberOfNamedEntries) == 0) { continue; } var found_dir_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(found_dir + 1); for (int j = 0; j < found_dir->NumberOfNamedEntries + found_dir->NumberOfIdEntries; j++) { if (!found_dir_entry[j].DataIsDirectory) { continue; } var found_subdir = (IMAGE_RESOURCE_DIRECTORY *)((BYTE *)resource_section + found_dir_entry->OffsetToDirectory); if ((found_subdir->NumberOfIdEntries + found_subdir->NumberOfNamedEntries) == 0) { continue; } var found_subdir_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(found_subdir + 1); if (found_subdir_entry->DataIsDirectory) { continue; } var found_data_entry = (IMAGE_RESOURCE_DATA_ENTRY *)((BYTE *)resource_section + found_subdir_entry->OffsetToData); var resptr = (VS_VERSIONINFO *)(raw + (found_data_entry->OffsetToData - section_header->VirtualAddress)); if (resptr->wType != 0 || !StringComparer.Ordinal.Equals(new string(resptr->szKey, 0, 15), "VS_VERSION_INFO") || resptr->FixedFileInfo.Signature != FixedFileVerInfo.FixedFileVerSignature) { SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); return(null); } ResourceSize = (int)found_data_entry->Size; return(resptr); } } } SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); return(null); }
internal OptionalHeader(IMAGE_OPTIONAL_HEADER32 *header) { _header32 = header; }