Class: Rex::PeParsey::PeBase

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/peparsey/pebase.rb

Direct Known Subclasses

Pe

Defined Under Namespace

Classes: ConfigHeader, DosHeader, ExportDirectory, ExportEntry, FileHeader, GenericHeader, GenericStruct, HeaderAccessor, ImportDescriptor, ImportEntry, OptionalHeader, OptionalHeader32, OptionalHeader64, RelocationDirectory, RelocationEntry, ResourceDirectory, ResourceEntry, RuntimeFunctionEntry, SectionHeader, TLSHeader, UnwindCode, UnwindInfo

Constant Summary collapse

IMAGE_DOS_SIGNATURE =

#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ

0x5a4d
IMAGE_DOS_HEADER_SIZE =

typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header

  WORD   e_magic;                     // Magic number
  WORD   e_cblp;                      // Bytes on last page of file
  WORD   e_cp;                        // Pages in file
  WORD   e_crlc;                      // Relocations
  WORD   e_cparhdr;                   // Size of header in paragraphs
  WORD   e_minalloc;                  // Minimum extra paragraphs needed
  WORD   e_maxalloc;                  // Maximum extra paragraphs needed
  WORD   e_ss;                        // Initial (relative) SS value
  WORD   e_sp;                        // Initial SP value
  WORD   e_csum;                      // Checksum
  WORD   e_ip;                        // Initial IP value
  WORD   e_cs;                        // Initial (relative) CS value
  WORD   e_lfarlc;                    // File address of relocation table
  WORD   e_ovno;                      // Overlay number
  WORD   e_res[4];                    // Reserved words
  WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
  WORD   e_oeminfo;                   // OEM information; e_oemid specific
  WORD   e_res2[10];                  // Reserved words
  LONG   e_lfanew;                    // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
64
IMAGE_DOS_HEADER =
Rex::Struct2::CStructTemplate.new(
  [ 'uint16v', 'e_magic',     IMAGE_DOS_SIGNATURE ],
  [ 'uint16v', 'e_cblp',      0 ],
  [ 'uint16v', 'e_cp',        0 ],
  [ 'uint16v', 'e_crlc',      0 ],
  [ 'uint16v', 'e_cparhdr',   0 ],
  [ 'uint16v', 'e_minalloc',  0 ],
  [ 'uint16v', 'e_maxalloc',  0 ],
  [ 'uint16v', 'e_ss',        0 ],
  [ 'uint16v', 'e_sp',        0 ],
  [ 'uint16v', 'e_csum',      0 ],
  [ 'uint16v', 'e_ip',        0 ],
  [ 'uint16v', 'e_cs',        0 ],
  [ 'uint16v', 'e_lfarlc',    0 ],
  [ 'uint16v', 'e_ovno',      0 ],
  [ 'template', 'e_res', Rex::Struct2::CStructTemplate.new(
    [ 'uint16v', 'e_res_0', 0 ],
    [ 'uint16v', 'e_res_1', 0 ],
    [ 'uint16v', 'e_res_2', 0 ],
    [ 'uint16v', 'e_res_3', 0 ]
  )],
  [ 'uint16v', 'e_oemid',     0 ],
  [ 'uint16v', 'e_oeminfo',   0 ],
  [ 'template', 'e_res2', Rex::Struct2::CStructTemplate.new(
    [ 'uint16v', 'e_res2_0', 0 ],
    [ 'uint16v', 'e_res2_1', 0 ],
    [ 'uint16v', 'e_res2_2', 0 ],
    [ 'uint16v', 'e_res2_3', 0 ],
    [ 'uint16v', 'e_res2_4', 0 ],
    [ 'uint16v', 'e_res2_5', 0 ],
    [ 'uint16v', 'e_res2_6', 0 ],
    [ 'uint16v', 'e_res2_7', 0 ],
    [ 'uint16v', 'e_res2_8', 0 ],
    [ 'uint16v', 'e_res2_9', 0 ]
  )],
  [ 'uint32v', 'e_lfanew',    0 ]
)
IMAGE_NT_SIGNATURE =

typedef struct _IMAGE_FILE_HEADER

WORD    Machine;
WORD    NumberOfSections;
DWORD   TimeDateStamp;
DWORD   PointerToSymbolTable;
DWORD   NumberOfSymbols;
WORD    SizeOfOptionalHeader;
WORD    Characteristics;

IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) #define IMAGE_SIZEOF_FILE_HEADER 20

0x00004550
IMAGE_FILE_MACHINE_I386 =
0x014c
IMAGE_FILE_MACHINE_IA64 =
0x0200
IMAGE_FILE_MACHINE_ALPHA64 =
0x0284
IMAGE_FILE_MACHINE_AMD64 =
0x8664
IMAGE_FILE_HEADER_SIZE =

because we include the signature

20+4
IMAGE_FILE_HEADER =
Rex::Struct2::CStructTemplate.new(
  # not really in the header, but easier for us this way
  [ 'uint32v', 'NtSignature',           0 ],
  [ 'uint16v', 'Machine',               0 ],
  [ 'uint16v', 'NumberOfSections',      0 ],
  [ 'uint32v', 'TimeDateStamp',         0 ],
  [ 'uint32v', 'PointerToSymbolTable',  0 ],
  [ 'uint32v', 'NumberOfSymbols',       0 ],
  [ 'uint16v', 'SizeOfOptionalHeader',  0 ],
  [ 'uint16v', 'Characteristics',       0 ]
)
SUPPORTED_MACHINES =
[
	IMAGE_FILE_MACHINE_I386,
	IMAGE_FILE_MACHINE_IA64,
	IMAGE_FILE_MACHINE_ALPHA64,
	IMAGE_FILE_MACHINE_AMD64
]
IMAGE_ORDINAL_FLAG32 =

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

union {
    DWORD   Characteristics;            // 0 for terminating null import descriptor
    DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
DWORD   TimeDateStamp;                  // 0 if not bound,
                                        // -1 if bound, and real date\time stamp
                                        //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                        // O.W. date/time stamp of DLL bound to (Old BIND)

DWORD   ForwarderChain;                 // -1 if no forwarders
DWORD   Name;
DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)

} IMAGE_IMPORT_DESCRIPTOR;

0x80000000
IMAGE_IMPORT_DESCRIPTOR_SIZE =
20
IMAGE_IMPORT_DESCRIPTOR =
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'OriginalFirstThunk',           0 ],
  [ 'uint32v', 'TimeDateStamp',                0 ],
  [ 'uint32v', 'ForwarderChain',               0 ],
  [ 'uint32v', 'Name',                         0 ],
  [ 'uint32v', 'FirstThunk',                   0 ]
)
IMAGE_EXPORT_DESCRIPTOR_SIZE =

