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 =
64
IMAGE_DOS_HEADER =

Struct

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;
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 =

#define IMAGE_NT_SIGNATURE 0x00004550 // PE00

0x00004550
IMAGE_FILE_MACHINE_I386 =

#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.

0x014c
IMAGE_FILE_MACHINE_IA64 =

#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64

0x0200
IMAGE_FILE_MACHINE_ALPHA64 =

#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64

0x0284
IMAGE_FILE_MACHINE_AMD64 =

#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)

0x8664
IMAGE_FILE_MACHINE_ARM64 =

#define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64

0xaa64
IMAGE_FILE_HEADER_SIZE =

#define IMAGE_SIZEOF_FILE_HEADER 20

20+4
IMAGE_FILE_HEADER =

C struct defining the PE file header

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;
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_FILE_MACHINE_ARM64
]
IMAGE_ORDINAL_FLAG32 =
0x80000000
IMAGE_IMPORT_DESCRIPTOR_SIZE =
20
IMAGE_IMPORT_DESCRIPTOR =

Struct

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;
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'OriginalFirstThunk',           0 ],
  [ 'uint32v', 'TimeDateStamp',                0 ],
  [ 'uint32v', 'ForwarderChain',               0 ],
  [ 'uint32v', 'Name',                         0 ],
  [ 'uint32v', 'FirstThunk',                   0 ]
)
IMAGE_EXPORT_DESCRIPTOR_SIZE =

sizeof(struct _IMAGE_EXPORT_DESCRIPTOR)

40
IMAGE_EXPORT_DESCRIPTOR =

Struct defining the export table

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;
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 =
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 =

Struct

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
Rex::Struct2::CStructTemplate.new(
  [ 'uint32v', 'VirtualAddress',               0 ],
  [ 'uint32v', 'Size',                         0 ]
)
IMAGE_NT_OPTIONAL_HDR32_MAGIC =

Struct

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 =

#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240

0x20b
IMAGE_SIZEOF_NT_OPTIONAL64_HEADER =

#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b

240
IMAGE_OPTIONAL_HEADER64 =

Struct

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_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_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 =

#define IMAGE_SIZEOF_SECTION_HEADER 40

40
IMAGE_SECTION_HEADER =

Struct

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;
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 =

#define IMAGE_SIZEOF_BASE_RELOCATION 8

8
IMAGE_BASE_RELOCATION =

Struct

typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;
    DWORD   SizeOfBlock;
//  WORD    TypeOffset[1];
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_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 =

Struct

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 =

Struct

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 =

Struct

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 =

Struct

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 =

Exception directory

12
IMAGE_RUNTIME_FUNCTION_ENTRY =

Struct

typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {
    DWORD BeginAddress;
    DWORD EndAddress;
    DWORD UnwindInfoAddress;
} _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_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.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _config_header
  @_config_header
end

#_dos_headerObject

Returns the value of attribute _dos_header.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _dos_header
  @_dos_header
end

#_exception_headerObject

Returns the value of attribute _exception_header.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _exception_header
  @_exception_header
end

#_exports_cacheObject

Returns the value of attribute _exports_cache.



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

def _exports_cache
  @_exports_cache
end

#_exports_cachedObject

Returns the value of attribute _exports_cached.



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

def _exports_cached
  @_exports_cached
end

#_file_headerObject

Returns the value of attribute _file_header.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _file_header
  @_file_header
end

#_imports_cacheObject

Returns the value of attribute _imports_cache.



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

def _imports_cache
  @_imports_cache
end

#_imports_cachedObject

Returns the value of attribute _imports_cached.



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

def _imports_cached
  @_imports_cached
end

#_isourceObject

instance stuff



1147
1148
1149
# File 'lib/rex/peparsey/pebase.rb', line 1147

def _isource
  @_isource
end

#_optional_headerObject

Returns the value of attribute _optional_header.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _optional_header
  @_optional_header
end

#_relocations_cacheObject

Returns the value of attribute _relocations_cache.



1155
1156
1157
# File 'lib/rex/peparsey/pebase.rb', line 1155

def _relocations_cache
  @_relocations_cache
end

#_relocations_cachedObject

Returns the value of attribute _relocations_cached.



1155
1156
1157
# File 'lib/rex/peparsey/pebase.rb', line 1155

def _relocations_cached
  @_relocations_cached
end

#_resources_cacheObject

Returns the value of attribute _resources_cache.



1156
1157
1158
# File 'lib/rex/peparsey/pebase.rb', line 1156

def _resources_cache
  @_resources_cache
end

#_resources_cachedObject

Returns the value of attribute _resources_cached.



1156
1157
1158
# File 'lib/rex/peparsey/pebase.rb', line 1156

def _resources_cached
  @_resources_cached
end

#_section_headersObject

Returns the value of attribute _section_headers.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _section_headers
  @_section_headers
end

#_tls_headerObject

Returns the value of attribute _tls_header.



1148
1149
1150
# File 'lib/rex/peparsey/pebase.rb', line 1148

def _tls_header
  @_tls_header
end

#hdrObject

Returns the value of attribute hdr.



1158
1159
1160
# File 'lib/rex/peparsey/pebase.rb', line 1158

def hdr
  @hdr
end

#header_sectionObject

Returns the value of attribute header_section.



1151
1152
1153
# File 'lib/rex/peparsey/pebase.rb', line 1151

def header_section
  @header_section
end

#image_baseObject

Returns the value of attribute image_base.



1151
1152
1153
# File 'lib/rex/peparsey/pebase.rb', line 1151

