-
-
Save CitizenInsane/079849d25d982239ba13dbbdeec8ce93 to your computer and use it in GitHub Desktop.
Obtaining information about Portable Executable file (.exe, .dll)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% | |
% PURPOSE: | |
% | |
% Returns raw information about specified portable executable file. | |
% | |
% SYNTAX: | |
% | |
% [rawInfo] = GetPortableExecutableRawInfo(filename); | |
% [rawInfo, PEConstants] = GetPortableExecutableRawInfo(filename); | |
% | |
% DESCRIPTION: | |
% | |
% - '[rawInfo] = GetPortableExecutableRawInfo(filename)' return raw | |
% information in 'rawInfo' structure about specified portable | |
% executable 'filename'. | |
% | |
% INPUTS: | |
% | |
% - 'filename': Path to portable executable file. | |
% | |
% OUTPUTS: | |
% | |
% - 'rawInfo': Raw information structure about specified portable | |
% executable file. Not fully described here but this is just | |
% standard 'winnt.h'-structures of PE files. | |
% | |
% NB: If some 'winnt.h' structure is present no in the file, it will | |
% not be present in the outputs. Make sure to test for existence when | |
% later examining PE data. | |
% | |
% - 'PEConstants': Predefined PE constants to help testing PE values. | |
% | |
% SEE ALSO: | |
% | |
% - 'GetPortableExecutableSimplifiedInfo' | |
% | |
%% --- | |
function [rawInfo, PEConstants] = GetPortableExecutableRawInfo(filename) | |
%[ | |
% Helper constants | |
PEConstants.IMAGE_FILE_MACHINE_ARM = hex2dec('1c4'); | |
PEConstants.IMAGE_FILE_MACHINE_I386 = hex2dec('14c'); | |
PEConstants.IMAGE_FILE_MACHINE_IA64 = hex2dec('200'); | |
PEConstants.IMAGE_FILE_MACHINE_AMD64 = hex2dec('8664'); | |
% Checking arguments | |
if (nargin <1), error('MATLAB:minrhs', 'Not enough input argments.'); end | |
if (~ischar(filename) || ~exist(filename, 'file')), error('Invalid argument: filename must be path to existing file.'); end | |
% Opening file | |
[fid, errmsg] = fopen(filename, 'rb'); | |
if (fid < 0), error('Failed to open `%s`: %s', filename, errmsg); end | |
cuo = onCleanup(@()fclose(fid)); | |
% Initializing error message | |
errmsg = sprintf('Invalid argument: `%s` does not seem to be portable executable file.', filename); | |
% Reading IMAGE_DOS_HEADER structure | |
% NB: Endianess is little-endian in file | |
[DOSHeader.e_magic, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[~, c] = fread(fid, 13+4+2+10, 'uint16'); if (c ~= (13+4+2+10)), error(errmsg); end %#ok<SPERR> | |
[DOSHeader.e_lfanew, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
if (DOSHeader.e_magic ~= 23117), error(errmsg); end %#ok<SPERR> | |
% Shift and read PE_SIGNATURE | |
% NB: Endianess is little-endian in file | |
c = fseek(fid, DOSHeader.e_lfanew, 'bof'); if (c ~= 0), error(errmsg); end %#ok<SPERR> | |
[pe_signature, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
if (pe_signature ~= 17744), error(errmsg); end %#ok<SPERR> | |
% Read IMAGE_FILE_HEADER | |
% NB: Endianess is little-endian in file | |
[COFFHeader.Machine, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COFFHeader.NumberOfSections, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COFFHeader.TimeDateStamp, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COFFHeader.PointerToSymbolTable, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COFFHeader.NumberOfSymbols, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COFFHeader.SizeOfOptionalHeader, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COFFHeader.Characteristics.BitFieldValue, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
COFFHeader.Characteristics.IMAGE_FILE_RELOCS_STRIPPED = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^0) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_EXECUTABLE_IMAGE = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^1) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_LINE_NUMS_STRIPPED = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^2) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_LOCAL_SYMS_STRIPPED = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^3) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_AGGRESIVE_WS_TRIM = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^4) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_LARGE_ADDRESS_AWARE = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^5) ~= 0); | |
% 2^6 ( Yes there is a gap) | |
COFFHeader.Characteristics.IMAGE_FILE_BYTES_REVERSED_LO = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^7) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_32BIT_MACHINE = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^8) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_DEBUG_STRIPPED = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^9) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^10) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_NET_RUN_FROM_SWAP = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^11) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_SYSTEM = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^12) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_DLL = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^13) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_UP_SYSTEM_ONLY = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^14) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_BYTES_REVERSED_HI = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^15) ~= 0); | |
COFFHeader.Characteristics.IMAGE_FILE_RELOCS_STRIPPED = (bitand(COFFHeader.Characteristics.BitFieldValue, 2^16) ~= 0); | |
rawInfo.COFFHeader = COFFHeader; | |
% Read IMAGE_OPTIONAL_HEADER(OBJ|32|64) | |
% NB: Endianess is little-endian in file | |
if (COFFHeader.SizeOfOptionalHeader == 0) | |
% This is OBJ => There is no optional header | |
elseif ((COFFHeader.SizeOfOptionalHeader == 224) || (COFFHeader.SizeOfOptionalHeader == 240)) | |
% This is x32 or x64 => Optional headers differ from a few elements only | |
[PEOptionalHeader.Magic, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MajorLinkerVersion, c] = fread(fid, 1, 'char*1'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MinorLinkerVersion, c] = fread(fid, 1, 'char*1'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfCode, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfInitializedData, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfUninitializedData, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.AddressOfEntryPoint, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.BaseOfCode, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
if (COFFHeader.SizeOfOptionalHeader == 224) | |
[PEOptionalHeader.BaseOfData, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.ImageBase, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
else | |
[PEOptionalHeader.ImageBase, c] = fread(fid, 1, 'uint64'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
end | |
[PEOptionalHeader.SectionAlignment, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.FileAlignment, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MajorOperatingSystemVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MinorOperatingSystemVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MajorImageVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MinorImageVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MajorSubsystemVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.MinorSubsystemVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.Win32VersionValue, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfImage, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfHeaders, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.Checksum, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.Subsystem, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.DLLCharacteristics.BitFieldValue, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
% reserved 2^0 | |
% reserved 2^1 | |
% reserved 2^2 | |
% reserved 2^3 | |
% reserved 2^4 | |
% reserved 2^5 | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^6) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^7) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_NX_COMPAT = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^8) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^9) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_SEH = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^10) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_BIND = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^11) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_APPCONTAINER = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^12) ~= 0); | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^13) ~= 0); | |
% reserved 2^14 | |
PEOptionalHeader.DLLCharacteristics.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = (bitand(PEOptionalHeader.DLLCharacteristics.BitFieldValue, 2^15) ~= 0); | |
if (COFFHeader.SizeOfOptionalHeader == 224) | |
[PEOptionalHeader.SizeOfStackReserve, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfStackCommit, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfHeapReserve, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfHeapCommit, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
else | |
[PEOptionalHeader.SizeOfStackReserve, c] = fread(fid, 1, 'uint64'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfStackCommit, c] = fread(fid, 1, 'uint64'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfHeapReserve, c] = fread(fid, 1, 'uint64'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.SizeOfHeapCommit, c] = fread(fid, 1, 'uint64'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
end | |
[PEOptionalHeader.LoaderFlags, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.NumberOfRvaAndSizes, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
StandardRvaNames = { 'ExportTable', 'ImportTable', 'ResourceTable', 'ExceptionTable', 'CertificateTable', 'BaseRelocationTable', 'Debug', 'Architecture', ... | |
'GlobalPtr', 'TLSTable', 'LoadConfigTable', 'BoundImport', 'IAT', 'DelayImportDescriptor', 'CLRRuntimeHeader', 'Reserved' }; | |
isStandardRvas = (numel(StandardRvaNames) == PEOptionalHeader.NumberOfRvaAndSizes); | |
for ki = 1:PEOptionalHeader.NumberOfRvaAndSizes, | |
PEOptionalHeader.DataDirectory(ki).Name = 'Unknown'; | |
if (isStandardRvas), PEOptionalHeader.DataDirectory(ki).Name = StandardRvaNames{ki}; end | |
[PEOptionalHeader.DataDirectory(ki).VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[PEOptionalHeader.DataDirectory(ki).Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
end | |
rawInfo.PEOptionalHeader = PEOptionalHeader; | |
else | |
error(errmsg); %#ok<SPERR> | |
end | |
% Read IMAGE_COR20_HEADER | |
% NB: Endianess is little-endian in file | |
% https://stackoverflow.com/questions/480696/how-to-find-if-a-native-dll-file-is-compiled-as-x64-or-x86/3899746 | |
idxClr = find(strcmpi(StandardRvaNames, 'CLRRuntimeHeader')); | |
if (exist('PEOptionalHeader', 'var') && isStandardRvas && isscalar(idxClr) && (PEOptionalHeader.DataDirectory(idxClr).Size == 72)) | |
Rva = PEOptionalHeader.DataDirectory(idxClr); | |
offset = getOffsetFromRva(fid, DOSHeader, COFFHeader, Rva); | |
c = fseek(fid, offset, 'bof'); if (c ~= 0), error(errmsg); end %#ok<SPERR> | |
[COR20Header.cb, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.MajorRuntimeVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.MinorRuntimeVersion, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.MetaData.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.MetaData.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.Flags.BitFieldValue, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
COR20Header.Flags.COMIMAGE_FLAGS_ILONLY = (bitand(COR20Header.Flags.BitFieldValue, 2^0) ~= 0); | |
COR20Header.Flags.COMIMAGE_FLAGS_32BITREQUIRED = (bitand(COR20Header.Flags.BitFieldValue, 2^1) ~= 0); | |
COR20Header.Flags.COMIMAGE_FLAGS_IL_LIBRARY = (bitand(COR20Header.Flags.BitFieldValue, 2^2) ~= 0); | |
COR20Header.Flags.COMIMAGE_FLAGS_STRONGNAMESIGNED = (bitand(COR20Header.Flags.BitFieldValue, 2^3) ~= 0); | |
COR20Header.Flags.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = (bitand(COR20Header.Flags.BitFieldValue, 2^4) ~= 0); | |
COR20Header.Flags.COMIMAGE_FLAGS_TRACKDEBUGDATA = (bitand(COR20Header.Flags.BitFieldValue, 2^16) ~= 0); | |
COR20Header.Flags.COMIMAGE_FLAGS_32BITPREFERRED = (bitand(COR20Header.Flags.BitFieldValue, 2^17) ~= 0); | |
% The main program if it is an EXE (not used if a DLL?) | |
% If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. | |
% If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint | |
% (depricated for DLLs, use modules constructors intead). | |
[COR20Header.EntryPointTokenOrRva, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
% This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and | |
% code:PEFile.GetResource and accessible from managed code from | |
% System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into | |
% this blob, so logically the blob is a set of resources. | |
[COR20Header.Resources.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.Resources.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
% IL assemblies can be signed with a public-private key to validate who created it. The signature goes | |
% here if this feature is used. | |
[COR20Header.StrongNameSignature.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.StrongNameSignature.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
% Depricated, not used | |
[COR20Header.CodeManagerTable.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.CodeManagerTable.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
% Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points) | |
[COR20Header.VTableFixups.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.VTableFixups.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.ExportAddressTableJumps.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.ExportAddressTableJumps.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
% Null for ordinary IL images. NGEN images it points at a code:CORCOMPILE_HEADER structure | |
[COR20Header.ManagedNativeHeader.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
[COR20Header.ManagedNativeHeader.Size, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end %#ok<SPERR> | |
rawInfo.COR20Header = COR20Header; | |
end | |
%] | |
end | |
function [offset] = getOffsetFromRva(fid, DOSHeader, COFFHeader, Rva) | |
%[ | |
% We need to move in file to compute offset, so just make sure to rewind whatever happens | |
fpos = ftell(fid); | |
cuo = onCleanup(@()fseek(fid, fpos, 'bof')); | |
%% #define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + ((ntheader))->FileHeader.SizeOfOptionalHeader )) | |
%% ==> Well this mean skip [DOS](e_lfanew) + [PESignature](4) + COFFHeahder(20) + OptionalHeader(COFFHeader.SizeOfOptionalHeader) | |
firstSectionHeaderOffset = DOSHeader.e_lfanew + 4 + 20 + COFFHeader.SizeOfOptionalHeader; | |
sectionHeaderSizeInBytes = 8+6*4+2*2+4; | |
for si = 1:COFFHeader.NumberOfSections, | |
% Read section header | |
errmsg = 'Failed to parse section header'; | |
sectionHeaderOffset = firstSectionHeaderOffset + (si-1) * sectionHeaderSizeInBytes; | |
status = fseek(fid, sectionHeaderOffset, 'bof'); if (status ~=0), error('Failed to move to section header.'); end | |
[sectionHeader.Name, c] = fread(fid, 8, 'char*1=>char'); if (c ~= 8), error(errmsg); end; sectionHeader.Name = sectionHeader.Name.'; | |
[sectionHeader.PhysicalAddressOrVirtualSize, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.VirtualAddress, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.SizeOfRawData, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.PointerToRawData, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.PointerToRelocations, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.PointerToLineNumbers, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.NumberOfRelocations, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.NumberOfLineNumbers, c] = fread(fid, 1, 'uint16'); if (c ~= 1), error(errmsg); end | |
[sectionHeader.Characteristics, c] = fread(fid, 1, 'uint32'); if (c ~= 1), error(errmsg); end | |
% Lookup which section contains this RVA so we can translate the VA to a file offset | |
if ((Rva.VirtualAddress >= sectionHeader.VirtualAddress) && (Rva.VirtualAddress < (sectionHeader.VirtualAddress + sectionHeader.PhysicalAddressOrVirtualSize))) | |
delta = sectionHeader.VirtualAddress - sectionHeader.PointerToRawData; | |
offset = Rva.VirtualAddress - delta; | |
return; | |
end | |
end | |
error('Failed to find section header matching selected Rva'); | |
%] | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% | |
% PURPOSE: | |
% | |
% Returns simplified information about specified portable executable file. | |
% | |
% SYNTAX: | |
% | |
% [simplifiedInfo] = GetPortableExecutableSimplifiedInfo(filename); | |
% | |
% DESCRIPTION: | |
% | |
% - '[simplifiedInfo] = GetPortableExecutableSimplifiedInfo(filename)' | |
% returns simplified information in 'simplifiedInfo' structure about | |
% specified portable executable 'filename'. | |
% | |
% INPUTS: | |
% | |
% - 'filename': Path to portable executable file. | |
% | |
% OUTPUTS: | |
% | |
% - 'simplifiedInfo': Simplified information about specified portable | |
% executable file. | |
% | |
% simplifiedInfo.Kind = (Executable|Library|Other); | |
% simplifiedInfo.CodeType = (Native|Managed|Mixed); | |
% simplifiedInfo.Platform = (x32|x64|AnyCpu|x32Preferred|Other) | |
% | |
% REMARKS: | |
% | |
% The goal of this function is to quickly identify if some file is an | |
% executable or a library, in .NET or native code and what plaform is | |
% targeted. | |
% | |
% It was mainly written because of programs badly installing in | |
% %Program files (x86)% while being x64 anyway. | |
% | |
%% --- | |
function [simplifiedInfo] = GetPortableExecutableSimplifiedInfo(filename) | |
%[ | |
% Checking arguments | |
if (nargin <1), error('MATLAB:minrhs', 'Not enough input argments.'); end | |
% Initializing simplified info | |
simplifiedInfo.Kind = 'Other'; | |
simplifiedInfo.CodeType = 'Other'; | |
simplifiedInfo.Platform = 'Other'; | |
% Obtaining raw info | |
[rawInfo, PEConstants] = GetPortableExecutableRawInfo(filename); | |
% Determining 'Kind' of PE | |
if (isfield(rawInfo, 'PEOptionalHeader') && (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_EXECUTABLE_IMAGE)) | |
if (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_DLL) | |
simplifiedInfo.Kind = 'Library'; | |
else | |
simplifiedInfo.Kind = 'Executable'; | |
end | |
else | |
% No optional header or no IMAGE_FILE_EXECUTABLE_IMAGE flag ... | |
% Maybe just .obj or other thing | |
simplifiedInfo.Kind = 'Other'; | |
end | |
% Determining 'CodeType' | |
% NB: 'COR20Header' is present for MSIL code, but not for native code | |
if (isfield(rawInfo, 'COR20Header')) | |
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_ILONLY) | |
simplifiedInfo.CodeType = 'Managed'; | |
else | |
simplifiedInfo.CodeType = 'Mixed'; | |
end | |
else | |
simplifiedInfo.CodeType = 'Native'; | |
end | |
% Determining platform | |
if (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_AMD64) | |
simplifiedInfo.Platform = 'x64'; | |
elseif (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_I386) | |
if (isfield(rawInfo, 'COR20Header')) | |
% PE contains MSIL code, need more checks | |
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITREQUIRED) | |
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITPREFERRED) | |
simplifiedInfo.Platform = 'x32Preferred'; | |
else | |
simplifiedInfo.Platform = 'x32'; | |
end | |
else | |
simplifiedInfo.Platform = 'AnyCpu'; | |
end | |
else | |
% This is native code so ... | |
simplifiedInfo.Platform = 'x32'; | |
end | |
else | |
% ARM, ... | |
simplifiedInfo.Platform = 'Other'; | |
end | |
%] | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Answer for https://stackoverflow.com/questions/480696/how-to-find-if-a-native-dll-file-is-compiled-as-x64-or-x86/3899746