typedef struct _IMAGE_EXPORT_DIRECTORY

DWORD   Characteristics;
DWORD   TimeDateStamp;
WORD    MajorVersion;
WORD    MinorVersion;
DWORD   Name;
DWORD   Base;
DWORD   NumberOfFunctions;
DWORD   NumberOfNames;
DWORD   AddressOfFunctions;     // RVA from base of image
DWORD   AddressOfNames;         // RVA from base of image
DWORD   AddressOfNameOrdinals;  // RVA from base of image

IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

40
IMAGE_EXPORT_DESCRIPTOR =
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'Characteristics',              0 ],
  [ 'uint32v', 'TimeDateStamp',                0 ],
  [ 'uint16v', 'MajorVersion',                 0 ],
  [ 'uint16v', 'MinorVersion',                 0 ],
  [ 'uint32v', 'Name',                         0 ],
  [ 'uint32v', 'Base',                         0 ],
  [ 'uint32v', 'NumberOfFunctions',            0 ],
  [ 'uint32v', 'NumberOfNames',                0 ],
  [ 'uint32v', 'AddressOfFunctions',           0 ],
  [ 'uint32v', 'AddressOfNames',               0 ],
  [ 'uint32v', 'AddressOfNameOrdinals',        0 ]
)
IMAGE_NUMBEROF_DIRECTORY_ENTRIES =

typedef struct _IMAGE_DATA_DIRECTORY

DWORD   VirtualAddress;
DWORD   Size;

IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

16
IMAGE_DATA_DIRECTORY_SIZE =
8
IMAGE_DIRECTORY_ENTRY_EXPORT =
0
IMAGE_DIRECTORY_ENTRY_IMPORT =
1
IMAGE_DIRECTORY_ENTRY_RESOURCE =
2
IMAGE_DIRECTORY_ENTRY_EXCEPTION =
3
IMAGE_DIRECTORY_ENTRY_SECURITY =
4
IMAGE_DIRECTORY_ENTRY_BASERELOC =
5
IMAGE_DIRECTORY_ENTRY_DEBUG =
6
IMAGE_DIRECTORY_ENTRY_COPYRIGHT =
7
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE =
7
IMAGE_DIRECTORY_ENTRY_GLOBALPTR =
8
IMAGE_DIRECTORY_ENTRY_TLS =
9
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG =
10
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT =
11
IMAGE_DIRECTORY_ENTRY_IAT =
12
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT =
13
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR =
14
IMAGE_DATA_DIRECTORY =
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'VirtualAddress',               0 ],
  [ 'uint32v', 'Size',                         0 ]
)
IMAGE_NT_OPTIONAL_HDR32_MAGIC =

typedef struct _IMAGE_OPTIONAL_HEADER

//
// Standard fields.
//

WORD    Magic;
BYTE    MajorLinkerVersion;
BYTE    MinorLinkerVersion;
DWORD   SizeOfCode;
DWORD   SizeOfInitializedData;
DWORD   SizeOfUninitializedData;
DWORD   AddressOfEntryPoint;
DWORD   BaseOfCode;
DWORD   BaseOfData;

//
// NT additional fields.
//

DWORD   ImageBase;
DWORD   SectionAlignment;
DWORD   FileAlignment;
WORD    MajorOperatingSystemVersion;
WORD    MinorOperatingSystemVersion;
WORD    MajorImageVersion;
WORD    MinorImageVersion;
WORD    MajorSubsystemVersion;
WORD    MinorSubsystemVersion;
DWORD   Win32VersionValue;
DWORD   SizeOfImage;
DWORD   SizeOfHeaders;
DWORD   CheckSum;
WORD    Subsystem;
WORD    DllCharacteristics;
DWORD   SizeOfStackReserve;
DWORD   SizeOfStackCommit;
DWORD   SizeOfHeapReserve;
DWORD   SizeOfHeapCommit;
DWORD   LoaderFlags;
DWORD   NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224

0x10b
IMAGE_SIZEOF_NT_OPTIONAL32_HEADER =
224
IMAGE_OPTIONAL_HEADER32 =
Rex::Struct2::CStructTemplate.new(
  [ 'uint16v', 'Magic',                        0 ],
  [ 'uint8',   'MajorLinkerVersion',           0 ],
  [ 'uint8',   'MinorLinkerVersion',           0 ],
  [ 'uint32v', 'SizeOfCode',                   0 ],
  [ 'uint32v', 'SizeOfInitializeData',         0 ],
  [ 'uint32v', 'SizeOfUninitializeData',       0 ],
  [ 'uint32v', 'AddressOfEntryPoint',          0 ],
  [ 'uint32v', 'BaseOfCode',                   0 ],
  [ 'uint32v', 'BaseOfData',                   0 ],
  [ 'uint32v', 'ImageBase',                    0 ],
  [ 'uint32v', 'SectionAlignment',             0 ],
  [ 'uint32v', 'FileAlignment',                0 ],
  [ 'uint16v', 'MajorOperatingSystemVersion',  0 ],
  [ 'uint16v', 'MinorOperatingSystemVersion',  0 ],
  [ 'uint16v', 'MajorImageVersion',            0 ],
  [ 'uint16v', 'MinorImageVersion',            0 ],
  [ 'uint16v', 'MajorSubsystemVersion',        0 ],
  [ 'uint16v', 'MinorSubsystemVersion',        0 ],
  [ 'uint32v', 'Win32VersionValue',            0 ],
  [ 'uint32v', 'SizeOfImage',                  0 ],
  [ 'uint32v', 'SizeOfHeaders',                0 ],
  [ 'uint32v', 'CheckSum',                     0 ],
  [ 'uint16v', 'Subsystem',                    0 ],
  [ 'uint16v', 'DllCharacteristics',           0 ],
  [ 'uint32v', 'SizeOfStackReserve',           0 ],
  [ 'uint32v', 'SizeOfStackCommit',            0 ],
  [ 'uint32v', 'SizeOfHeapReserve',            0 ],
  [ 'uint32v', 'SizeOfHeapCommit',             0 ],
  [ 'uint32v', 'LoaderFlags',                  0 ],
  [ 'uint32v', 'NumberOfRvaAndSizes',          0 ],
  [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new(
    [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ]
  )]
)
IMAGE_NT_OPTIONAL_HDR64_MAGIC =

typedef struct _IMAGE_OPTIONAL_HEADER64 { USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONGLONG ImageBase; ULONG SectionAlignment; ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Win32VersionValue; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory; } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240

