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_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_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.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _config_header
  @_config_header
end

#_dos_headerObject

Returns the value of attribute _dos_header.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _dos_header
  @_dos_header
end

#_exception_headerObject

Returns the value of attribute _exception_header.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _exception_header
  @_exception_header
end

#_exports_cacheObject

Returns the value of attribute _exports_cache.



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

def _exports_cache
  @_exports_cache
end

#_exports_cachedObject

Returns the value of attribute _exports_cached.



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

def _exports_cached
  @_exports_cached
end

#_file_headerObject

Returns the value of attribute _file_header.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _file_header
  @_file_header
end

#_imports_cacheObject

Returns the value of attribute _imports_cache.



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

def _imports_cache
  @_imports_cache
end

#_imports_cachedObject

Returns the value of attribute _imports_cached.



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

def _imports_cached
  @_imports_cached
end

#_isourceObject

instance stuff



1144
1145
1146
# File 'lib/rex/peparsey/pebase.rb', line 1144

def _isource
  @_isource
end

#_optional_headerObject

Returns the value of attribute _optional_header.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _optional_header
  @_optional_header
end

#_relocations_cacheObject

Returns the value of attribute _relocations_cache.



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

def _relocations_cache
  @_relocations_cache
end

#_relocations_cachedObject

Returns the value of attribute _relocations_cached.



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

def _relocations_cached
  @_relocations_cached
end

#_resources_cacheObject

Returns the value of attribute _resources_cache.



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

def _resources_cache
  @_resources_cache
end

#_resources_cachedObject

Returns the value of attribute _resources_cached.



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

def _resources_cached
  @_resources_cached
end

#_section_headersObject

Returns the value of attribute _section_headers.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _section_headers
  @_section_headers
end

#_tls_headerObject

Returns the value of attribute _tls_header.



1145
1146
1147
# File 'lib/rex/peparsey/pebase.rb', line 1145

def _tls_header
  @_tls_header
end

#hdrObject

Returns the value of attribute hdr.



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

def hdr
  @hdr
end

#header_sectionObject

Returns the value of attribute header_section.



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

def header_section
  @header_section
end

#image_baseObject

Returns the value of attribute image_base.



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

def image_base
  @image_base
end

#sectionsObject

Returns the value of attribute sections.



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

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…



1134
1135
1136
1137
1138
# File 'lib/rex/peparsey/pebase.rb', line 1134

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



213
214
215
# File 'lib/rex/peparsey/pebase.rb', line 213

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

._parse_optional_header(rawdata) ⇒ Object



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

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



643
644
645
646
647
648
649
650
651
652
653
654
# File 'lib/rex/peparsey/pebase.rb', line 643

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



1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
# File 'lib/rex/peparsey/pebase.rb', line 1157

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



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

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



1235
1236
1237
1238
1239
1240
1241
1242
1243
# File 'lib/rex/peparsey/pebase.rb', line 1235

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



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

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



1379
1380
1381
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
# File 'lib/rex/peparsey/pebase.rb', line 1379

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



1308
1309
1310
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
# File 'lib/rex/peparsey/pebase.rb', line 1308

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



1455
1456
1457
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
# File 'lib/rex/peparsey/pebase.rb', line 1455

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



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

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



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

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



1536
1537
1538
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
# File 'lib/rex/peparsey/pebase.rb', line 1536

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



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

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



1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
# File 'lib/rex/peparsey/pebase.rb', line 1625

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



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

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



1576
1577
1578
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
# File 'lib/rex/peparsey/pebase.rb', line 1576

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



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

def close
  _isource.close
end

#configObject



857
858
859
860
# File 'lib/rex/peparsey/pebase.rb', line 857

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

#exceptionObject



1123
1124
1125
1126
# File 'lib/rex/peparsey/pebase.rb', line 1123

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

#exportsObject

We lazily parse the exports, and then cache it



1371
1372
1373
1374
1375
1376
1377
# File 'lib/rex/peparsey/pebase.rb', line 1371

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:



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

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



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

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

#find_section_by_rva(rva) ⇒ Object



1244
1245
1246
1247
1248
1249
1250
1251
1252
# File 'lib/rex/peparsey/pebase.rb', line 1244

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



1257
1258
1259
# File 'lib/rex/peparsey/pebase.rb', line 1257

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



1300
1301
1302
1303
1304
1305
1306
# File 'lib/rex/peparsey/pebase.rb', line 1300

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

#read_asciiz_rva(rva) ⇒ Object



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

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

#read_asciiz_vma(vma) ⇒ Object



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

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



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

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

#read_vma(vma, length) ⇒ Object



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

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

#relocationsObject

Base relocations in the hizzy



1447
1448
1449
1450
1451
1452
1453
# File 'lib/rex/peparsey/pebase.rb', line 1447

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



1508
1509
1510
1511
1512
1513
1514
1515
# File 'lib/rex/peparsey/pebase.rb', line 1508

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

  return self._resources_cache
end

#rva_to_file_offset(rva) ⇒ Object

Raises:



1193
1194
1195
1196
1197
1198
1199
1200
# File 'lib/rex/peparsey/pebase.rb', line 1193

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…



1185
1186
1187
# File 'lib/rex/peparsey/pebase.rb', line 1185

def rva_to_vma(rva)
  return rva + image_base
end

#tlsObject



988
989
990
991
# File 'lib/rex/peparsey/pebase.rb', line 988

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

#update_checksumObject



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

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)


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

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

#valid_vma?(vma) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#vma_to_file_offset(vma) ⇒ Object



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

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

#vma_to_rva(vma) ⇒ Object



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

def vma_to_rva(vma)
  return vma - image_base
end