"""
Win32 Platform Module
"""
# Copyright (C) 2007 Invisigoth - See LICENSE file for details
import os
import sys
import struct
import traceback
import platform
import PE
import vstruct
import vstruct.builder as vs_builder
import vstruct.defs.win32 as vs_win32
import vstruct.defs.windows as vs_windows
import vtrace
import vtrace.archs.i386 as v_i386
import vtrace.archs.amd64 as v_amd64
import vtrace.platforms.base as v_base
import envi
import envi.bits as e_bits
import envi.memory as e_mem
import envi.resolver as e_resolv
import envi.archs.i386 as e_i386
import envi.archs.amd64 as e_amd64
from ctypes import *
#from ctypes.wintypes import *
platdir = os.path.dirname(__file__)
kernel32 = None
dbghelp = None
psapi = None
ntdll = None
advapi32 = None
IsWow64Process = None
# Setup some ctypes helpers:
# NOTE: we don't use LPVOID because it can return None.
# c_size_t is the designated platform word width int.
LPVOID = c_size_t
HANDLE = LPVOID
SIZE_T = LPVOID
QWORD = c_ulonglong
DWORD = c_ulong
WORD = c_ushort
BOOL = c_ulong
BYTE = c_ubyte
NULL = 0
INFINITE = 0xffffffff
EXCEPTION_MAXIMUM_PARAMETERS = 15
# Debug Event Types
EXCEPTION_DEBUG_EVENT =1
CREATE_THREAD_DEBUG_EVENT =2
CREATE_PROCESS_DEBUG_EVENT =3
EXIT_THREAD_DEBUG_EVENT =4
EXIT_PROCESS_DEBUG_EVENT =5
LOAD_DLL_DEBUG_EVENT =6
UNLOAD_DLL_DEBUG_EVENT =7
OUTPUT_DEBUG_STRING_EVENT =8
RIP_EVENT =9
# Symbol Flags
SYMFLAG_VALUEPRESENT = 0x00000001
SYMFLAG_REGISTER = 0x00000008
SYMFLAG_REGREL = 0x00000010
SYMFLAG_FRAMEREL = 0x00000020
SYMFLAG_PARAMETER = 0x00000040
SYMFLAG_LOCAL = 0x00000080
SYMFLAG_CONSTANT = 0x00000100
SYMFLAG_EXPORT = 0x00000200
SYMFLAG_FORWARDER = 0x00000400
SYMFLAG_FUNCTION = 0x00000800
SYMFLAG_VIRTUAL = 0x00001000
SYMFLAG_THUNK = 0x00002000
SYMFLAG_TLSREL = 0x00004000
# Symbol Resolution Options
SYMOPT_CASE_INSENSITIVE = 0x00000001
SYMOPT_UNDNAME = 0x00000002
SYMOPT_DEFERRED_LOADS = 0x00000004
SYMOPT_NO_CPP = 0x00000008
SYMOPT_LOAD_LINES = 0x00000010
SYMOPT_OMAP_FIND_NEAREST = 0x00000020
SYMOPT_LOAD_ANYTHING = 0x00000040
SYMOPT_IGNORE_CVREC = 0x00000080
SYMOPT_NO_UNQUALIFIED_LOADS = 0x00000100
SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200
SYMOPT_EXACT_SYMBOLS = 0x00000400
SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x00000800
SYMOPT_IGNORE_NT_SYMPATH = 0x00001000
SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000
SYMOPT_PUBLICS_ONLY = 0x00004000
SYMOPT_NO_PUBLICS = 0x00008000
SYMOPT_AUTO_PUBLICS = 0x00010000
SYMOPT_NO_IMAGE_SEARCH = 0x00020000
SYMOPT_SECURE = 0x00040000
SYMOPT_NO_PROMPTS = 0x00080000
SYMOPT_OVERWRITE = 0x00100000
SYMOPT_DEBUG = 0x80000000
# Exception Types
EXCEPTION_WAIT_0 = 0x00000000L
EXCEPTION_ABANDONED_WAIT_0 = 0x00000080L
EXCEPTION_USER_APC = 0x000000C0L
EXCEPTION_TIMEOUT = 0x00000102L
EXCEPTION_PENDING = 0x00000103L
DBG_EXCEPTION_HANDLED = 0x00010001L
DBG_CONTINUE = 0x00010002L
EXCEPTION_SEGMENT_NOTIFICATION = 0x40000005L
DBG_TERMINATE_THREAD = 0x40010003L
DBG_TERMINATE_PROCESS = 0x40010004L
DBG_CONTROL_C = 0x40010005L
DBG_CONTROL_BREAK = 0x40010008L
DBG_COMMAND_EXCEPTION = 0x40010009L
EXCEPTION_GUARD_PAGE_VIOLATION = 0x80000001L
EXCEPTION_DATATYPE_MISALIGNMENT = 0x80000002L
EXCEPTION_BREAKPOINT = 0x80000003L
EXCEPTION_SINGLE_STEP = 0x80000004L
DBG_EXCEPTION_NOT_HANDLED = 0x80010001L
EXCEPTION_ACCESS_VIOLATION = 0xC0000005L
EXCEPTION_IN_PAGE_ERROR = 0xC0000006L
EXCEPTION_INVALID_HANDLE = 0xC0000008L
EXCEPTION_NO_MEMORY = 0xC0000017L
EXCEPTION_ILLEGAL_INSTRUCTION = 0xC000001DL
EXCEPTION_NONCONTINUABLE_EXCEPTION = 0xC0000025L
EXCEPTION_INVALID_DISPOSITION = 0xC0000026L
EXCEPTION_ARRAY_BOUNDS_EXCEEDED = 0xC000008CL
EXCEPTION_FLOAT_DENORMAL_OPERAND = 0xC000008DL
EXCEPTION_FLOAT_DIVIDE_BY_ZERO = 0xC000008EL
EXCEPTION_FLOAT_INEXACT_RESULT = 0xC000008FL
EXCEPTION_FLOAT_INVALID_OPERATION = 0xC0000090L
EXCEPTION_FLOAT_OVERFLOW = 0xC0000091L
EXCEPTION_FLOAT_STACK_CHECK = 0xC0000092L
EXCEPTION_FLOAT_UNDERFLOW = 0xC0000093L
EXCEPTION_INTEGER_DIVIDE_BY_ZERO = 0xC0000094L
EXCEPTION_INTEGER_OVERFLOW = 0xC0000095L
EXCEPTION_PRIVILEGED_INSTRUCTION = 0xC0000096L
EXCEPTION_STACK_OVERFLOW = 0xC00000FDL
EXCEPTION_CONTROL_C_EXIT = 0xC000013AL
EXCEPTION_FLOAT_MULTIPLE_FAULTS = 0xC00002B4L
EXCEPTION_FLOAT_MULTIPLE_TRAPS = 0xC00002B5L
EXCEPTION_REG_NAT_CONSUMPTION = 0xC00002C9L
# Context Info
CONTEXT_i386 = 0x00010000 # this assumes that i386 and
CONTEXT_i486 = 0x00010000 # i486 have identical context records
CONTEXT_AMD64 = 0x00100000 # For amd x64...
CONTEXT_CONTROL = 0x00000001L # SS:SP, CS:IP, FLAGS, BP
CONTEXT_INTEGER = 0x00000002L # AX, BX, CX, DX, SI, DI
CONTEXT_SEGMENTS = 0x00000004L # DS, ES, FS, GS
CONTEXT_FLOATING_POINT = 0x00000008L # 387 state
CONTEXT_DEBUG_REGISTERS = 0x00000010L # DB 0-3,6,7
CONTEXT_EXTENDED_REGISTERS = 0x00000020L # cpu specific extensions
CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS)
# Thread Permissions
THREAD_ALL_ACCESS = 0x001f03ff
PROCESS_ALL_ACCESS = 0x001f0fff
# Memory Permissions
PAGE_NOACCESS = 0x01
PAGE_READONLY = 0x02
PAGE_READWRITE = 0x04
PAGE_WRITECOPY = 0x08
PAGE_EXECUTE = 0x10
PAGE_EXECUTE_READ = 0x20
PAGE_EXECUTE_READWRITE = 0x40
PAGE_EXECUTE_WRITECOPY = 0x80
PAGE_GUARD = 0x100
PAGE_NOCACHE = 0x200
PAGE_WRITECOMBINE = 0x400
# Map win32 permissions to envi permissions
perm_lookup = {
PAGE_NOACCESS:0,
PAGE_READONLY:e_mem.MM_READ,
PAGE_READWRITE: e_mem.MM_READ | e_mem.MM_WRITE,
PAGE_WRITECOPY: e_mem.MM_READ | e_mem.MM_WRITE,
PAGE_EXECUTE: e_mem.MM_EXEC,
PAGE_EXECUTE_READ: e_mem.MM_EXEC | e_mem.MM_READ,
PAGE_EXECUTE_READWRITE: e_mem.MM_EXEC | e_mem.MM_READ | e_mem.MM_WRITE,
PAGE_EXECUTE_WRITECOPY: e_mem.MM_EXEC | e_mem.MM_READ | e_mem.MM_WRITE,
}
# To get win32 permssions from envi permissions
perm_rev_lookup = {
0:PAGE_NOACCESS,
e_mem.MM_READ:PAGE_READONLY,
e_mem.MM_READ|e_mem.MM_WRITE:PAGE_READWRITE,
e_mem.MM_EXEC:PAGE_EXECUTE,
e_mem.MM_EXEC|e_mem.MM_READ:PAGE_EXECUTE_READ,
e_mem.MM_EXEC|e_mem.MM_READ|e_mem.MM_WRITE:PAGE_EXECUTE_READWRITE,
}
# Memory States
MEM_COMMIT = 0x1000
MEM_FREE = 0x10000
MEM_RESERVE = 0x2000
# Memory Types
MEM_IMAGE = 0x1000000
MEM_MAPPED = 0x40000
MEM_PRIVATE = 0x20000
# Process Creation Flags
DEBUG_ONLY_THIS_PROCESS = 0x02
MAX_PATH=260
[docs]class MSR(Structure):
_fields_ = [
('msr', DWORD),
('value', QWORD),
]
# The enum of NtSystemDebugControl operations
SysDbgQueryModuleInformation = 0
SysDbgQueryTraceInformation = 1
SysDbgSetTracepoint = 2
SysDbgSetSpecialCall = 3
SysDbgClearSpecialCalls = 4
SysDbgQuerySpecialCalls = 5
SysDbgBreakPoint = 6
SysDbgQueryVersion = 7
SysDbgReadVirtual = 8
SysDbgWriteVirtual = 9
SysDbgReadPhysical = 10
SysDbgWritePhysical = 11
SysDbgReadControlSpace = 12
SysDbgWriteControlSpace = 13
SysDbgReadIoSpace = 14
SysDbgWriteIoSpace = 15
SysDbgReadMsr = 16
SysDbgWriteMsr = 17
SysDbgReadBusData = 18
SysDbgWriteBusData = 19
SysDbgCheckLowMemory = 20
SysDbgEnableKernelDebugger = 21
SysDbgDisableKernelDebugger = 22
SysDbgGetAutoKdEnable = 23
SysDbgSetAutoKdEnable = 24
SysDbgGetPrintBufferSize = 25
SysDbgSetPrintBufferSize = 26
SysDbgGetKdUmExceptionEnable = 27
SysDbgSetKdUmExceptionEnable = 28
SysDbgGetTriageDump = 29
SysDbgGetKdBlockEnable = 30
SysDbgSetKdBlockEnable = 31
SysDbgRegisterForUmBreakInfo = 32
SysDbgGetUmBreakPid = 33
SysDbgClearUmBreakPid = 34
SysDbgGetUmAttachPid = 35
SysDbgClearUmAttachPid = 36
[docs]def wrmsr(msrid, value):
m = MSR()
m.msr = msrid
m.value = value
mptr = addressof(m)
x = ntdll.NtSystemDebugControl(SysDbgWriteMsr, mptr, sizeof(m), 0, 0, 0)
if x != 0:
raise vtrace.PlatformException('NtSystemDebugControl Failed: 0x%.8x' % kernel32.GetLastError())
return 0
[docs]def rdmsr(msrid):
m = MSR()
m.msr = msrid
m.value = 0
mptr = addressof(m)
msize = sizeof(m)
x = ntdll.NtSystemDebugControl(SysDbgReadMsr, mptr, msize, mptr, msize, 0)
if x != 0:
raise vtrace.PlatformException('NtSystemDebugControl Failed: 0x%.8x' % kernel32.GetLastError())
return m.value
SC_MANAGER_ALL_ACCESS = 0xF003F
SC_MANAGER_CREATE_SERVICE = 0x0002
SC_MANAGER_CONNECT = 0x0001
SC_MANAGER_ENUMERATE_SERVICE = 0x0004
SC_MANAGER_LOCK = 0x0008
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
SC_ENUM_PROCESS_INFO = 0
SERVICE_WIN32 = 0x30
SERVICE_ACTIVE = 0x01
SERVICE_INNACTIVE = 0x02
SERVICE_STATE_ALL = 0x03
[docs]class SERVICE_STATUS_PROCESS(Structure):
_fields_ = [
('dwServiceType', DWORD),
('dwCurrentState', DWORD),
('dwControlsAccepted', DWORD),
('dwWin32ExitCode', DWORD),
('dwServiceSpecificExitCode',DWORD),
('dwCheckPoint', DWORD),
('dwWaitHint', DWORD),
('dwProcessId', DWORD),
('dwServiceFlags', DWORD)
]
[docs]class ENUM_SERVICE_STATUS_PROCESS(Structure):
_fields_ = [
('lpServiceName', c_wchar_p),
('lpDisplayName', c_wchar_p),
('ServiceStatusProcess', SERVICE_STATUS_PROCESS),
]
[docs]class EXCEPTION_RECORD(Structure):
_fields_ = [
("ExceptionCode", DWORD),
("ExceptionFlags", DWORD),
("ExceptionRecord", LPVOID),
("ExceptionAddress", LPVOID),
("NumberParameters", c_ulong),
("ExceptionInformation", LPVOID * EXCEPTION_MAXIMUM_PARAMETERS)
]
[docs]class EXCEPTION_DEBUG_INFO(Structure):
_fields_ = [
("ExceptionRecord", EXCEPTION_RECORD),
("FirstChance", c_ulong)
]
[docs]class CREATE_THREAD_DEBUG_INFO(Structure):
_fields_ = [
("Thread", HANDLE),
("ThreadLocalBase", LPVOID),
("StartAddress", LPVOID)
]
[docs]class CREATE_PROCESS_DEBUG_INFO(Structure):
_fields_ = [
("File", HANDLE),
("Process", HANDLE),
("Thread", HANDLE),
("BaseOfImage", LPVOID),
("DebugInfoFileOffset", c_ulong),
("DebugInfoSize", c_ulong),
("ThreadLocalBase", LPVOID),
("StartAddress", LPVOID),
("ImageName", LPVOID),
("Unicode", c_short),
]
[docs]class EXIT_THREAD_DEBUG_INFO(Structure):
_fields_ = [("ExitCode", c_ulong),]
[docs]class EXIT_PROCESS_DEBUG_INFO(Structure):
_fields_ = [("ExitCode", c_ulong),]
[docs]class LOAD_DLL_DEBUG_INFO(Structure):
_fields_ = [
("File", HANDLE),
("BaseOfDll", LPVOID),
("DebugInfoFileOffset", c_ulong),
("DebugInfoSize", c_ulong),
("ImageName", LPVOID),
("Unicode", c_ushort),
]
[docs]class UNLOAD_DLL_DEBUG_INFO(Structure):
_fields_ = [
("BaseOfDll", LPVOID),
]
[docs]class OUTPUT_DEBUG_STRING_INFO(Structure):
_fields_ = [
("DebugStringData", LPVOID),
("Unicode", c_ushort),
("DebugStringLength", c_ushort),
]
[docs]class RIP_INFO(Structure):
_fields_ = [
("Error", c_ulong),
("Type", c_ulong),
]
[docs]class DBG_EVENT_UNION(Union):
_fields_ = [ ("Exception",EXCEPTION_DEBUG_INFO),
("CreateThread", CREATE_THREAD_DEBUG_INFO),
("CreateProcessInfo", CREATE_PROCESS_DEBUG_INFO),
("ExitThread", EXIT_THREAD_DEBUG_INFO),
("ExitProcess", EXIT_PROCESS_DEBUG_INFO),
("LoadDll", LOAD_DLL_DEBUG_INFO),
("UnloadDll", UNLOAD_DLL_DEBUG_INFO),
("DebugString", OUTPUT_DEBUG_STRING_INFO),
("RipInfo", RIP_INFO)]
[docs]class DEBUG_EVENT(Structure):
_fields_ = [
("DebugEventCode", c_ulong),
("ProcessId", c_ulong),
("ThreadId", c_ulong),
("u", DBG_EVENT_UNION),
]
[docs]class FloatSavex86(Structure):
_fields_ = [("ControlWord", c_ulong),
("StatusWord", c_ulong),
("TagWord", c_ulong),
("ErrorOffset", c_ulong),
("ErrorSelector", c_ulong),
("DataOffset", c_ulong),
("DataSelector", c_ulong),
("RegisterSave", c_byte*80),
("Cr0NpxState", c_ulong),
]
[docs]class CONTEXTx64(Structure):
_fields_ = [
("P1Home",c_ulonglong),
("P2Home",c_ulonglong),
("P3Home",c_ulonglong),
("P4Home",c_ulonglong),
("P5Home",c_ulonglong),
("P6Home",c_ulonglong),
("ContextFlags", DWORD),
("MxCsr",DWORD),
("cs",WORD),
("ds",WORD),
("es",WORD),
("fs", WORD),
("gs",WORD),
("ss",WORD),
("eflags",DWORD),
("debug0",c_ulonglong),
("debug1",c_ulonglong),
("debug2",c_ulonglong),
("debug3",c_ulonglong),
("debug6",c_ulonglong),
("debug7",c_ulonglong),
("rax",c_ulonglong),
("rcx",c_ulonglong),
("rdx",c_ulonglong),
("rbx",c_ulonglong),
("rsp",c_ulonglong),
("rbp",c_ulonglong),
("rsi",c_ulonglong),
("rdi",c_ulonglong),
("r8",c_ulonglong),
("r9",c_ulonglong),
("r10",c_ulonglong),
("r11",c_ulonglong),
("r12",c_ulonglong),
("r13",c_ulonglong),
("r14",c_ulonglong),
("r15",c_ulonglong),
("rip",c_ulonglong),
("foo",c_ulonglong*200),
#union {
#XMM_SAVE_AREA32 FltSave,
#struct {
#M128A Header[2],
#M128A Legacy[8],
#M128A Xmm0,
#M128A Xmm1,
#M128A Xmm2,
#M128A Xmm3,
#M128A Xmm4,
#M128A Xmm5,
#M128A Xmm6,
#M128A Xmm7,
#M128A Xmm8,
#M128A Xmm9,
#M128A Xmm10,
#M128A Xmm11,
#M128A Xmm12,
#M128A Xmm13,
#M128A Xmm14,
#M128A Xmm15,
#},
#},
#M128A VectorRegister[26],
#(VectorControl,c_ulonglong),
#(DebugControl,c_ulonglong),
#(LastBranchToRip,c_ulonglong),
#(LastBranchFromRip,c_ulonglong),
#(LastExceptionToRip,c_ulonglong),
#(LastExceptionFromRip,c_ulonglong),
]
[docs] def regPostProcess(self):
pass
# Used for xmm registers
[docs]class M128A(Structure):
_fields_ = [
('Low', c_ulonglong),
('High', c_ulonglong),
]
[docs]class ExtendedXmmx86(Structure):
_fields_ = [
('Header', M128A * 2),
('Legacy', M128A * 8),
('_xmm0', M128A),
('_xmm1', M128A),
('_xmm2', M128A),
('_xmm3', M128A),
('_xmm4', M128A),
('_xmm5', M128A),
('_xmm6', M128A),
('_xmm7', M128A),
("Pad", c_byte * 224),
]
[docs]class CONTEXTx86(Structure):
_fields_ = [ ("ContextFlags", c_ulong),
("debug0", c_ulong),
("debug1", c_ulong),
("debug2", c_ulong),
("debug3", c_ulong),
("debug6", c_ulong),
("debug7", c_ulong),
("FloatSave", FloatSavex86),
("gs", c_ulong),
("fs", c_ulong),
("es", c_ulong),
("ds", c_ulong),
("edi", c_ulong),
("esi", c_ulong),
("ebx", c_ulong),
("edx", c_ulong),
("ecx", c_ulong),
("eax", c_ulong),
("ebp", c_ulong),
("eip", c_ulong),
("cs", c_ulong),
("eflags", c_ulong),
("esp", c_ulong),
("ss", c_ulong),
#("Extension", c_byte * 512),
('Extension', ExtendedXmmx86),
#M128A Header[2],
#M128A Legacy[8],
#M128A Xmm0,
#M128A Xmm1,
#M128A Xmm2,
#M128A Xmm3,
#M128A Xmm4,
#M128A Xmm5,
#M128A Xmm6,
#M128A Xmm7,
]
[docs] def regPostProcess(self):
self.xmm0 = (self.Extension._xmm0.High << 8) + self.Extension._xmm0.Low
self.xmm1 = (self.Extension._xmm1.High << 8) + self.Extension._xmm1.Low
self.xmm2 = (self.Extension._xmm2.High << 8) + self.Extension._xmm2.Low
self.xmm3 = (self.Extension._xmm3.High << 8) + self.Extension._xmm3.Low
self.xmm4 = (self.Extension._xmm4.High << 8) + self.Extension._xmm4.Low
self.xmm5 = (self.Extension._xmm5.High << 8) + self.Extension._xmm5.Low
self.xmm6 = (self.Extension._xmm6.High << 8) + self.Extension._xmm6.Low
self.xmm7 = (self.Extension._xmm7.High << 8) + self.Extension._xmm7.Low
[docs]class STARTUPINFO(Structure):
"""
Passed into CreateProcess
"""
_fields_ = [
("db", c_ulong),
("Reserved", c_char_p),
("Desktop", c_char_p),
("Title", c_char_p),
("X", c_ulong),
("Y", c_ulong),
("XSize", c_ulong),
("YSize", c_ulong),
("XCountChars", c_ulong),
("YCountChars", c_ulong),
("FillAttribute", c_ulong),
("Flags", c_ulong),
("ShowWindow", c_ushort),
("Reserved2", c_ushort),
("Reserved3", LPVOID),
("StdInput", c_ulong),
("StdOutput", c_ulong),
("StdError", c_ulong),
]
[docs]class SYMBOL_INFO(Structure):
_fields_ = [
("SizeOfStruct", c_ulong),
("TypeIndex", c_ulong),
("Reserved1", c_ulonglong),
("Reserved2", c_ulonglong),
("Index", c_ulong),
("Size", c_ulong),
("ModBase", c_ulonglong),
("Flags", c_ulong),
("Value", c_ulonglong),
("Address", c_ulonglong),
("Register", c_ulong),
("Scope", c_ulong),
("Tag", c_ulong),
("NameLen", c_ulong),
("MaxNameLen", c_ulong),
("Name", c_char * 2000), # MAX_SYM_NAME
]
[docs]class IMAGEHLP_MODULE64(Structure):
_fields_ = [
("SizeOfStruct", c_ulong),
("BaseOfImage", c_ulonglong),
("ImageSize", c_ulong),
("TimeDateStamp", c_ulong),
("CheckSum", c_ulong),
("NumSyms", c_ulong),
("SymType", c_ulong),
("ModuleName", c_char*32),
("ImageName", c_char*256),
("LoadedImageName", c_char*256),
("LoadedPdbName", c_char*256),
("CvSig", c_ulong),
("CvData", c_char*(MAX_PATH*3)),
("PdbSig", c_ulong),
("PdbSig70", c_char * 16), #GUID
("PdbAge", c_ulong),
("PdbUnmatched", c_ulong),
("DbgUnmatched", c_ulong),
("LineNumbers", c_ulong),
("GlobalSymbols", c_ulong),
("TypeInfo", c_ulong),
]
[docs]class IMAGEHLP_STACK_FRAME(Structure):
_fields_ = [
('InstructionOffset', QWORD),
('ReturnOffset', QWORD),
('FrameOffset', QWORD),
('StackOffset', QWORD),
('BackingStoreOffset', QWORD),
('FuncTableEntry', QWORD),
('Params', QWORD*4),
('Reserved', QWORD*5),
('Virtual', BOOL),
('Reserved2', DWORD),
]
IMAGE_DIRECTORY_ENTRY_EXPORT =0 # Export Directory
IMAGE_DIRECTORY_ENTRY_IMPORT =1 # Import Directory
IMAGE_DIRECTORY_ENTRY_RESOURCE =2 # Resource Directory
IMAGE_DIRECTORY_ENTRY_EXCEPTION =3 # Exception Directory
IMAGE_DIRECTORY_ENTRY_SECURITY =4 # Security Directory
IMAGE_DIRECTORY_ENTRY_BASERELOC =5 # Base Relocation Table
IMAGE_DIRECTORY_ENTRY_DEBUG =6 # Debug Directory
IMAGE_DIRECTORY_ENTRY_COPYRIGHT =7 # (X86 usage)
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE =7 # Architecture Specific Data
IMAGE_DIRECTORY_ENTRY_GLOBALPTR =8 # RVA of GP
IMAGE_DIRECTORY_ENTRY_TLS =9 # TLS Directory
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG =10 # Load Configuration Directory
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT =11 # Bound Import Directory in headers
IMAGE_DIRECTORY_ENTRY_IAT =12 # Import Address Table
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT =13 # Delay Load Import Descriptors
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR =14 # COM Runtime descriptor
IMAGE_DEBUG_TYPE_UNKNOWN =0
IMAGE_DEBUG_TYPE_COFF =1
IMAGE_DEBUG_TYPE_CODEVIEW =2
IMAGE_DEBUG_TYPE_FPO =3
IMAGE_DEBUG_TYPE_MISC =4
IMAGE_DEBUG_TYPE_EXCEPTION =5
IMAGE_DEBUG_TYPE_FIXUP =6
IMAGE_DEBUG_TYPE_OMAP_TO_SRC =7
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC =8
IMAGE_DEBUG_TYPE_BORLAND =9
IMAGE_DEBUG_TYPE_RESERVED10 =10
IMAGE_DEBUG_TYPE_CLSID =11
SSRVOPT_CALLBACK = 0x0001
SSRVOPT_DWORD = 0x0002
SSRVOPT_DWORDPTR = 0x0004
SSRVOPT_GUIDPTR = 0x0008
SSRVOPT_OLDGUIDPTR = 0x0010
SSRVOPT_UNATTENDED = 0x0020
SSRVOPT_NOCOPY = 0x0040
SSRVOPT_PARENTWIN = 0x0080
SSRVOPT_PARAMTYPE = 0x0100
SSRVOPT_SECURE = 0x0200
SSRVOPT_TRACE = 0x0400
SSRVOPT_SETCONTEXT = 0x0800
SSRVOPT_PROXY = 0x1000
SSRVOPT_DOWNSTREAM_STORE = 0x2000
TI_GET_SYMTAG = 0
TI_GET_SYMNAME = 1
TI_GET_LENGTH = 2
TI_GET_TYPE = 3
TI_GET_TYPEID = 4
TI_GET_BASETYPE = 5
TI_GET_ARRAYINDEXTYPEID = 6
TI_FINDCHILDREN = 7
TI_GET_DATAKIND = 8
TI_GET_ADDRESSOFFSET = 9
TI_GET_OFFSET = 10
TI_GET_VALUE = 11
TI_GET_COUNT = 12
TI_GET_CHILDRENCOUNT = 13
TI_GET_BITPOSITION = 14
TI_GET_VIRTUALBASECLASS = 15
TI_GET_VIRTUALTABLESHAPEID = 16
TI_GET_VIRTUALBASEPOINTEROFFSET = 17
TI_GET_CLASSPARENTID = 18
TI_GET_NESTED = 19
TI_GET_SYMINDEX = 20
TI_GET_LEXICALPARENT = 21
TI_GET_ADDRESS = 22
TI_GET_THISADJUST = 23
TI_GET_UDTKIND = 24
TI_IS_EQUIV_TO = 25
TI_GET_CALLING_CONVENTION = 26
SymTagNull = 0
SymTagExe = 1
SymTagCompiland = 2
SymTagCompilandDetails = 3
SymTagCompilandEnv = 4
SymTagFunction = 5
SymTagBlock = 6
SymTagData = 7
SymTagAnnotation = 8
SymTagLabel = 9
SymTagPublicSymbol = 10
SymTagUDT = 11
SymTagEnum = 12
SymTagFunctionType = 13
SymTagPointerType = 14
SymTagArrayType = 15
SymTagBaseType = 16
SymTagTypedef = 17
SymTagBaseClass = 18
SymTagFriend = 19
SymTagFunctionArgType = 20
SymTagFuncDebugStart = 21
SymTagFuncDebugEnd = 22
SymTagUsingNamespace = 23
SymTagVTableShape = 24
SymTagVTable = 25
SymTagCustom = 26
SymTagThunk = 27
SymTagCustomType = 28
SymTagManagedType = 29
SymTagDimension = 30
SymTagMax = 31
[docs]class IMAGE_DEBUG_DIRECTORY(Structure):
_fields_ = [
("Characteristics", c_ulong),
("TimeDateStamp", c_ulong),
("MajorVersion", c_ushort),
("MinorVersion", c_ushort),
("Type", c_ulong),
("SizeOfData", c_ulong),
("AddressOfRawData", c_ulong),
("PointerToRawData", c_ulong),
]
NT_LIST_HANDLES = 16
ACCESS_MASK = DWORD
[docs]class SYSTEM_HANDLE(Structure):
_fields_ = [
('ProcessID' , c_ulong),
('HandleType' , c_byte),
('Flags' , c_byte),
('HandleNumber' , c_ushort),
('KernelAddress' , LPVOID),
('GrantedAccess' , ACCESS_MASK),
]
PSYSTEM_HANDLE = POINTER(SYSTEM_HANDLE)
# OBJECT_INFORMATION_CLASS
ObjectBasicInformation = 0
ObjectNameInformation = 1
ObjectTypeInformation = 2
ObjectAllTypesInformation = 3
ObjectHandleInformation = 4
# ProcessInformationClass
ProcessBasicInformation = 0 # Get pointer to PEB
ProcessDebugPort = 7 # Get DWORD_PTR to debug port number
ProcessWow64Information = 26 # Get WOW64 status
# FIXME may be more reliable to use this! \|/
ProcessImageFileName = 27 # Get a UNICODE_STRING of the filename
ProcessExecuteFlags = 34 # Get DWORD of execute status (including DEP) (bug: your process only)
[docs]class UNICODE_STRING(Structure):
_fields_ = (
("Length",c_ushort),
("MaximumLength", c_ushort),
("Buffer", c_wchar_p)
)
PUNICODE_STRING = POINTER(UNICODE_STRING)
object_type_map = {
"File":vtrace.FD_FILE,
"Directory":vtrace.FD_FILE,
"Event":vtrace.FD_EVENT,
"KeyedEvent":vtrace.FD_EVENT,
"Mutant":vtrace.FD_LOCK,
"Semaphore":vtrace.FD_LOCK,
"Key":vtrace.FD_REGKEY,
"Port":vtrace.FD_UNKNOWN,
"Section":vtrace.FD_UNKNOWN,
"IoCompletion":vtrace.FD_UNKNOWN,
"Desktop":vtrace.FD_UNKNOWN,
"WindowStation":vtrace.FD_UNKNOWN,
}
[docs]class LUID(Structure):
_fields_ = (
("LowPart", c_ulong),
("HighPart", c_ulong)
)
[docs]class TOKEN_PRIVILEGES(Structure):
# This isn't really universal, more just for one priv use
_fields_ = (
("PrivilegeCount", c_ulong), # Always one
("Privilege", LUID),
("PrivilegeAttribute", c_ulong)
)
# All platforms must be able to import this module (for exceptions etc..)
# (do this stuff *after* we define some types...)
if sys.platform == "win32":
kernel32 = windll.kernel32
# We need to inform some of the APIs about their args
kernel32.OpenProcess.argtypes = [DWORD, BOOL, DWORD]
kernel32.OpenProcess.restype = HANDLE
kernel32.CreateProcessA.argtypes = [LPVOID, c_char_p, LPVOID, LPVOID, c_uint, DWORD, LPVOID, LPVOID, LPVOID, LPVOID]
kernel32.ReadProcessMemory.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T, LPVOID]
kernel32.WriteProcessMemory.argtypes = [HANDLE, LPVOID, c_char_p, SIZE_T, LPVOID]
kernel32.GetThreadContext.argtypes = [HANDLE, LPVOID]
kernel32.SetThreadContext.argtypes = [HANDLE, LPVOID]
kernel32.CreateRemoteThread.argtypes = [HANDLE, LPVOID, SIZE_T, LPVOID, LPVOID, DWORD, LPVOID]
kernel32.SuspendThread.argtypes = [HANDLE,]
kernel32.ResumeThread.argtypes = [HANDLE,]
kernel32.VirtualQueryEx.argtypes = [HANDLE, LPVOID, LPVOID, SIZE_T]
kernel32.DebugBreakProcess.argtypes = [HANDLE,]
kernel32.CloseHandle.argtypes = [HANDLE,]
kernel32.GetLogicalDriveStringsA.argtypes = [DWORD, LPVOID]
kernel32.TerminateProcess.argtypes = [HANDLE, DWORD]
kernel32.VirtualProtectEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, LPVOID]
kernel32.VirtualAllocEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD, DWORD]
kernel32.VirtualFreeEx.argtypes = [HANDLE, LPVOID, SIZE_T, DWORD]
kernel32.DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPVOID, DWORD, DWORD, DWORD]
kernel32.SetEvent.argtypes = [HANDLE, ]
IsWow64Process = getattr(kernel32, 'IsWow64Process', None)
if IsWow64Process != None:
IsWow64Process.argtypes = [HANDLE, LPVOID]
psapi = windll.psapi
psapi.GetModuleFileNameExW.argtypes = [HANDLE, HANDLE, LPVOID, DWORD]
psapi.GetMappedFileNameW.argtypes = [HANDLE, LPVOID, LPVOID, DWORD]
ntdll = windll.ntdll
ntdll.NtQuerySystemInformation.argtypes = [DWORD, LPVOID, DWORD, LPVOID]
ntdll.NtQueryObject.argtypes = [HANDLE, DWORD, c_void_p, DWORD, LPVOID]
ntdll.NtQueryInformationProcess.argtypes = [HANDLE, DWORD, c_void_p, DWORD, LPVOID]
ntdll.NtSystemDebugControl.restype = SIZE_T
try:
SYMCALLBACK = WINFUNCTYPE(BOOL, POINTER(SYMBOL_INFO), c_ulong, LPVOID)
PDBCALLBACK = WINFUNCTYPE(BOOL, c_char_p, LPVOID)
arch_name = envi.getCurrentArch()
symsrv = windll.LoadLibrary(os.path.join(platdir, "windll", arch_name, "symsrv.dll"))
dbghelp = windll.LoadLibrary(os.path.join(platdir, "windll", arch_name, "dbghelp.dll"))
dbghelp.SymInitialize.argtypes = [HANDLE, c_char_p, BOOL]
dbghelp.SymInitialize.restype = BOOL
dbghelp.SymSetOptions.argtypes = [DWORD]
dbghelp.SymSetOptions.restype = DWORD
dbghelp.SymCleanup.argtypes = [HANDLE]
dbghelp.SymCleanup.restype = BOOL
dbghelp.SymLoadModule64.argtypes = [HANDLE, HANDLE, c_char_p, c_char_p, QWORD, DWORD]
dbghelp.SymLoadModule64.restype = QWORD
dbghelp.SymGetModuleInfo64.argtypes = [HANDLE, QWORD, POINTER(IMAGEHLP_MODULE64)]
dbghelp.SymSetContext.restype = BOOL
dbghelp.SymSetContext.argtypes = [ HANDLE, POINTER(IMAGEHLP_STACK_FRAME), LPVOID ]
dbghelp.SymGetModuleInfo64.restype = BOOL
dbghelp.SymEnumSymbols.argtypes = [HANDLE, QWORD, c_char_p, SYMCALLBACK, LPVOID]
dbghelp.SymEnumSymbols.restype = BOOL
dbghelp.SymEnumTypes.argtypes = [HANDLE, QWORD, SYMCALLBACK, LPVOID]
dbghelp.SymEnumTypes.restype = BOOL
dbghelp.SymGetTypeInfo.argtypes = [HANDLE, QWORD, DWORD, DWORD, c_void_p]
dbghelp.SymGetTypeInfo.restype = BOOL
dbghelp.SymFromAddr.argtypes = [HANDLE, QWORD, POINTER(QWORD), POINTER(SYMBOL_INFO) ]
except Exception, e:
print "WARNING: Failed to import dbghelp/symsrv: %s" % e
advapi32 = windll.advapi32
advapi32.LookupPrivilegeValueA.argtypes = [LPVOID, c_char_p, LPVOID]
advapi32.OpenProcessToken.argtypes = [HANDLE, DWORD, HANDLE]
advapi32.AdjustTokenPrivileges.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID, LPVOID]
advapi32.OpenSCManagerA.argtypes = [ LPVOID, LPVOID, DWORD ]
advapi32.OpenSCManagerA.restype = HANDLE
advapi32.EnumServicesStatusExW.argtypes = [ HANDLE,
LPVOID,
DWORD,
DWORD,
LPVOID,
DWORD,
LPVOID,
LPVOID,
LPVOID,
LPVOID ]
advapi32.EnumServicesStatusExW.restype = BOOL
advapi32.CloseServiceHandle.argtypes = [ HANDLE, ]
advapi32.CloseServiceHandle.restype = BOOL
advapi32.GetTokenInformation.argtypes = [HANDLE, DWORD, LPVOID, DWORD, LPVOID]
advapi32.GetTokenInformation.restype = BOOL
[docs]def getServicesList():
'''
Get a list of (pid, servicename, displayname) tuples for the
currently running services.
'''
ret = []
scmh = advapi32.OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE)
try:
dwSvcSize = DWORD(0)
dwSvcCount = DWORD(0)
advapi32.EnumServicesStatusExW( scmh,
SC_ENUM_PROCESS_INFO,
SERVICE_WIN32,
SERVICE_ACTIVE,
NULL,
0,
addressof(dwSvcSize),
addressof(dwSvcCount),
NULL,
NULL)
buf = create_string_buffer(dwSvcSize.value)
#print 'NEEDED',dwSvcSize
#print 'COUNT',dwSvcCount
advapi32.EnumServicesStatusExW( scmh,
SC_ENUM_PROCESS_INFO,
SERVICE_WIN32,
SERVICE_ACTIVE,
addressof(buf),
dwSvcSize.value,
addressof(dwSvcSize),
addressof(dwSvcCount),
NULL,
NULL)
#p = POINTER(ENUM_SERVICE_STATUS_PROCESS)(addressof(buf))
p = cast(buf, POINTER(ENUM_SERVICE_STATUS_PROCESS))
for i in xrange(dwSvcCount.value):
pid = p[i].ServiceStatusProcess.dwProcessId
name = p[i].lpServiceName
descr = p[i].lpDisplayName
ret.append((pid, name, descr))
finally:
advapi32.CloseServiceHandle(scmh)
return ret
x = '''
BOOL WINAPI EnumServicesStatusEx(
__in SC_HANDLE hSCManager,
__in SC_ENUM_TYPE InfoLevel,
__in DWORD dwServiceType,
__in DWORD dwServiceState,
__out_opt LPBYTE lpServices,
__in DWORD cbBufSize,
__out LPDWORD pcbBytesNeeded,
__out LPDWORD lpServicesReturned,
__inout_opt LPDWORD lpResumeHandle,
__in_opt LPCTSTR pszGroupName
);
'''
SE_PRIVILEGE_ENABLED = 0x00000002
TOKEN_ADJUST_PRIVILEGES = 0x00000020
TOKEN_QUERY = 0x00000008
dbgprivdone = False
# TOKEN_INFORMATION_CLASS
TokenUser = 1
TokenGroups = 2
TokenPrivileges = 3
TokenOwner = 4
TokenPrimaryGroup = 5
TokenDefaultDacl = 6
TokenSource = 7
TokenType = 8
TokenImpersonationLevel = 9
TokenStatistics = 10
TokenRestrictedSids = 11
TokenSessionId = 12
TokenGroupsAndPrivileges = 13
TokenSessionReference = 14
TokenSandBoxInert = 15
TokenAuditPolicy = 16
TokenOrigin = 17
TokenElevationType = 18
TokenLinkedToken = 19
TokenElevation = 20
TokenHasRestrictions = 21
TokenAccessInformation = 22
TokenVirtualizationAllowed = 23
TokenVirtualizationEnabled = 24
TokenIntegrityLevel = 25
TokenUIAccess = 26
TokenMandatoryPolicy = 27
TokenLogonSid = 28
MaxTokenInfoClass = 29
# TOKEN_ELEVATION_TYPE
TokenElevationTypeDefault = 1
TokenElevationTypeFull = 2
TokenElevationTypeLimited = 3
[docs]def getTokenElevationType(handle=-1):
token = HANDLE(0)
etype = DWORD(0)
outsize = DWORD(0)
if not advapi32.OpenProcessToken(handle, TOKEN_QUERY, addressof(token)):
raise Exception('Invalid Process Handle: %d' % handle)
advapi32.GetTokenInformation(token, TokenElevationType, addressof(etype), 4, addressof(outsize))
return etype.value
if __name__ == '__main__':
print getTokenElevationType()
[docs]def getDebugPrivileges():
tokprivs = TOKEN_PRIVILEGES()
dbgluid = LUID()
token = HANDLE(0)
if not advapi32.LookupPrivilegeValueA(0, "seDebugPrivilege", addressof(dbgluid)):
print "LookupPrivilegeValue Failed: %d" % kernel32.GetLastError()
return False
if not advapi32.OpenProcessToken(-1, TOKEN_ADJUST_PRIVILEGES, addressof(token)):
print "kernel32.OpenProcessToken Failed: %d" % kernel32.GetLastError()
return False
tokprivs.PrivilegeCount = 1
tokprivs.Privilege = dbgluid
tokprivs.PrivilegeAttribute = SE_PRIVILEGE_ENABLED
if not advapi32.AdjustTokenPrivileges(token, 0, addressof(tokprivs), 0, 0, 0):
kernel32.CloseHandle(token)
print "AdjustTokenPrivileges Failed: %d" % kernel32.GetLastError()
return False
kernel32.CloseHandle(token)
[docs]def buildFindChildrenParams(count):
class TI_FINDCHILDREN_PARAMS(Structure):
_fields_ = [ ('Count', c_ulong), ('Start', c_ulong), ("Children",c_ulong * count),]
tif = TI_FINDCHILDREN_PARAMS()
tif.Count = count
return tif
[docs]def raiseWin32Error(name):
raise vtrace.PlatformException("Win32 Error %s failed: %s" % (name,kernel32.GetLastError()))
[docs]def GetModuleFileNameEx(phandle, mhandle):
buf = create_unicode_buffer(1024)
psapi.GetModuleFileNameExW(phandle, mhandle, addressof(buf), 1024)
return buf.value
av_einfo_perms = [e_mem.MM_READ, e_mem.MM_WRITE, None, None, None, None, None, None, e_mem.MM_EXEC]
[docs]class WindowsMixin:
"""
A mixin to handle all non-arch specific win32 stuff.
"""
def __init__(self):
self.casesens = False
self.phandle = None
self.thandles = {}
self.win32threads = {}
self.dosdevs = []
self.flushcache = False
self.faultaddr = None
global dbgprivdone
if not dbgprivdone:
dbgprivdone = getDebugPrivileges()
self._is_wow64 = False # 64 bit trace uses this...
self._step_suspends = set() # Threads we have suspended for single stepping
# Skip the attach event and plow through to the first
# injected breakpoint (cause libs are loaded by then)
self.enableAutoContinue(vtrace.NOTIFY_ATTACH)
self.setupDosDeviceMaps()
# Setup our binary format meta
self.setMeta('Format','pe')
# Setup some win32_ver info in metadata
rel,ver,csd,ptype = platform.win32_ver()
self.setMeta("WindowsRelease",rel)
self.setMeta("WindowsVersion", ver)
self.setMeta("WindowsCsd", csd)
self.setMeta("WindowsProcessorType", ptype)
# Setup modes which only apply to windows systems
self.initMode('BlockStep', False, 'Single step to branch entry points')
# If possible, get a default set of struct definitions
# for ntdll...
nt = vs_windows.getCurrentDef('ntdll')
if nt != None:
self.vsbuilder.addVStructNamespace('ntdll', nt)
# Either way, add the fallback "win32" namespace
self.vsbuilder.addVStructNamespace('win32', vs_win32)
# We need thread proxying for a few calls...
self.fireTracerThread()
def _winJitEvent(self, handle):
kernel32.SetEvent(handle)
[docs] def dupHandle(self, handle):
"""
Duplicate the handle (who's id is in the currently attached
target process) and return our own copy.
"""
hret = c_uint(0)
kernel32.DuplicateHandle(self.phandle, handle,
kernel32.GetCurrentProcess(), addressof(hret),
0, False, 2) # DUPLICATE_SAME_ACCESS
return hret.value
[docs] def getHandleInfo(self, handle, itype=ObjectTypeInformation, wait=False):
retSiz = c_uint(0)
buf = create_string_buffer(100)
# Some NtQueryObject calls will hang, lets figgure out which...
if wait:
if kernel32.WaitForSingleObject(handle, 150) == EXCEPTION_TIMEOUT:
return "_TIMEOUT_"
x = ntdll.NtQueryObject(handle, itype,
buf, sizeof(buf), addressof(retSiz))
if x != 0:
return 'Error 0x%.8x' % (e_bits.unsigned(x, self.psize))
realbuf = create_string_buffer(retSiz.value)
if ntdll.NtQueryObject(handle, itype,
realbuf, sizeof(realbuf), addressof(retSiz)) == 0:
uString = cast(realbuf, PUNICODE_STRING).contents
return uString.Buffer
return "Unknown"
[docs] def getHandles(self):
hinfo = buildSystemHandleInformation(1)
hsize = c_ulong(sizeof(hinfo))
ntdll.NtQuerySystemInformation(NT_LIST_HANDLES, addressof(hinfo), hsize, addressof(hsize))
count = (hsize.value-4) / sizeof(SYSTEM_HANDLE)
hinfo = buildSystemHandleInformation(count)
hsize = c_ulong(sizeof(hinfo))
ntdll.NtQuerySystemInformation(NT_LIST_HANDLES, addressof(hinfo), hsize, 0)
return hinfo
[docs] def setupDosDeviceMaps(self):
self.dosdevs = []
dname = (c_char * 512)()
size = kernel32.GetLogicalDriveStringsA(512, addressof(dname))
devs = dname.raw[:size-1].split("\x00")
for dev in devs:
dosname = "%s:" % dev[0]
kernel32.QueryDosDeviceA("%s:" % dev[0], pointer(dname), 512)
self.dosdevs.append( (dosname, dname.value) )
@v_base.threadwrap
@v_base.threadwrap
@v_base.threadwrap
@v_base.threadwrap
def _continueDebugEvent(self):
magic = DBG_CONTINUE
if self.getCurrentSignal() != None:
magic = DBG_EXCEPTION_NOT_HANDLED
if self.flushcache:
self.flushcache = False
kernel32.FlushInstructionCache(self.phandle, 0, 0)
if not kernel32.ContinueDebugEvent(self.pid, self.getMeta("StoppedThreadId"), magic):
raiseWin32Error("ContinueDebugEvent")
@v_base.threadwrap
@v_base.threadwrap
[docs] def getMappedFileName(self, address):
self.requireAttached()
fname = (c_wchar * 512)()
x = psapi.GetMappedFileNameW(self.phandle, address, addressof(fname), 512)
if not x:
return ""
name = fname.value
for dosname, devname in self.dosdevs:
if name.startswith(devname):
return name.replace(devname, dosname)
return name
[docs] def parseWithDbgHelp(self, filename, baseaddr, normname):
funcflags = (SYMFLAG_FUNCTION | SYMFLAG_EXPORT)
sympath = self.getMeta('NtSymbolPath')
parser = Win32SymbolParser(self.phandle, filename, baseaddr, sympath=sympath)
parser.parse()
parser.loadSymsIntoTrace(self, normname)
[docs] def parseWithPE(self, filename, baseaddr, normname):
pe = PE.peFromMemoryObject(self, baseaddr)
for rva, ord, name in pe.getExports():
self.addSymbol(e_resolv.Symbol(name, baseaddr+rva, 0, normname))
@v_base.threadwrap
@v_base.threadwrap
def _getSvcList(self):
'''
Expose the getServicesList via the trace for remote...
'''
return getServicesList()
def _getUacStatus(self):
return getTokenElevationType(self.phandle)
# NOTE: The order of the constructors vs inheritance is very important...
[docs]class Windowsi386Trace(
vtrace.Trace,
WindowsMixin,
v_i386.i386Mixin,
v_base.TracerBase,
):
def __init__(self):
vtrace.Trace.__init__(self)
v_base.TracerBase.__init__(self)
v_i386.i386Mixin.__init__(self)
WindowsMixin.__init__(self)
def _winGetRegStruct(self):
c = CONTEXTx86()
c.ContextFlags = (CONTEXT_i386 |
CONTEXT_FULL |
CONTEXT_DEBUG_REGISTERS |
CONTEXT_EXTENDED_REGISTERS)
return c
[docs]class WindowsAmd64Trace(
vtrace.Trace,
WindowsMixin,
v_amd64.Amd64Mixin,
v_base.TracerBase,
):
def __init__(self):
vtrace.Trace.__init__(self)
v_base.TracerBase.__init__(self)
WindowsMixin.__init__(self)
v_amd64.Amd64Mixin.__init__(self)
def _winGetRegStruct(self):
c = CONTEXTx64()
c.ContextFlags = (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS)
return c
reserved = {
'None': True,
'True': True,
'False': True,
}
VT_EMPTY = 0
VT_NULL = 1
VT_I2 = 2
VT_I4 = 3
VT_R4 = 4
VT_R8 = 5
VT_CY = 6
VT_DATE = 7
VT_BSTR = 8
VT_DISPATCH = 9
VT_ERROR = 10
VT_BOOL = 11
VT_VARIANT = 12
VT_UNKNOWN = 13
VT_I1 = 16
VT_UI1 = 17
VT_UI2 = 18
VT_UI4 = 19
VT_INT = 20
VT_UINT = 21
[docs]class VARIANT_guts(Union):
_fields_ = [
('ui1', c_uint8),
('ui2', c_uint16),
('ui4', c_uint32),
('i1', c_int8),
('i2', c_int16),
('i4', c_int32),
('pad', BYTE*32),
]
[docs]class VARIANT(Structure):
_fields_ = [
('vt', WORD),
('res1', WORD),
('res2', WORD),
('res3', WORD),
('u', VARIANT_guts),
]
[docs]class Win32SymbolParser:
def __init__(self, phandle, filename, loadbase, sympath=None):
self.phandle = phandle
self.filename = filename
self.loadbase = loadbase
self.sympath = sympath
self.symbols = []
self.symopts = (SYMOPT_UNDNAME | SYMOPT_NO_PROMPTS | SYMOPT_NO_CPP)
self._sym_types = {}
self._sym_enums = {}
self._sym_locals = {}
[docs] def printSymbolInfo(self, info):
# Just a helper function for "reversing" how dbghelp works
for n,t in info.__class__._fields_:
print n,repr(getattr(info, n))
[docs] def symGetTypeInfo(self, tindex, tinfo, tparam):
x = dbghelp.SymGetTypeInfo(self.phandle, self.loadbase,
tindex, tinfo, tparam)
if x == 0:
return False
return True
[docs] def symGetTypeName(self, typeid):
n = c_wchar_p()
self.symGetTypeInfo(typeid, TI_GET_SYMNAME, pointer(n))
val = n.value
# Strip leading / trailing _'s
if val != None:
val = val.strip('_')
if val == '<unnamed-tag>' or val == 'unnamed':
val = '_unnamed_%d' % typeid
#print repr(val)
return val
[docs] def symGetUdtKind(self, typeid):
offset = c_ulong(0)
self.symGetTypeInfo(typeid, TI_GET_UDTKIND, pointer(offset))
return offset.value
[docs] def symGetTypeOffset(self, typeid):
offset = c_ulong(0)
self.symGetTypeInfo(typeid, TI_GET_OFFSET, pointer(offset))
return offset.value
[docs] def symGetTypeLength(self, typeid):
size = c_ulonglong(0)
self.symGetTypeInfo(typeid, TI_GET_LENGTH, pointer(size))
return size.value
[docs] def symGetArrayIndexType(self, typeid):
offset = c_ulong(0)
self.symGetTypeInfo(typeid, TI_GET_ARRAYINDEXTYPEID, pointer(offset))
return offset.value
[docs] def symGetTypeValue(self, typeid):
#size = c_ulonglong(0)
v = VARIANT()
self.symGetTypeInfo(typeid, TI_GET_VALUE, pointer(v))
vt = v.vt
# Messy, but gotta do it...
if vt == VT_I1: return v.u.i1
if vt == VT_I2: return v.u.i2
if vt == VT_I4: return v.u.i4
if vt == VT_UI1: return v.u.ui1
if vt == VT_UI2: return v.u.ui2
if vt == VT_UI4: return v.u.ui4
raise Exception('Unhandled Variant Type: %d' % v.vt)
[docs] def symGetTypeBase(self, typeid):
btype = c_ulong(typeid)
# Resolve the deepest base type
while self.symGetTypeTag(btype.value) == SymTagTypedef:
self.symGetTypeInfo(btype.value, TI_GET_BASETYPE, pointer(btype))
return btype.value
[docs] def symGetTypeType(self, child):
ktype = c_ulong(0)
self.symGetTypeInfo(child, TI_GET_TYPE, pointer(ktype))
return ktype.value
[docs] def symGetTypeTag(self, typeid):
btype = c_ulong(0)
self.symGetTypeInfo(typeid, TI_GET_SYMTAG, pointer(btype))
return btype.value
def _fixKidName(self, kidname):
if kidname and kidname[0].isdigit():
kidname = '_%s' % kidname
if reserved.get(kidname):
kidname = '_%s' % kidname
return kidname
def _symTypeEnum(self, name, tidx):
size = self.symGetTypeLength(tidx)
kids = []
for child in self._symGetChildren(tidx):
kidname = self.symGetTypeName(child)
kidval = self.symGetTypeValue(child)
kidname = self._fixKidName(kidname)
kids.append((kidname, kidval))
self._sym_enums[name] = (name, size, kids)
def _symTypeUserDefined(self, name, tidx):
size = self.symGetTypeLength(tidx)
kids = []
for child in self._symGetChildren(tidx):
kidname = self.symGetTypeName(child)
kidoff = self.symGetTypeOffset(child)
ktype = self.symGetTypeType(child)
ksize = self.symGetTypeLength(ktype)
ktag = self.symGetTypeTag(ktype)
kidname = self._fixKidName(kidname)
kflags = 0
ktypename = None
kcount = None
if ktag == SymTagPointerType:
kflags |= vs_builder.VSFF_POINTER
ptype = self.symGetTypeType(ktype)
ktypename = self.symGetTypeName(ptype)
elif ktag == SymTagArrayType:
atype = self.symGetTypeType(ktype)
asize = self.symGetTypeLength(atype)
kcount = ksize / asize
# Now, we setup our *child* to be the type
ktypename = self.symGetTypeName(atype)
ksize = asize
if self.symGetTypeTag(atype) == SymTagPointerType:
kflags |= vs_builder.VSFF_POINTER
elif ktag == SymTagEnum:
#ktypename = self.symGetTypeName(ktype)
pass
elif ktag == SymTagUDT:
ktypename = self.symGetTypeName(ktype)
elif ktag == SymTagBaseType:
pass
elif ktag == SymTagFunctionType:
# Function pointer types...
pass
elif ktag == SymTagNull:
pass
else:
print '%s:%s Unknown Type Tag: %d' % (name, kidname, ktag)
kids.append((kidname, kidoff, ksize, ktypename, kflags, kcount))
self._sym_types[name] = (name, size, kids)
def _symGetChildren(self, typeIndex):
s = c_ulong(0)
self.symGetTypeInfo(typeIndex, TI_GET_CHILDRENCOUNT, pointer(s))
tif = buildFindChildrenParams(s.value)
self.symGetTypeInfo(typeIndex, TI_FINDCHILDREN, pointer(tif))
for i in range(s.value):
child = tif.Children[i]
yield child
[docs] def typeEnumCallback(self, psym, size, ctx):
sym = psym.contents
myname = self.symGetTypeName(sym.TypeIndex)
mytag = self.symGetTypeTag(sym.TypeIndex)
if mytag == SymTagUDT:
self._symTypeUserDefined(myname, sym.TypeIndex)
return True
if mytag == SymTagEnum:
self._symTypeEnum(myname, sym.TypeIndex)
return True
return True
[docs] def symFromAddr(self, address):
si = SYMBOL_INFO()
si.SizeOfStruct = sizeof(si) - 2000
si.MaxNameLen = 2000
disp = QWORD()
dbghelp.SymFromAddr(self.phandle, address, pointer(disp), pointer(si))
return si
[docs] def symInit(self):
dbghelp.SymInitialize(self.phandle, self.sympath, False)
dbghelp.SymSetOptions(self.symopts)
x = dbghelp.SymLoadModule64(self.phandle,
0,
self.filename,
None,
self.loadbase,
os.path.getsize(self.filename))
# This is for debugging which pdb got loaded
#imghlp = IMAGEHLP_MODULE64()
#imghlp.SizeOfStruct = sizeof(imghlp)
#dbghelp.SymGetModuleInfo64(self.phandle, x, pointer(imghlp))
#print "PDB",repr(imghlp.LoadedPdbName)
[docs] def symCleanup(self):
dbghelp.SymCleanup(self.phandle)
[docs] def symLocalCallback(self, psym, size, ctx):
sym = psym.contents
address = c_int32(sym.Address).value
self._cur_locs.append( (sym.Name, address, sym.Size, sym.Flags) )
return True
[docs] def parseArgs(self):
for name, addr, size, flags in self.symbols:
si = self.symFromAddr(addr)
if si.Tag != SymTagFunction:
continue
self._cur_locs = []
sframe = IMAGEHLP_STACK_FRAME()
sframe.InstructionOffset = addr
dbghelp.SymSetContext(self.phandle, pointer(sframe), 0)
dbghelp.SymEnumSymbols(self.phandle,
0,
None,
SYMCALLBACK(self.symLocalCallback),
0)
if len(self._cur_locs):
self._sym_locals[addr] = self._cur_locs
[docs] def parse(self):
try:
self.symInit()
dbghelp.SymEnumSymbols(self.phandle,
self.loadbase,
None,
SYMCALLBACK(self.symEnumCallback),
NULL)
self.parseTypes()
#self.parseArgs()
self.symCleanup()
except Exception, e:
traceback.print_exc()
raise
[docs] def parseTypes(self):
#self.symInit()
# This is how you enumerate type information
dbghelp.SymEnumTypes(self.phandle,
self.loadbase,
SYMCALLBACK(self.typeEnumCallback),
NULL)
#self.symCleanup()
[docs] def loadSymsIntoTrace(self, trace, normname):
funcflags = (SYMFLAG_FUNCTION | SYMFLAG_EXPORT)
for name, addr, size, flags in self.symbols:
symclass = e_resolv.Symbol
if flags & funcflags:
symclass = e_resolv.FunctionSymbol
sym = symclass(name, addr, size, normname)
trace.addSymbol(sym)
t = self._sym_types.values()
e = self._sym_enums.values()
# Only add the namespace if we have values...
if len(t):
builder = vs_builder.VStructBuilder(defs=t, enums=e)
trace.vsbuilder.addVStructNamespace(normname, builder)