0x20b
IMAGE_SIZEOF_NT_OPTIONAL64_HEADER =
240
IMAGE_OPTIONAL_HEADER64 =
Rex::Struct2::CStructTemplate.new(
  [ 'uint16v', 'Magic',                        0 ],
  [ 'uint8',   'MajorLinkerVersion',           0 ],
  [ 'uint8',   'MinorLinkerVersion',           0 ],
  [ 'uint32v', 'SizeOfCode',                   0 ],
  [ 'uint32v', 'SizeOfInitializeData',         0 ],
  [ 'uint32v', 'SizeOfUninitializeData',       0 ],
  [ 'uint32v', 'AddressOfEntryPoint',          0 ],
  [ 'uint32v', 'BaseOfCode',                   0 ],
  [ 'uint64v', 'ImageBase',                    0 ],
  [ 'uint32v', 'SectionAlignment',             0 ],
  [ 'uint32v', 'FileAlignment',                0 ],
  [ 'uint16v', 'MajorOperatingsystemVersion',  0 ],
  [ 'uint16v', 'MinorOperatingsystemVersion',  0 ],
  [ 'uint16v', 'MajorImageVersion',            0 ],
  [ 'uint16v', 'MinorImageVersion',            0 ],
  [ 'uint16v', 'MajorSubsystemVersion',        0 ],
  [ 'uint16v', 'MinorSubsystemVersion',        0 ],
  [ 'uint32v', 'Win32VersionValue',            0 ],
  [ 'uint32v', 'SizeOfImage',                  0 ],
  [ 'uint32v', 'SizeOfHeaders',                0 ],
  [ 'uint32v', 'CheckSum',                     0 ],
  [ 'uint16v', 'Subsystem',                    0 ],
  [ 'uint16v', 'DllCharacteristics',           0 ],
  [ 'uint64v', 'SizeOfStackReserve',           0 ],
  [ 'uint64v', 'SizeOfStackCommit',            0 ],
  [ 'uint64v', 'SizeOfHeapReserve',            0 ],
  [ 'uint64v', 'SizeOfHeapCommit',             0 ],
  [ 'uint32v', 'LoaderFlags',                  0 ],
  [ 'uint32v', 'NumberOfRvaAndSizes',          0 ],
  [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new(
    [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ],
    [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ]
  )]
)
IMAGE_SIZEOF_SECTION_HEADER =

typedef struct _IMAGE_SECTION_HEADER {

BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
union {
        DWORD   PhysicalAddress;
        DWORD   VirtualSize;
} Misc;
DWORD   VirtualAddress;
DWORD   SizeOfRawData;
DWORD   PointerToRawData;
DWORD   PointerToRelocations;
DWORD   PointerToLinenumbers;
WORD    NumberOfRelocations;
WORD    NumberOfLinenumbers;
DWORD   Characteristics;

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

#define IMAGE_SIZEOF_SECTION_HEADER 40

40
IMAGE_SECTION_HEADER =
Rex::Struct2::CStructTemplate.new(
  [ 'string',  'Name', 8,               '' ],
  [ 'uint32v', 'Misc',                   0 ],
  [ 'uint32v', 'VirtualAddress',         0 ],
  [ 'uint32v', 'SizeOfRawData',          0 ],
  [ 'uint32v', 'PointerToRawData',       0 ],
  [ 'uint32v', 'PointerToRelocations',   0 ],
  [ 'uint32v', 'NumberOfRelocations',    0 ],
  [ 'uint32v', 'NumberOfLineNumbers',    0 ],
  [ 'uint32v', 'Characteristics',        0 ]
)
IMAGE_SIZEOF_BASE_RELOCATION =

typedef struct _IMAGE_BASE_RELOCATION {

DWORD   VirtualAddress;
DWORD   SizeOfBlock;

// WORD TypeOffset; } IMAGE_BASE_RELOCATION; typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

#define IMAGE_SIZEOF_BASE_RELOCATION 8

8
IMAGE_BASE_RELOCATION =
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'VirtualAddress',         0 ],
  [ 'uint32v', 'SizeOfBlock',            0 ]
)
IMAGE_BASE_RELOCATION_TYPE_OFFSET =
Rex::Struct2::CStructTemplate.new(
  [ 'uint16v', 'TypeOffset',             0 ]
)
IMAGE_LOAD_CONFIG_DIRECTORY32 =

typedef struct

DWORD   Size;
DWORD   TimeDateStamp;
WORD    MajorVersion;
WORD    MinorVersion;
DWORD   GlobalFlagsClear;
DWORD   GlobalFlagsSet;
DWORD   CriticalSectionDefaultTimeout;
DWORD   DeCommitFreeBlockThreshold;
DWORD   DeCommitTotalFreeThreshold;
DWORD   LockPrefixTable;            // VA
DWORD   MaximumAllocationSize;
DWORD   VirtualMemoryThreshold;
DWORD   ProcessHeapFlags;
DWORD   ProcessAffinityMask;
WORD    CSDVersion;
WORD    Reserved1;
DWORD   EditList;                   // VA
DWORD   SecurityCookie;             // VA
DWORD   SEHandlerTable;             // VA
DWORD   SEHandlerCount;

IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;

Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'Size',                          0 ],
  [ 'uint32v', 'TimeDateStamp',                 0 ],
  [ 'uint16v', 'MajorVersion',                  0 ],
  [ 'uint16v', 'MinorVersion',                  0 ],
  [ 'uint32v', 'GlobalFlagsClear',              0 ],
  [ 'uint32v', 'GlobalFlagsSet',                0 ],
  [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
  [ 'uint32v', 'DeCommitFreeBlockThreshold',    0 ],
  [ 'uint32v', 'DeCommitTotalFreeThreshold',    0 ],
  [ 'uint32v', 'LockPrefixTable',               0 ],
  [ 'uint32v', 'MaximumAllocationSize',         0 ],
  [ 'uint32v', 'VirtualMemoryThreshold',        0 ],
  [ 'uint32v', 'ProcessHeapFlags',              0 ],
  [ 'uint32v', 'ProcessAffinityMask',           0 ],
  [ 'uint16v', 'CSDVersion',                    0 ],
  [ 'uint16v', 'Reserved1',                     0 ],
  [ 'uint32v', 'EditList',                      0 ],
  [ 'uint32v', 'SecurityCookie',                0 ],
  [ 'uint32v', 'SEHandlerTable',                0 ],
  [ 'uint32v', 'SEHandlerCount',                0 ]
)
IMAGE_LOAD_CONFIG_DIRECTORY64 =