def image_base
  @image_base
end

#sectionsObject

Returns the value of attribute sections.



1151
1152
1153
# File 'lib/rex/peparsey/pebase.rb', line 1151

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…



1137
1138
1139
1140
1141
# File 'lib/rex/peparsey/pebase.rb', line 1137

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

._parse_dos_header(rawdata) ⇒ Object



135
136
137
# File 'lib/rex/peparsey/pebase.rb', line 135

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

._parse_file_header(rawdata) ⇒ Object



216
217
218
# File 'lib/rex/peparsey/pebase.rb', line 216

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

._parse_optional_header(rawdata) ⇒ Object



574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# File 'lib/rex/peparsey/pebase.rb', line 574

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



646
647
648
649
650
651
652
653
654
655
656
657
# File 'lib/rex/peparsey/pebase.rb', line 646

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



1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
# File 'lib/rex/peparsey/pebase.rb', line 1160

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



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

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



1238
1239
1240
1241
1242
1243
1244
1245
1246
# File 'lib/rex/peparsey/pebase.rb', line 1238

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



1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
# File 'lib/rex/peparsey/pebase.rb', line 1100

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



1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
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
# File 'lib/rex/peparsey/pebase.rb', line 1382

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



1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
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
# File 'lib/rex/peparsey/pebase.rb', line 1311

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



1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
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
# File 'lib/rex/peparsey/pebase.rb', line 1458

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



1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
# File 'lib/rex/peparsey/pebase.rb', line 1520

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 ++



835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
# File 'lib/rex/peparsey/pebase.rb', line 835

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



1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
# File 'lib/rex/peparsey/pebase.rb', line 1539

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



1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
# File 'lib/rex/peparsey/pebase.rb', line 1611

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



1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
# File 'lib/rex/peparsey/pebase.rb', line 1628

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/n, 2)
    return unistr ? unistr.gsub(/\x00/n, '') : nil
  end

  rname.to_s
end

#_parse_tls_headerObject



966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
# File 'lib/rex/peparsey/pebase.rb', line 966

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



1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
# File 'lib/rex/peparsey/pebase.rb', line 1579

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



1178
1179
1180
# File 'lib/rex/peparsey/pebase.rb', line 1178

def close
  _isource.close
end

#configObject



860
861
862
863
# File 'lib/rex/peparsey/pebase.rb', line 860

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

#exceptionObject



1126
1127
1128
1129
# File 'lib/rex/peparsey/pebase.rb', line 1126

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

#exportsObject

We lazily parse the exports, and then cache it



1374
1375
1376
1377
1378
1379
1380
# File 'lib/rex/peparsey/pebase.rb', line 1374

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:



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

def file_offset_to_rva(foffset)
  if foffset < 0
    raise PeParseyError, "Offset should not be less than 0. The value is: #{foffset}", caller
  end

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

  raise PeParseyError, "No section contains file offset #{foffset}", caller
end

#file_offset_to_vma(foffset) ⇒ Object



1223
1224
1225
# File 'lib/rex/peparsey/pebase.rb', line 1223

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

#find_section_by_rva(rva) ⇒ Object



1247
1248
1249
1250
1251
1252
1253
1254
1255
# File 'lib/rex/peparsey/pebase.rb', line 1247

def find_section_by_rva(rva)
  section = _find_section_by_rva(rva)

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

  return section
end

#find_section_by_vma(vma) ⇒ Object

Find a section by a VMA



1260
1261
1262
# File 'lib/rex/peparsey/pebase.rb', line 1260

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



1303
1304
1305
1306
1307
1308
1309
# File 'lib/rex/peparsey/pebase.rb', line 1303

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

#read_asciiz_rva(rva) ⇒ Object



1286
1287
1288
# File 'lib/rex/peparsey/pebase.rb', line 1286

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

#read_asciiz_vma(vma) ⇒ Object



1290
1291
1292
# File 'lib/rex/peparsey/pebase.rb', line 1290

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…)



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

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

#read_vma(vma, length) ⇒ Object



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

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

#relocationsObject

Base relocations in the hizzy



1450
1451
1452
1453
1454
1455
1456
# File 'lib/rex/peparsey/pebase.rb', line 1450

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



1511
1512
1513
1514
1515
1516
1517
1518
# File 'lib/rex/peparsey/pebase.rb', line 1511

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

  return self._resources_cache
end

#rva_to_file_offset(rva) ⇒ Object

Raises:



1196
1197
1198
1199
1200
1201
1202
1203
# File 'lib/rex/peparsey/pebase.rb', line 1196

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 PeParseyError, "No section contains RVA", caller
end

#rva_to_vma(rva) ⇒ Object

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



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

def rva_to_vma(rva)
  return rva + image_base
end

#tlsObject



991
992
993
994
# File 'lib/rex/peparsey/pebase.rb', line 991

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

#update_checksumObject



1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
# File 'lib/rex/peparsey/pebase.rb', line 1639

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)


1264
1265
1266
# File 'lib/rex/peparsey/pebase.rb', line 1264

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

#valid_vma?(vma) ⇒ Boolean

Returns:

  • (Boolean)


1267
1268
1269
# File 'lib/rex/peparsey/pebase.rb', line 1267

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

#vma_to_file_offset(vma) ⇒ Object



1205
1206
1207
# File 'lib/rex/peparsey/pebase.rb', line 1205

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

#vma_to_rva(vma) ⇒ Object



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

def vma_to_rva(vma)
  return vma - image_base
end