typedef struct { ULONG Size; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG GlobalFlagsClear; ULONG GlobalFlagsSet; ULONG CriticalSectionDefaultTimeout; ULONGLONG DeCommitFreeBlockThreshold; ULONGLONG DeCommitTotalFreeThreshold; ULONGLONG LockPrefixTable; // VA ULONGLONG MaximumAllocationSize; ULONGLONG VirtualMemoryThreshold; ULONGLONG ProcessAffinityMask; ULONG ProcessHeapFlags; USHORT CSDVersion; USHORT Reserved1; ULONGLONG EditList; // VA ULONGLONG SecurityCookie; // VA ULONGLONG SEHandlerTable; // VA ULONGLONG SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;

Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'Size',                          0 ],
  [ 'uint32v', 'TimeDateStamp',                 0 ],
  [ 'uint16v', 'MajorVersion',                  0 ],
  [ 'uint16v', 'MinorVersion',                  0 ],
  [ 'uint32v', 'GlobalFlagsClear',              0 ],
  [ 'uint32v', 'GlobalFlagsSet',                0 ],
  [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
  [ 'uint64v', 'DeCommitFreeBlockThreshold',    0 ],
  [ 'uint64v', 'DeCommitTotalFreeThreshold',    0 ],
  [ 'uint64v', 'LockPrefixTable',               0 ],
  [ 'uint64v', 'MaximumAllocationSize',         0 ],
  [ 'uint64v', 'VirtualMemoryThreshold',        0 ],
  [ 'uint64v', 'ProcessAffinityMask',           0 ],
  [ 'uint32v', 'ProcessHeapFlags',              0 ],
  [ 'uint16v', 'CSDVersion',                    0 ],
  [ 'uint16v', 'Reserved1',                     0 ],
  [ 'uint64v', 'EditList',                      0 ],
  [ 'uint64v', 'SecurityCookie',                0 ],
  [ 'uint64v', 'SEHandlerTable',                0 ],
  [ 'uint64v', 'SEHandlerCount',                0 ]
)
IMAGE_LOAD_TLS_DIRECTORY32 =

typedef struct

DWORD   Size;
DWORD   TimeDateStamp;
WORD    MajorVersion;
WORD    MinorVersion;
DWORD   GlobalFlagsClear;
DWORD   GlobalFlagsSet;
DWORD   CriticalSectionDefaultTimeout;
DWORD   DeCommitFreeBlockThreshold;
DWORD   DeCommitTotalFreeThreshold;
DWORD   LockPrefixTable;            // VA
DWORD   MaximumAllocationSize;
DWORD   VirtualMemoryThreshold;
DWORD   ProcessHeapFlags;
DWORD   ProcessAffinityMask;
WORD    CSDVersion;
WORD    Reserved1;
DWORD   EditList;                   // VA
DWORD   SecurityCookie;             // VA
DWORD   SEHandlerTable;             // VA
DWORD   SEHandlerCount;

IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;

Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'Size',                          0 ],
  [ 'uint32v', 'TimeDateStamp',                 0 ],
  [ 'uint16v', 'MajorVersion',                  0 ],
  [ 'uint16v', 'MinorVersion',                  0 ],
  [ 'uint32v', 'GlobalFlagsClear',              0 ],
  [ 'uint32v', 'GlobalFlagsSet',                0 ],
  [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
  [ 'uint32v', 'DeCommitFreeBlockThreshold',    0 ],
  [ 'uint32v', 'DeCommitTotalFreeThreshold',    0 ],
  [ 'uint32v', 'LockPrefixTable',               0 ],
  [ 'uint32v', 'MaximumAllocationSize',         0 ],
  [ 'uint32v', 'VirtualMemoryThreshold',        0 ],
  [ 'uint32v', 'ProcessHeapFlags',              0 ],
  [ 'uint32v', 'ProcessAffinityMask',           0 ],
  [ 'uint16v', 'CSDVersion',                    0 ],
  [ 'uint16v', 'Reserved1',                     0 ],
  [ 'uint32v', 'EditList',                      0 ],
  [ 'uint32v', 'SecurityCookie',                0 ],
  [ 'uint32v', 'SEHandlerTable',                0 ],
  [ 'uint32v', 'SEHandlerCount',                0 ]
)
IMAGE_LOAD_TLS_DIRECTORY64 =

typedef struct { ULONG Size; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG GlobalFlagsClear; ULONG GlobalFlagsSet; ULONG CriticalSectionDefaultTimeout; ULONGLONG DeCommitFreeBlockThreshold; ULONGLONG DeCommitTotalFreeThreshold; ULONGLONG LockPrefixTable; // VA ULONGLONG MaximumAllocationSize; ULONGLONG VirtualMemoryThreshold; ULONGLONG ProcessAffinityMask; ULONG ProcessHeapFlags; USHORT CSDVersion; USHORT Reserved1; ULONGLONG EditList; // VA ULONGLONG SecurityCookie; // VA ULONGLONG SEHandlerTable; // VA ULONGLONG SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;

Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'Size',                          0 ],
  [ 'uint32v', 'TimeDateStamp',                 0 ],
  [ 'uint16v', 'MajorVersion',                  0 ],
  [ 'uint16v', 'MinorVersion',                  0 ],
  [ 'uint32v', 'GlobalFlagsClear',              0 ],
  [ 'uint32v', 'GlobalFlagsSet',                0 ],
  [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
  [ 'uint64v', 'DeCommitFreeBlockThreshold',    0 ],
  [ 'uint64v', 'DeCommitTotalFreeThreshold',    0 ],
  [ 'uint64v', 'LockPrefixTable',               0 ],
  [ 'uint64v', 'MaximumAllocationSize',         0 ],
  [ 'uint64v', 'VirtualMemoryThreshold',        0 ],
  [ 'uint64v', 'ProcessAffinityMask',           0 ],
  [ 'uint32v', 'ProcessHeapFlags',              0 ],
  [ 'uint16v', 'CSDVersion',                    0 ],
  [ 'uint16v', 'Reserved1',                     0 ],
  [ 'uint64v', 'EditList',                      0 ],
  [ 'uint64v', 'SecurityCookie',                0 ],
  [ 'uint64v', 'SEHandlerTable',                0 ],
  [ 'uint64v', 'SEHandlerCount',                0 ]
)
IMAGE_RUNTIME_FUNCTION_ENTRY_SZ =

typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY

DWORD BeginAddress;
DWORD EndAddress;
DWORD UnwindInfoAddress;

_IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;

12
IMAGE_RUNTIME_FUNCTION_ENTRY =
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'BeginAddress',                  0 ],
  [ 'uint32v', 'EndAddress',                    0 ],
  [ 'uint32v', 'UnwindInfoAddress',             0 ]
)
UNWIND_INFO_HEADER_SZ =
4
UNWIND_INFO_HEADER =
Rex::Struct2::CStructTemplate.new(
  [ 'uint8', 'VersionFlags',                  0 ],
  [ 'uint8', 'SizeOfProlog',                  0 ],
  [ 'uint8', 'CountOfCodes',                  0 ],
  [ 'uint8', 'FrameRegisterAndOffset',        0 ]
)
UWOP_PUSH_NONVOL =

1 node

0
UWOP_ALLOC_LARGE =

2 or 3 nodes

1
UWOP_ALLOC_SMALL =

1 node

2
UWOP_SET_FPREG =

1 node

3
UWOP_SAVE_NONVOL =

2 nodes

4
UWOP_SAVE_NONVOL_FAR =

3 nodes

5
UWOP_SAVE_XMM128 =

2 nodes

8
UWOP_SAVE_XMM128_FAR =

3 nodes

9
UWOP_PUSH_MACHFRAME =

1 node

10
UNW_FLAG_EHANDLER =
1
UNW_FLAG_UHANDLER =
2
UNW_FLAG_CHAININFO =
4

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#_config_headerObject

Returns the value of attribute _config_header.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _config_header
  @_config_header
end

#_dos_headerObject

Returns the value of attribute _dos_header.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _dos_header
  @_dos_header
end

#_exception_headerObject

Returns the value of attribute _exception_header.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _exception_header
  @_exception_header
end

#_exports_cacheObject

Returns the value of attribute _exports_cache.



1169
1170
1171
# File 'lib/rex/peparsey/pebase.rb', line 1169

def _exports_cache
  @_exports_cache
end

#_exports_cachedObject

Returns the value of attribute _exports_cached.



1169
1170
1171
# File 'lib/rex/peparsey/pebase.rb', line 1169

def _exports_cached
  @_exports_cached
end

#_file_headerObject

Returns the value of attribute _file_header.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _file_header
  @_file_header
end

#_imports_cacheObject

Returns the value of attribute _imports_cache.



1168
1169
1170
# File 'lib/rex/peparsey/pebase.rb', line 1168

def _imports_cache
  @_imports_cache
end

#_imports_cachedObject

Returns the value of attribute _imports_cached.



1168
1169
1170
# File 'lib/rex/peparsey/pebase.rb', line 1168

def _imports_cached
  @_imports_cached
end

#_isourceObject

instance stuff



1162
1163
1164
# File 'lib/rex/peparsey/pebase.rb', line 1162

def _isource
  @_isource
end

#_optional_headerObject

Returns the value of attribute _optional_header.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _optional_header
  @_optional_header
end

#_relocations_cacheObject

Returns the value of attribute _relocations_cache.



1170
1171
1172
# File 'lib/rex/peparsey/pebase.rb', line 1170

def _relocations_cache
  @_relocations_cache
end

#_relocations_cachedObject

Returns the value of attribute _relocations_cached.



1170
1171
1172
# File 'lib/rex/peparsey/pebase.rb', line 1170

def _relocations_cached
  @_relocations_cached
end

#_resources_cacheObject

Returns the value of attribute _resources_cache.



1171
1172
1173
# File 'lib/rex/peparsey/pebase.rb', line 1171

def _resources_cache
  @_resources_cache
end

#_resources_cachedObject

Returns the value of attribute _resources_cached.



1171
1172
1173
# File 'lib/rex/peparsey/pebase.rb', line 1171

def _resources_cached
  @_resources_cached
end

#_section_headersObject

Returns the value of attribute _section_headers.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _section_headers
  @_section_headers
end

#_tls_headerObject

Returns the value of attribute _tls_header.



1163
1164
1165
# File 'lib/rex/peparsey/pebase.rb', line 1163

def _tls_header
  @_tls_header
end

#hdrObject

Returns the value of attribute hdr.



1173
1174
1175
# File 'lib/rex/peparsey/pebase.rb', line 1173

def hdr
  @hdr
end

#header_sectionObject

Returns the value of attribute header_section.



1166
1167
1168
# File 'lib/rex/peparsey/pebase.rb', line 1166

def header_section
  @header_section
end

#image_baseObject

Returns the value of attribute image_base.



1166
1167
1168
# File 'lib/rex/peparsey/pebase.rb', line 1166

def image_base
  @image_base
end

#sectionsObject

Returns the value of attribute sections.



1166
1167
1168
# File 'lib/rex/peparsey/pebase.rb', line 1166

def sections
  @sections
end

Class Method Details

._align_offset(offset, alignment) ⇒ Object

Just a stupid routine to round an offset up to it’s alignment.

For example, you’re going to want this for FileAlignment and SectionAlignment, etc…



1152
1153
1154
1155
1156
# File 'lib/rex/peparsey/pebase.rb', line 1152

def self._align_offset(offset, alignment)
	offset += alignment - 1
	offset -= offset % alignment
	return offset
end

._parse_dos_header(rawdata) ⇒ Object



140
141
142
# File 'lib/rex/peparsey/pebase.rb', line 140

def self._parse_dos_header(rawdata)
	return DosHeader.new(rawdata)
end

._parse_file_header(rawdata) ⇒ Object



220
221
222
# File 'lib/rex/peparsey/pebase.rb', line 220

def self._parse_file_header(rawdata)
	return FileHeader.new(rawdata)
end

._parse_optional_header(rawdata) ⇒ Object



583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/rex/peparsey/pebase.rb', line 583

def self._parse_optional_header(rawdata)
	case rawdata.length
		# no optional header
		when 0
			return nil

		# good, good
		when IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
			return OptionalHeader32.new(rawdata)

		when IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
			return OptionalHeader64.new(rawdata)

		# bad, bad
		else
			raise OptionalHeaderError, "I don't know this header size, #{rawdata.length}", caller
	end

end

._parse_section_headers(rawdata) ⇒ Object



658
659
660
661
662
663
664
665
666
667
668
669
# File 'lib/rex/peparsey/pebase.rb', line 658

def self._parse_section_headers(rawdata)
	section_headers = [ ]
	size = IMAGE_SIZEOF_SECTION_HEADER
	numsections = rawdata.length / size

	numsections.times do |i|
		data = rawdata[i * size, size]
		section_headers << SectionHeader.new(data)
	end

	return section_headers
end

.new_from_file(filename, disk_backed = false) ⇒ Object



1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
# File 'lib/rex/peparsey/pebase.rb', line 1175

def self.new_from_file(filename, disk_backed = false)

	file = ::File.new(filename)
	file.binmode # windows... :\

	if disk_backed
		return self.new(ImageSource::Disk.new(file))
	else
		obj = new_from_string(file.read)
		file.close
		return obj
	end
end

.new_from_string(data) ⇒ Object



1189
1190
1191
# File 'lib/rex/peparsey/pebase.rb', line 1189

def self.new_from_string(data)
	return self.new(ImageSource::Memory.new(data))
end

Instance Method Details

#_find_section_by_rva(rva) ⇒ Object

Find a section by an RVA



1253
1254
1255
1256
1257
1258
1259
1260
1261
# File 'lib/rex/peparsey/pebase.rb', line 1253

def _find_section_by_rva(rva)
	all_sections.each do |section|
		if section.contains_rva?(rva)
			return section
		end
	end

	return nil
end

#_load_exception_directoryObject



1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
# File 'lib/rex/peparsey/pebase.rb', line 1115

def _load_exception_directory
	@exception   = []
	
	exception_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_EXCEPTION]
	rva             = exception_entry.v['VirtualAddress']
	size            = exception_entry.v['Size']
	
	return if (rva == 0)
	
	data = _isource.read(rva_to_file_offset(rva), size)
	
	case hdr.file.Machine
		when IMAGE_FILE_MACHINE_AMD64
			count = data.length / IMAGE_RUNTIME_FUNCTION_ENTRY_SZ
			
			count.times { |current|
				@exception << RuntimeFunctionEntry.new(self,
					data.slice!(0, IMAGE_RUNTIME_FUNCTION_ENTRY_SZ))
			}
		else
	end
	
	return @exception
end

#_load_exportsObject



1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
# File 'lib/rex/peparsey/pebase.rb', line 1397

def _load_exports

	#
	# Get the data directory entry, size, etc
	#
	exports_entry = _optional_header['DataDirectory'][0]
	rva           = exports_entry.v['VirtualAddress']
	size          = exports_entry.v['Size']

	return nil if size == 0

	#
	# Ok, so we have the data directory, now lets parse it
	#

	directory = IMAGE_EXPORT_DESCRIPTOR.make_struct
	directory.from_s(_isource.read(rva_to_file_offset(rva), IMAGE_EXPORT_DESCRIPTOR_SIZE))

	#
	# We can have nameless exports, so we need to do the whole
	# NumberOfFunctions NumberOfNames foo
	#
	num_functions = directory.v['NumberOfFunctions']
	num_names     = directory.v['NumberOfNames']

	dllname_rva   = directory.v['Name']
	dllname       = _isource.read_asciiz(rva_to_file_offset(dllname_rva))

	# FIXME Base, etc
	fun_off       = rva_to_file_offset(directory.v['AddressOfFunctions'])
	name_off      = rva_to_file_offset(directory.v['AddressOfNames'])
	ord_off       = rva_to_file_offset(directory.v['AddressOfNameOrdinals'])
	base          = directory.v['Base']

	# Allocate the list of names
	names = Array.new(num_functions)

	#
	# Iterate the names and name/ordinal list, getting the names
	# and storing them in the name list...
	#
	num_names.times do |i|
		name_rva = _isource.read(name_off + (i * 4), 4).unpack('V')[0]
		ordinal  = _isource.read(ord_off + (i * 2), 2).unpack('v')[0]
		name     = _isource.read_asciiz(rva_to_file_offset(name_rva))

		# store the exported name in the name list
		names[ordinal] = name
	end

	exports = ExportDirectory.new(dllname, [ ], base)

	#
	# Now just iterate the functions (rvas) list..
	#
	num_functions.times do |i|
		rva      = _isource.read(fun_off + (i * 4), 4).unpack('V')[0]

		# ExportEntry.new(name, ordinal, rva)
		exports.entries << ExportEntry.new(names[i], i + base, rva)
	end

	return exports
end

#_load_importsObject



1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
# File 'lib/rex/peparsey/pebase.rb', line 1326

def _load_imports
	#
	# Get the data directory entry, size, etc
	#
	imports_entry = _optional_header['DataDirectory'][1]
	rva           = imports_entry.v['VirtualAddress']
	size          = imports_entry.v['Size']

	return nil if size == 0

	#
	# Ok, so we have the data directory, now lets parse it
	#

	imports = [ ]

	descriptors_data = _isource.read(rva_to_file_offset(rva), size)

	while descriptors_data.length >= IMAGE_IMPORT_DESCRIPTOR_SIZE
		descriptor = IMAGE_IMPORT_DESCRIPTOR.make_struct
		descriptor.from_s(descriptors_data)
		descriptors_data = descriptor.leftover

		othunk = descriptor.v['OriginalFirstThunk']
		fthunk = descriptor.v['FirstThunk']

		break if fthunk == 0

		dllname = _isource.read_asciiz(rva_to_file_offset(descriptor.v['Name']))

		import = ImportDescriptor.new(dllname, [ ])

		# we prefer the Characteristics/OriginalFirstThunk...
		thunk_off = rva_to_file_offset(othunk == 0 ? fthunk : othunk)

		while (orgrva = _isource.read(thunk_off, 4).unpack('V')[0]) != 0
			hint = nil
			name = nil

			if (orgrva & IMAGE_ORDINAL_FLAG32) != 0
				hint = orgrva & 0xffff
			else
				foff = rva_to_file_offset(orgrva)
				hint = _isource.read(foff, 2).unpack('v')[0]
				name = _isource.read_asciiz(foff + 2)
			end

			import.entries << ImportEntry.new(name, hint)

			thunk_off += 4
		end

		imports << import
	end

	return imports
end

#_load_relocationsObject



1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
# File 'lib/rex/peparsey/pebase.rb', line 1473

def _load_relocations

	#
	# Get the data directory entry, size, etc
	#
	exports_entry = _optional_header['DataDirectory'][5]
	rva           = exports_entry.v['VirtualAddress']
	size          = exports_entry.v['Size']

	return nil if size == 0

	#
	# Ok, so we have the data directory, now lets parse it
	#

	dirdata = _isource.read(rva_to_file_offset(rva), size)

	relocdirs = [ ]

	while dirdata.length >= IMAGE_SIZEOF_BASE_RELOCATION
		header = IMAGE_BASE_RELOCATION.make_struct
		header.from_s(dirdata)
		dirdata = header.leftover

		numrelocs = (header.v['SizeOfBlock'] - IMAGE_SIZEOF_BASE_RELOCATION) / 2

		relocbase = header.v['VirtualAddress']

		relocdir = RelocationDirectory.new(relocbase, [ ])

		numrelocs.times do
			reloc = IMAGE_BASE_RELOCATION_TYPE_OFFSET.make_struct
			reloc.from_s(dirdata)
			dirdata = reloc.leftover

			typeoffset = reloc.v['TypeOffset']

			relocrva  = relocbase + (typeoffset & 0xfff)
			reloctype = (typeoffset >> 12) & 0xf

			relocdir.entries << RelocationEntry.new(relocrva, reloctype)
		end

		relocdirs << relocdir
	end

	return relocdirs
end

#_load_resourcesObject



1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
# File 'lib/rex/peparsey/pebase.rb', line 1535

def _load_resources
	#
	# Get the data directory entry, size, etc
	#
	rsrc_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_RESOURCE]
	rva        = rsrc_entry.v['VirtualAddress']
	size       = rsrc_entry.v['Size']

	return nil if size == 0

	#
	# Ok, so we have the data directory, now lets parse it
	#
	data = _isource.read(rva_to_file_offset(rva), size)

	self._resources_cache = {}
	_parse_resource_directory(data)
end

#_parse_config_headerObject

doesn’t seem to be used – not compatible with 64-bit def self._parse_config_header(rawdata) header = IMAGE_LOAD_CONFIG_DIRECTORY32.make_struct header.from_s(rawdata) ConfigHeader.new(header) end



847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
# File 'lib/rex/peparsey/pebase.rb', line 847

def _parse_config_header

	#
	# Get the data directory entry, size, etc
	#
	exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]
	rva           = exports_entry.v['VirtualAddress']
	size          = exports_entry.v['Size']

	return nil if size == 0

	#
	# Ok, so we have the data directory, now lets parse it
	#

	dirdata = _isource.read(rva_to_file_offset(rva), size)
	klass   = (ptr_64?) ? IMAGE_LOAD_CONFIG_DIRECTORY64 : IMAGE_LOAD_CONFIG_DIRECTORY32
	header  = klass.make_struct

	header.from_s(dirdata)

	@config = ConfigHeader.new(header)
end

#_parse_resource_directory(data, rname = 0, rvalue = 0x80000000, path = '0', pname = nil) ⇒ Object



1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
# File 'lib/rex/peparsey/pebase.rb', line 1554

def _parse_resource_directory(data, rname=0, rvalue=0x80000000, path='0', pname=nil)

	pname = _parse_resource_name(data, rname)
	if (path.scan('/').length == 1)
		if (pname !~ /^\d+/)
			path = "/" + pname
		else
			path = "/" + _resource_lookup( (rname & ~0x80000000).to_s)
		end
	end


	rvalue &= ~0x80000000
	vals  = data[rvalue, 16].unpack('VVvvvv')

	chars = vals[0]
	tdate = vals[1]
	vers  = "#{vals[2]}#{vals[3]}"
	count = vals[4] + vals[5]

	0.upto(count-1) do |i|

		ename, evalue = data[rvalue + 16 + ( i * 8), 8].unpack('VV')
		epath = path + '/' + i.to_s

		if (ename & 0x80000000 != 0)
			pname = _parse_resource_name(data, ename)
		end

		if (evalue & 0x80000000 != 0)
			# This is a subdirectory
			_parse_resource_directory(data, ename, evalue, epath, pname)
		else
			# This is an entry
			_parse_resource_entry(data, ename, evalue, epath, pname)
		end
	end

end

#_parse_resource_entry(data, rname, rvalue, path, pname) ⇒ Object



1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
# File 'lib/rex/peparsey/pebase.rb', line 1626

def _parse_resource_entry(data, rname, rvalue, path, pname)

	rva, size, code = data[rvalue, 12].unpack('VVV')
	lang = _parse_resource_name(data, rname)

	ent = ResourceEntry.new(
		self,
		path,
		lang,
		code,
		rva,
		size,
		pname
	)
	self._resources_cache[path] = ent
end

#_parse_resource_name(data, rname) ⇒ Object



1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
# File 'lib/rex/peparsey/pebase.rb', line 1643

def _parse_resource_name(data, rname)
	if (rname & 0x80000000 != 0)
		rname &= ~0x80000000
		unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ]
		unistr, trash = unistr.split(/\x00\x00/, 2)
		return unistr ? unistr.gsub(/\x00/, '') : nil
	end

	rname.to_s
end

#_parse_tls_headerObject



980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
# File 'lib/rex/peparsey/pebase.rb', line 980

def _parse_tls_header

	#
	# Get the data directory entry, size, etc
	#
	exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_TLS]
	rva           = exports_entry.v['VirtualAddress']
	size          = exports_entry.v['Size']

	return nil if size == 0

	#
	# Ok, so we have the data directory, now lets parse it
	#

	dirdata = _isource.read(rva_to_file_offset(rva), size)
	klass   = (ptr_64?) ? IMAGE_LOAD_TLS_DIRECTORY64 : IMAGE_LOAD_TLS_DIRECTORY32
	header  = klass.make_struct

	header.from_s(dirdata)

	@tls = TLSHeader.new(header)
end

#_resource_lookup(i) ⇒ Object



1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
# File 'lib/rex/peparsey/pebase.rb', line 1594

def _resource_lookup(i)
	tbl = {
		'1'      => 'RT_CURSOR',
		'2'      => 'RT_BITMAP',
		'3'      => 'RT_ICON',
		'4'      => 'RT_MENU',
		'5'      => 'RT_DIALOG',
		'6'      => 'RT_STRING',
		'7'      => 'RT_FONTDIR',
		'8'      => 'RT_FONT',
		'9'      => 'RT_ACCELERATORS',
		'10'     => 'RT_RCDATA',
		'11'     => 'RT_MESSAGETABLE',
		'12'     => 'RT_GROUP_CURSOR',
		'14'     => 'RT_GROUP_ICON',
		'16'     => 'RT_VERSION',
		'17'     => 'RT_DLGINCLUDE',
		'19'     => 'RT_PLUGPLAY',
		'20'     => 'RT_VXD',
		'21'     => 'RT_ANICURSOR',
		'22'     => 'RT_ANIICON',
		'23'     => 'RT_HTML',
		'24'     => 'RT_MANIFEST',
		'32767'  => 'RT_ERROR',
		'8192'   => 'RT_NEWRESOURCE',
		'8194'   => 'RT_NEWBITMAP',
		'8196'   => 'RT_NEWMENU',
		'8197'   => 'RT_NEWDIALOG'
	}
	tbl[i] || i
end

#closeObject



1193
1194
1195
# File 'lib/rex/peparsey/pebase.rb', line 1193

def close
	_isource.close
end

#configObject



872
873
874
875
# File 'lib/rex/peparsey/pebase.rb', line 872

def config
	_parse_config_header if @config.nil?
	@config
end

#exceptionObject



1141
1142
1143
1144
# File 'lib/rex/peparsey/pebase.rb', line 1141

def exception
	_load_exception_directory if @exception.nil?
	@exception
end

#exportsObject

We lazily parse the exports, and then cache it



1389
1390
1391
1392
1393
1394
1395
# File 'lib/rex/peparsey/pebase.rb', line 1389

def exports
	if !_exports_cached
		self._exports_cache  = _load_exports
		self._exports_cached = true
	end
	return _exports_cache
end

#file_offset_to_rva(foffset) ⇒ Object

Raises:



1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
# File 'lib/rex/peparsey/pebase.rb', line 1224

def file_offset_to_rva(foffset)
	if foffset < 0
		raise WtfError, "lame", caller
	end

	all_sections.each do |section|
		if section.contains_file_offset?(foffset)
			return section.file_offset_to_rva(foffset)
		end
	end

	raise WtfError, "wtf! #{foffset}", caller
end

#file_offset_to_vma(foffset) ⇒ Object



1238
1239
1240
# File 'lib/rex/peparsey/pebase.rb', line 1238

def file_offset_to_vma(foffset)
	return rva_to_vma(file_offset_to_rva(foffset))
end

#find_section_by_rva(rva) ⇒ Object



1262
1263
1264
1265
1266
1267
1268
1269
1270
# File 'lib/rex/peparsey/pebase.rb', line 1262

def find_section_by_rva(rva)
	section = _find_section_by_rva(rva)

	if !section
		raise WtfError, "Cannot find rva! #{rva}", caller
	end

	return section
end

#find_section_by_vma(vma) ⇒ Object

Find a section by a VMA



1275
1276
1277
# File 'lib/rex/peparsey/pebase.rb', line 1275

def find_section_by_vma(vma)
	return find_section_by_rva(vma_to_rva(vma))
end

#importsObject

We lazily parse the imports, and then cache it



1318
1319
1320
1321
1322
1323
1324
# File 'lib/rex/peparsey/pebase.rb', line 1318

def imports
	if !_imports_cached
		self._imports_cache  = _load_imports
		self._imports_cached = true
	end
	return _imports_cache
end

#read_asciiz_rva(rva) ⇒ Object



1301
1302
1303
# File 'lib/rex/peparsey/pebase.rb', line 1301

def read_asciiz_rva(rva)
	return find_section_by_rva(rva).read_asciiz_rva(rva)
end

#read_asciiz_vma(vma) ⇒ Object



1305
1306
1307
# File 'lib/rex/peparsey/pebase.rb', line 1305

def read_asciiz_vma(vma)
	return read_asciiz_rva(vma_to_rva(vma))
end

#read_rva(rva, length) ⇒ Object

Some convenient methods to read a vma/rva without having the section… (inefficent though I suppose…)



1293
1294
1295
# File 'lib/rex/peparsey/pebase.rb', line 1293

def read_rva(rva, length)
	return find_section_by_rva(rva).read_rva(rva, length)
end

#read_vma(vma, length) ⇒ Object



1297
1298
1299
# File 'lib/rex/peparsey/pebase.rb', line 1297

def read_vma(vma, length)
	return read_rva(vma_to_rva(vma), length)
end

#relocationsObject

Base relocations in the hizzy



1465
1466
1467
1468
1469
1470
1471
# File 'lib/rex/peparsey/pebase.rb', line 1465

def relocations
	if !_relocations_cached
		self._relocations_cache  = _load_relocations
		self._relocations_cached = true
	end
	return _relocations_cache
end

#resourcesObject

We lazily parse the resources, and then cache them



1526
1527
1528
1529
1530
1531
1532
1533
# File 'lib/rex/peparsey/pebase.rb', line 1526

def resources
	if !_resources_cached
		_load_resources
		self._resources_cached = true
	end

	return self._resources_cache
end

#rva_to_file_offset(rva) ⇒ Object

Raises:



1211
1212
1213
1214
1215
1216
1217
1218
# File 'lib/rex/peparsey/pebase.rb', line 1211

def rva_to_file_offset(rva)
	all_sections.each do |section|
		if section.contains_rva?(rva)
			return section.rva_to_file_offset(rva)
		end
	end
	raise WtfError, "wtf!", caller
end

#rva_to_vma(rva) ⇒ Object

Random rva, vma, file offset, section offset, etc conversion routines…



1203
1204
1205
# File 'lib/rex/peparsey/pebase.rb', line 1203

def rva_to_vma(rva)
	return rva + image_base
end

#tlsObject



1005
1006
1007
1008
# File 'lib/rex/peparsey/pebase.rb', line 1005

def tls
	_parse_config_header if @tls.nil?
	@tls
end

#update_checksumObject



1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
# File 'lib/rex/peparsey/pebase.rb', line 1654

def update_checksum
	off = _dos_header.e_lfanew + IMAGE_FILE_HEADER_SIZE + 0x40
	_isource.rawdata[off, 4] = [0].pack('V')

	rem = _isource.size % 4
	sum_me = ''
	sum_me << _isource.rawdata
	sum_me << "\x00" * (4 - rem) if rem > 0

	cksum = 0
	sum_me.unpack('V*').each { |el|
		cksum = (cksum & 0xffffffff) + (cksum >> 32) + el
		if cksum > 2**32
			cksum = (cksum & 0xffffffff) + (cksum >> 32)
		end
	}

	cksum = (cksum & 0xffff) + (cksum >> 16)
	cksum += (cksum >> 16)
	cksum &= 0xffff

	cksum += _isource.size

	_isource.rawdata[off, 4] = [cksum].pack('V')
end

#valid_rva?(rva) ⇒ Boolean

Returns:

  • (Boolean)


1279
1280
1281
# File 'lib/rex/peparsey/pebase.rb', line 1279

def valid_rva?(rva)
	_find_section_by_rva(rva) != nil
end

#valid_vma?(vma) ⇒ Boolean

Returns:

  • (Boolean)


1282
1283
1284
# File 'lib/rex/peparsey/pebase.rb', line 1282

def valid_vma?(vma)
	_find_section_by_rva(vma_to_rva(vma)) != nil
end

#vma_to_file_offset(vma) ⇒ Object



1220
1221
1222
# File 'lib/rex/peparsey/pebase.rb', line 1220

def vma_to_file_offset(vma)
	return rva_to_file_offset(vma_to_rva(vma))
end

#vma_to_rva(vma) ⇒ Object



1207
1208
1209
# File 'lib/rex/peparsey/pebase.rb', line 1207

def vma_to_rva(vma)
	return vma - image_base
end