Add TCP connections + Syswow64 injection

This commit is contained in:
Clement Rouault
2015-04-01 18:22:42 +02:00
parent a7b463c05a
commit 481b8861f0
11 changed files with 795 additions and 231 deletions
+32 -1
View File
@@ -13,6 +13,7 @@ class Flag(long):
NULL = Flag("NULL", 0)
MAX_PATH = Flag("MAX_PATH", 260)
ANYSIZE_ARRAY = Flag("ANYSIZE_ARRAY", 1)
ANY_SIZE = Flag("ANY_SIZE", 1)
IMAGE_SIZEOF_SHORT_NAME = Flag("IMAGE_SIZEOF_SHORT_NAME", 8)
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = Flag("IMAGE_NUMBEROF_DIRECTORY_ENTRIES", 16)
STD_INPUT_HANDLE = Flag("STD_INPUT_HANDLE", -10)
@@ -242,4 +243,34 @@ TOKEN_ALL_ACCESS = Flag("TOKEN_ALL_ACCESS", ( TOKEN_ALL_ACCESS_P | TOKEN_ADJUST_
SE_PRIVILEGE_ENABLED_BY_DEFAULT = Flag("SE_PRIVILEGE_ENABLED_BY_DEFAULT", ( 0x00000001L ))
SE_PRIVILEGE_ENABLED = Flag("SE_PRIVILEGE_ENABLED", ( 0x00000002L ))
SE_PRIVILEGE_REMOVED = Flag("SE_PRIVILEGE_REMOVED", ( 0X00000004L ))
SE_PRIVILEGE_USED_FOR_ACCESS = Flag("SE_PRIVILEGE_USED_FOR_ACCESS", ( 0x80000000L ))
SE_PRIVILEGE_USED_FOR_ACCESS = Flag("SE_PRIVILEGE_USED_FOR_ACCESS", ( 0x80000000L ))
AF_UNSPEC = Flag("AF_UNSPEC", 0)
AF_UNIX = Flag("AF_UNIX", 1)
AF_INET = Flag("AF_INET", 2)
AF_IMPLINK = Flag("AF_IMPLINK", 3)
AF_PUP = Flag("AF_PUP", 4)
AF_CHAOS = Flag("AF_CHAOS", 5)
AF_NS = Flag("AF_NS", 6)
AF_IPX = Flag("AF_IPX", AF_NS)
AF_ISO = Flag("AF_ISO", 7)
AF_OSI = Flag("AF_OSI", AF_ISO)
AF_ECMA = Flag("AF_ECMA", 8)
AF_DATAKIT = Flag("AF_DATAKIT", 9)
AF_CCITT = Flag("AF_CCITT", 10)
AF_SNA = Flag("AF_SNA", 11)
AF_DECnet = Flag("AF_DECnet", 12)
AF_DLI = Flag("AF_DLI", 13)
AF_LAT = Flag("AF_LAT", 14)
AF_HYLINK = Flag("AF_HYLINK", 15)
AF_APPLETALK = Flag("AF_APPLETALK", 16)
AF_NETBIOS = Flag("AF_NETBIOS", 17)
AF_VOICEVIEW = Flag("AF_VOICEVIEW", 18)
AF_FIREFOX = Flag("AF_FIREFOX", 19)
AF_UNKNOWN1 = Flag("AF_UNKNOWN1", 20)
AF_BAN = Flag("AF_BAN", 21)
AF_ATM = Flag("AF_ATM", 22)
AF_INET6 = Flag("AF_INET6", 23)
AF_CLUSTER = Flag("AF_CLUSTER", 24)
AF_12844 = Flag("AF_12844", 25)
AF_IRDA = Flag("AF_IRDA", 26)
AF_NETDES = Flag("AF_NETDES", 28)
+13 -1
View File
@@ -3,7 +3,7 @@ from ctypes import *
from ctypes.wintypes import *
from winstructs import *
functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentProcessorNumber', 'AllocConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile']
functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentProcessorNumber', 'AllocConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry']
# ExitProcess(uExitCode):
ExitProcessPrototype = WINFUNCTYPE(VOID, UINT)
@@ -213,3 +213,15 @@ SetThreadAffinityMaskParams = ((1, 'hThread'), (1, 'dwThreadAffinityMask'))
WriteFilePrototype = WINFUNCTYPE(BOOL, HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED)
WriteFileParams = ((1, 'hFile'), (1, 'lpBuffer'), (1, 'nNumberOfBytesToWrite'), (1, 'lpNumberOfBytesWritten'), (1, 'lpOverlapped'))
# GetExtendedTcpTable(pTcpTable, pdwSize, bOrder, ulAf, TableClass, Reserved):
GetExtendedTcpTablePrototype = WINFUNCTYPE(DWORD, PVOID, PDWORD, BOOL, ULONG, TCP_TABLE_CLASS, ULONG)
GetExtendedTcpTableParams = ((1, 'pTcpTable'), (1, 'pdwSize'), (1, 'bOrder'), (1, 'ulAf'), (1, 'TableClass'), (1, 'Reserved'))
# GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, ulAf, TableClass, Reserved):
GetExtendedUdpTablePrototype = WINFUNCTYPE(DWORD, PVOID, PDWORD, BOOL, ULONG, UDP_TABLE_CLASS, ULONG)
GetExtendedUdpTableParams = ((1, 'pUdpTable'), (1, 'pdwSize'), (1, 'bOrder'), (1, 'ulAf'), (1, 'TableClass'), (1, 'Reserved'))
# SetTcpEntry(pTcpRow):
SetTcpEntryPrototype = WINFUNCTYPE(DWORD, PMIB_TCPROW)
SetTcpEntryParams = ((1, 'pTcpRow'),)
+136 -12
View File
@@ -15,6 +15,7 @@ LPTHREAD_START_ROUTINE = PVOID
LPBYTE = POINTER(BYTE)
ULONG_PTR = PULONG
CHAR = c_char
UCHAR = c_char
FARPROC = PVOID
HGLOBAL = PVOID
ULONGLONG = c_ulonglong
@@ -23,9 +24,9 @@ PULONG64 = POINTER(ULONG64)
PHANDLE = POINTER(HANDLE)
VOID = DWORD
structs = ['_LIST_ENTRY', '_PEB_LDR_DATA', '_LSA_UNICODE_STRING', '_RTL_USER_PROCESS_PARAMETERS', '_PEB', '_SECURITY_ATTRIBUTES', '_SYSTEM_VERIFIER_INFORMATION', '_LDR_DATA_TABLE_ENTRY', '_PEB_LDR_DATA', '_IMAGE_FILE_HEADER', '_IMAGE_DATA_DIRECTORY', '_IMAGE_SECTION_HEADER', '_IMAGE_OPTIONAL_HEADER64', '_IMAGE_OPTIONAL_HEADER', '_IMAGE_NT_HEADERS64', '_IMAGE_NT_HEADERS', '_IMAGE_IMPORT_DESCRIPTOR', '_IMAGE_IMPORT_BY_NAME', '_MEMORY_BASIC_INFORMATION', '_STARTUPINFOA', '_STARTUPINFOW', '_PROCESS_INFORMATION', '_FLOATING_SAVE_AREA', '_CONTEXT', 'tagPROCESSENTRY32W', 'tagPROCESSENTRY32', 'tagTHREADENTRY32', '_LUID', '_LUID_AND_ATTRIBUTES', '_TOKEN_PRIVILEGES', '_OSVERSIONINFOA', '_OSVERSIONINFOW', '_OSVERSIONINFOEXA', '_OSVERSIONINFOEXW', '_OVERLAPPED']
structs = ['_LIST_ENTRY', '_PEB_LDR_DATA', '_LSA_UNICODE_STRING', '_RTL_USER_PROCESS_PARAMETERS', '_PEB', '_SECURITY_ATTRIBUTES', '_SYSTEM_VERIFIER_INFORMATION', '_LDR_DATA_TABLE_ENTRY', '_IMAGE_FILE_HEADER', '_IMAGE_DATA_DIRECTORY', '_IMAGE_SECTION_HEADER', '_IMAGE_OPTIONAL_HEADER64', '_IMAGE_OPTIONAL_HEADER', '_IMAGE_NT_HEADERS64', '_IMAGE_NT_HEADERS', '_IMAGE_IMPORT_DESCRIPTOR', '_IMAGE_IMPORT_BY_NAME', '_MEMORY_BASIC_INFORMATION', '_STARTUPINFOA', '_STARTUPINFOW', '_PROCESS_INFORMATION', '_FLOATING_SAVE_AREA', '_CONTEXT', 'tagPROCESSENTRY32W', 'tagPROCESSENTRY32', 'tagTHREADENTRY32', '_LUID', '_LUID_AND_ATTRIBUTES', '_TOKEN_PRIVILEGES', '_OSVERSIONINFOA', '_OSVERSIONINFOW', '_OSVERSIONINFOEXA', '_OSVERSIONINFOEXW', '_OVERLAPPED', '_MIB_TCPROW_OWNER_PID', '_MIB_TCPTABLE_OWNER_PID', '_MIB_UDPROW_OWNER_PID', '_MIB_UDPTABLE_OWNER_PID', '_MIB_UDP6ROW_OWNER_PID', '_MIB_UDP6TABLE_OWNER_PID', '_MIB_TCP6ROW_OWNER_PID', '_MIB_TCP6TABLE_OWNER_PID', '_MIB_TCPROW']
enums = ['_SYSTEM_INFORMATION_CLASS']
enums = ['_SYSTEM_INFORMATION_CLASS', '_TCP_TABLE_CLASS', '_UDP_TABLE_CLASS', '_MIB_TCP_STATE']
# Enum _SYSTEM_INFORMATION_CLASS definitions
_SYSTEM_INFORMATION_CLASS = DWORD
@@ -114,6 +115,42 @@ SystemSuperfetchInformation = 0x4f
SystemMemoryListInformation = 0x50
SystemFileCacheInformationEx = 0x51
MaxSystemInfoClass = 0x52
# Enum _TCP_TABLE_CLASS definitions
_TCP_TABLE_CLASS = DWORD
TCP_TABLE_CLASS = _TCP_TABLE_CLASS
TCP_TABLE_BASIC_LISTENER = 0x0
TCP_TABLE_BASIC_CONNECTIONS = 0x1
TCP_TABLE_BASIC_ALL = 0x2
TCP_TABLE_OWNER_PID_LISTENER = 0x3
TCP_TABLE_OWNER_PID_CONNECTIONS = 0x4
TCP_TABLE_OWNER_PID_ALL = 0x5
TCP_TABLE_OWNER_MODULE_LISTENER = 0x6
TCP_TABLE_OWNER_MODULE_CONNECTIONS = 0x7
TCP_TABLE_OWNER_MODULE_ALL = 0x8
# Enum _UDP_TABLE_CLASS definitions
_UDP_TABLE_CLASS = DWORD
UDP_TABLE_CLASS = _UDP_TABLE_CLASS
UDP_TABLE_BASIC = 0x0
UDP_TABLE_OWNER_PID = 0x1
UDP_TABLE_OWNER_MODULE = 0x2
# Enum _MIB_TCP_STATE definitions
_MIB_TCP_STATE = DWORD
MIB_TCP_STATE = _MIB_TCP_STATE
MIB_TCP_STATE_CLOSED = 0x1
MIB_TCP_STATE_LISTEN = 0x2
MIB_TCP_STATE_SYN_SENT = 0x3
MIB_TCP_STATE_SYN_RCVD = 0x4
MIB_TCP_STATE_ESTAB = 0x5
MIB_TCP_STATE_FIN_WAIT1 = 0x6
MIB_TCP_STATE_FIN_WAIT2 = 0x7
MIB_TCP_STATE_CLOSE_WAIT = 0x8
MIB_TCP_STATE_CLOSING = 0x9
MIB_TCP_STATE_LAST_ACK = 0xa
MIB_TCP_STATE_TIME_WAIT = 0xb
MIB_TCP_STATE_DELETE_TCB = 0xc
# Struct _LIST_ENTRY definitions
# Self referencing struct tricks
class _LIST_ENTRY(Structure): pass
@@ -238,16 +275,6 @@ class _LDR_DATA_TABLE_ENTRY(Structure):
PLDR_DATA_TABLE_ENTRY = POINTER(_LDR_DATA_TABLE_ENTRY)
LDR_DATA_TABLE_ENTRY = _LDR_DATA_TABLE_ENTRY
# Struct _PEB_LDR_DATA definitions
class _PEB_LDR_DATA(Structure):
_fields_ = [
("Reserved1", BYTE * 8),
("Reserved2", PVOID * 3),
("InMemoryOrderModuleList", LIST_ENTRY),
]
PPEB_LDR_DATA = POINTER(_PEB_LDR_DATA)
PEB_LDR_DATA = _PEB_LDR_DATA
# Struct _IMAGE_FILE_HEADER definitions
class _IMAGE_FILE_HEADER(Structure):
_fields_ = [
@@ -687,3 +714,100 @@ class _OVERLAPPED(Structure):
LPOVERLAPPED = POINTER(_OVERLAPPED)
OVERLAPPED = _OVERLAPPED
# Struct _MIB_TCPROW_OWNER_PID definitions
class _MIB_TCPROW_OWNER_PID(Structure):
_fields_ = [
("dwState", DWORD),
("dwLocalAddr", DWORD),
("dwLocalPort", DWORD),
("dwRemoteAddr", DWORD),
("dwRemotePort", DWORD),
("dwOwningPid", DWORD),
]
MIB_TCPROW_OWNER_PID = _MIB_TCPROW_OWNER_PID
PMIB_TCPROW_OWNER_PID = POINTER(_MIB_TCPROW_OWNER_PID)
# Struct _MIB_TCPTABLE_OWNER_PID definitions
class _MIB_TCPTABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("table", MIB_TCPROW_OWNER_PID * ANY_SIZE),
]
MIB_TCPTABLE_OWNER_PID = _MIB_TCPTABLE_OWNER_PID
PMIB_TCPTABLE_OWNER_PID = POINTER(_MIB_TCPTABLE_OWNER_PID)
# Struct _MIB_UDPROW_OWNER_PID definitions
class _MIB_UDPROW_OWNER_PID(Structure):
_fields_ = [
("dwLocalAddr", DWORD),
("dwLocalPort", DWORD),
("dwOwningPid", DWORD),
]
MIB_UDPROW_OWNER_PID = _MIB_UDPROW_OWNER_PID
PMIB_UDPROW_OWNER_PID = POINTER(_MIB_UDPROW_OWNER_PID)
# Struct _MIB_UDPTABLE_OWNER_PID definitions
class _MIB_UDPTABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("table", MIB_UDPROW_OWNER_PID * ANY_SIZE),
]
MIB_UDPTABLE_OWNER_PID = _MIB_UDPTABLE_OWNER_PID
PMIB_UDPTABLE_OWNER_PID = POINTER(_MIB_UDPTABLE_OWNER_PID)
# Struct _MIB_UDP6ROW_OWNER_PID definitions
class _MIB_UDP6ROW_OWNER_PID(Structure):
_fields_ = [
("ucLocalAddr", UCHAR * 16),
("dwLocalScopeId", DWORD),
("dwLocalPort", DWORD),
("dwOwningPid", DWORD),
]
MIB_UDP6ROW_OWNER_PID = _MIB_UDP6ROW_OWNER_PID
PMIB_UDP6ROW_OWNER_PID = POINTER(_MIB_UDP6ROW_OWNER_PID)
# Struct _MIB_UDP6TABLE_OWNER_PID definitions
class _MIB_UDP6TABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("table", MIB_UDP6ROW_OWNER_PID * ANY_SIZE),
]
PMIB_UDP6TABLE_OWNER_PID = POINTER(_MIB_UDP6TABLE_OWNER_PID)
MIB_UDP6TABLE_OWNER_PID = _MIB_UDP6TABLE_OWNER_PID
# Struct _MIB_TCP6ROW_OWNER_PID definitions
class _MIB_TCP6ROW_OWNER_PID(Structure):
_fields_ = [
("ucLocalAddr", UCHAR * 16),
("dwLocalScopeId", DWORD),
("dwLocalPort", DWORD),
("ucRemoteAddr", UCHAR * 16),
("dwRemoteScopeId", DWORD),
("dwRemotePort", DWORD),
("dwState", DWORD),
("dwOwningPid", DWORD),
]
MIB_TCP6ROW_OWNER_PID = _MIB_TCP6ROW_OWNER_PID
PMIB_TCP6ROW_OWNER_PID = POINTER(_MIB_TCP6ROW_OWNER_PID)
# Struct _MIB_TCP6TABLE_OWNER_PID definitions
class _MIB_TCP6TABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("table", MIB_TCP6ROW_OWNER_PID * ANY_SIZE),
]
MIB_TCP6TABLE_OWNER_PID = _MIB_TCP6TABLE_OWNER_PID
PMIB_TCP6TABLE_OWNER_PID = POINTER(_MIB_TCP6TABLE_OWNER_PID)
# Struct _MIB_TCPROW definitions
class _MIB_TCPROW(Structure):
_fields_ = [
("dwState", DWORD),
("dwLocalAddr", DWORD),
("dwLocalPort", DWORD),
("dwRemoteAddr", DWORD),
("dwRemotePort", DWORD),
]
MIB_TCPROW = _MIB_TCPROW
PMIB_TCPROW = POINTER(_MIB_TCPROW)
+15 -17
View File
@@ -27,22 +27,22 @@ def generate_python_exec_shellcode_32(PYDLL_addr, PyInit, PyRun, PYCODE_ADDR):
code += Push_X(PyRun)
code += Push_EDI()
code += Call_EBX()
# Call PyInit with python code to exec
# Call PyRun with python code to exec
code += Push_X(PYCODE_ADDR)
code += Call_EAX()
code += Pop_EDI()
code += Ret()
return code.get_code()
# 64 to 64 injection
# 64 to 64 injection
def generate_python_exec_shellcode_64(PYDLL_addr, PyInit, PyRun, PYCODE_ADDR):
from native_exec.simple_x64 import *
LoadLibraryA = utils.get_func_addr('kernel32', 'LoadLibraryA')
GetProcAddress = utils.get_func_addr('kernel32', 'GetProcAddress')
Reserve_space_for_call = MultipleInstr([Push_RDI()] * 4)
Clean_space_for_call = MultipleInstr([Pop_RDI()] * 4)
code = MultipleInstr()
# Do stack alignement
code += Push_RAX()
@@ -81,34 +81,33 @@ def generate_python_exec_shellcode_64(PYDLL_addr, PyInit, PyRun, PYCODE_ADDR):
# Remove stack alignement
code += Pop_RAX()
code += Ret()
return code.get_code()
return code.get_code()
def inject_python_command(process, code_injected, PYDLL="python27.dll\x00"):
PyInitT = "Py_Initialize\x00"
Pyrun = "PyRun_SimpleString\x00"
PYCODE = code_injected + "\x00"
remote_addr_base = process.virtual_alloc(len(code_injected) + 0x100)
remote_addr = remote_addr_base
PYDLL_addr = remote_addr
process.write_memory(remote_addr, PYDLL)
remote_addr += len(PYDLL)
PyInitT_ADDR = remote_addr
process.write_memory(remote_addr, PyInitT)
remote_addr += len(PyInitT)
Pyrun_ADDR = remote_addr
process.write_memory(remote_addr, Pyrun)
remote_addr += len(Pyrun)
remote_addr += len(Pyrun)
PYCODE_ADDR = remote_addr
process.write_memory(remote_addr, PYCODE)
remote_addr += len(PYCODE)
SHELLCODE_ADDR = remote_addr
if process.bitness == 32:
shellcode = generate_python_exec_shellcode_32(PYDLL_addr, PyInitT_ADDR, Pyrun_ADDR, PYCODE_ADDR)
@@ -117,8 +116,8 @@ def inject_python_command(process, code_injected, PYDLL="python27.dll\x00"):
process.write_memory(SHELLCODE_ADDR, shellcode)
return SHELLCODE_ADDR
def execute_python_code(process, code):
print("me = {0}".format(windows.current_process.bitness))
print("him = {0}".format(process.bitness))
@@ -126,4 +125,3 @@ def execute_python_code(process, code):
raise NotImplementedError("Cannot perform 32 <-> 64 injection")
shellcode_remote_addr = inject_python_command(process, code)
return process.create_thread(shellcode_remote_addr, 0)
+100 -82
View File
@@ -9,11 +9,9 @@ import windows.generated_def.winfuncs as winfuncs
kernel32 = ctypes.windll.kernel32
advapi32 = ctypes.windll.Advapi32
iphlpapi = ctypes.windll.iphlpapi
class Kernel32Error(WindowsError):
def __new__(cls, func_name):
win_error = ctypes.WinError()
api_error = super(Kernel32Error, cls).__new__(cls)
@@ -22,21 +20,45 @@ class Kernel32Error(WindowsError):
api_error.strerror = win_error.strerror
api_error.args = (func_name, win_error.winerror, win_error.strerror)
return api_error
def __init__(self, func_name):
pass
def __repr__(self):
return "{0}: {1}".format(self.api_name, super(Kernel32Error, self).__repr__())
def __str__(self):
return "{0}: {1}".format(self.api_name, super(Kernel32Error, self).__str__())
def no_error_check(result, func, args):
class IphlpapiError(Kernel32Error):
def __new__(cls, func_name, code):
win_error = ctypes.WinError(code)
api_error = super(Kernel32Error, cls).__new__(cls)
api_error.api_name = func_name
api_error.winerror = win_error.winerror
api_error.strerror = win_error.strerror
api_error.args = (func_name, win_error.winerror, win_error.strerror)
return api_error
def __init__(self, func_name, code):
pass
# Error check method
def no_error_check(func_name, result, func, args):
"""Nothing special"""
return args
# Design 1
return args
def kernel32_error_check(func_name, result, func, args):
"""raise Kernel32Error if result is 0"""
if not result:
raise Kernel32Error(func_name)
return args
def iphlpapi_error_check(func_name, result, func, args):
"""raise IphlpapiError if result is NOT 0"""
if result:
raise IphlpapiError(func_name, result)
return args
# Design 1
class ApiProxy(object):
APIDLL = None
"""Create a python wrapper around a kernel32 function"""
@@ -44,14 +66,8 @@ class ApiProxy(object):
self.func_name = func_name
if error_check is None:
error_check = self.default_error_check
self.error_check = error_check
def default_error_check(self, result, func, args):
"""raise Kernel32Error if result is 0"""
if not result:
raise Kernel32Error(self.func_name)
return args
self.error_check = functools.wraps(error_check)(functools.partial(error_check, func_name))
def __call__(self, python_proxy, ):
prototype = getattr(winfuncs, self.func_name + "Prototype")
params = getattr(winfuncs, self.func_name + "Params")
@@ -74,44 +90,44 @@ class ApiProxy(object):
return c_prototyped(*args)
setattr(python_proxy, "ctypes_function", perform_call)
return python_proxy
class Kernel32Proxy(ApiProxy):
APIDLL = kernel32
default_error_check = staticmethod(kernel32_error_check)
class Advapi32Proxy(ApiProxy):
APIDLL = advapi32
def TransparentApiProxy(APIDLL, func_name, error_check=None):
default_error_check = staticmethod(kernel32_error_check)
class IphlpapiProxy(ApiProxy):
APIDLL = iphlpapi
default_error_check = staticmethod(iphlpapi_error_check)
def TransparentApiProxy(APIDLL, func_name, error_check):
"""Create a ctypes function for 'func_name' with no python arg pre-check"""
def default_error_check(result, func, args):
if not result:
raise Kernel32Error(func_name)
return args
if error_check is None:
error_check = default_error_check
prototype = getattr(winfuncs, func_name + "Prototype")
args = getattr(winfuncs, func_name + "Params")
c_prototyped = prototype((func_name, APIDLL), args)
c_prototyped.errcheck = error_check
return c_prototyped
c_prototyped.errcheck = functools.wraps(error_check)(functools.partial(error_check, func_name))
return c_prototyped
TransparentKernel32Proxy = lambda func_name, error_check=kernel32_error_check : TransparentApiProxy(kernel32, func_name, error_check)
TransparentAdvapi32Proxy = lambda func_name, error_check=kernel32_error_check : TransparentApiProxy(advapi32, func_name, error_check)
TransparentIphlpapiProxy = lambda func_name, error_check=iphlpapi_error_check : TransparentApiProxy(iphlpapi, func_name, error_check)
TransparentKernel32Proxy = lambda *args: TransparentApiProxy(kernel32, *args)
TransparentAdvapi32Proxy = lambda *args: TransparentApiProxy(advapi32, *args)
class NeededParameterType(object):
_inst = None
def __new__(cls):
if cls._inst is None:
cls._inst = super(NeededParameterType, cls).__new__(cls)
return cls._inst
def __repr__(self):
return "NeededParameter"
NeededParameter = NeededParameterType()
NeededParameter = NeededParameterType()
ExitProcess = TransparentKernel32Proxy("ExitProcess")
CloseHandle = TransparentKernel32Proxy("CloseHandle")
@@ -130,23 +146,23 @@ SetStdHandle = TransparentKernel32Proxy("SetStdHandle")
@Kernel32Proxy("VirtualAlloc")
def VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT, flProtect=PAGE_EXECUTE_READWRITE):
return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
@Kernel32Proxy("VirtualAllocEx")
def VirtualAllocEx(hProcess, lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT, flProtect=PAGE_EXECUTE_READWRITE):
return VirtualAllocEx.ctypes_function(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
@Kernel32Proxy("CreateRemoteThread")
@Kernel32Proxy("CreateRemoteThread")
def CreateRemoteThread(hProcess=NeededParameter, lpThreadAttributes=None, dwStackSize=0,
lpStartAddress=NeededParameter, lpParameter=NeededParameter, dwCreationFlags=0, lpThreadId=None):
return CreateRemoteThread.ctypes_function(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)
@Kernel32Proxy("VirtualProtect")
@Kernel32Proxy("VirtualProtect")
def VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect=0):
return VirtualProtect.ctypes_function(lpAddress, dwSize, flNewProtect, lpflOldProtect)
@Kernel32Proxy("CreateProcessA")
def CreateProcessA(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False,
dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None, lpProcessInformation=None):
dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None, lpProcessInformation=None):
if lpStartupInfo is None:
StartupInfo = STARTUPINFOA()
StartupInfo.cb = ctypes.sizeof(StartupInfo)
@@ -154,22 +170,22 @@ def CreateProcessA(lpApplicationName, lpCommandLine=None, lpProcessAttributes=No
StartupInfo.wShowWindow = SW_HIDE
lpStartupInfo = ctypes.byref(StartupInfo)
if lpProcessInformation is None:
lpProcessInformation = ctypes.byref(PROCESS_INFORMATION())
lpProcessInformation = ctypes.byref(PROCESS_INFORMATION())
return CreateProcessA.ctypes_function(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
@Kernel32Proxy("CreateProcessW")
def CreateProcessW(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False,
dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None, lpProcessInformation=None):
dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None, lpProcessInformation=None):
if lpStartupInfo is None:
StartupInfo = STARTUPINFOW()
StartupInfo.cb = ctypes.sizeof(StartupInfo)
StartupInfo.dwFlags = STARTF_USESHOWWINDOW
StartupInfo.wShowWindow = SW_HIDE
lpStartupInfo = ctypes.byref(StartupInfo)
lpStartupInfo = ctypes.byref(StartupInfo)
if lpProcessInformation is None:
lpProcessInformation = ctypes.byref(PROCESS_INFORMATION())
lpProcessInformation = ctypes.byref(PROCESS_INFORMATION())
return CreateProcessW.ctypes_function(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
@Kernel32Proxy("GetThreadContext")
def GetThreadContext(hThread, lpContext=None):
if lpContext is None:
@@ -177,14 +193,14 @@ def GetThreadContext(hThread, lpContext=None):
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
lpContext = ctypes.byref(Context)
return GetThreadContext.ctypes_function(hThread, lpContext)
@Kernel32Proxy("SetThreadContext")
def SetThreadContext(hThread, lpContext):
""" Allows to directly pass a CONTEXT and will call with byref(CONTEXT) by itself"""
if type(lpContext) == CONTEXT:
lpContext = ctypes.byref(lpContext)
return SetThreadContext.ctypes_function(hThread, lpContext)
@Kernel32Proxy("OpenThread")
def OpenThread(dwDesiredAccess=THREAD_ALL_ACCESS, bInheritHandle=0, dwThreadId=NeededParameter):
return OpenThread.ctypes_function(dwDesiredAccess, bInheritHandle, dwThreadId)
@@ -192,64 +208,60 @@ def OpenThread(dwDesiredAccess=THREAD_ALL_ACCESS, bInheritHandle=0, dwThreadId=N
@Kernel32Proxy("OpenProcess")
def OpenProcess(dwDesiredAccess=PROCESS_ALL_ACCESS, bInheritHandle=0, dwProcessId=NeededParameter):
return OpenProcess.ctypes_function(dwDesiredAccess, bInheritHandle, dwProcessId)
@Kernel32Proxy("ReadProcessMemory")
def ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer=None, nSize=NeededParameter, lpNumberOfBytesRead=None):
"""Create a string buffer if lpBuffer is not given"""
if lpBuffer is None and nSize is not NeededParameter:
lpBuffer = ctypes.create_string_buffer(nSize)
def ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead=None):
return ReadProcessMemory.ctypes_function(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead)
@Kernel32Proxy("WriteProcessMemory")
def WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize=None, lpNumberOfBytesWritten=None):
"""Computer nSize with len(lpBuffer) if not given"""
if nSize is None:
nSize = len(lpBuffer)
return WriteProcessMemory.ctypes_function(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten)
@Kernel32Proxy('SetThreadAffinityMask')
def SetThreadAffinityMask(hThread=None, dwThreadAffinityMask=NeededParameter):
"""If hThread is not given, it will be the current thread"""
if hThread is None:
hThread = GetCurrentThread()
return SetThreadAffinityMask.ctypes_function(hThread, dwThreadAffinityMask)
@Kernel32Proxy("CreateToolhelp32Snapshot")
@Kernel32Proxy("CreateToolhelp32Snapshot")
def CreateToolhelp32Snapshot(dwFlags, th32ProcessID=0):
return CreateToolhelp32Snapshot.ctypes_function(dwFlags, th32ProcessID)
@Kernel32Proxy("Thread32First", no_error_check)
@Kernel32Proxy("Thread32First", no_error_check)
def Thread32First(hSnapshot, lpte):
"""Set byref(lpte) if needed"""
if type(lpte) == THREADENTRY32:
lpte = ctypes.byref(lpte)
return Thread32First.ctypes_function(hSnapshot, lpte)
@Kernel32Proxy("Thread32Next", no_error_check)
@Kernel32Proxy("Thread32Next", no_error_check)
def Thread32Next(hSnapshot, lpte):
"""Set byref(lpte) if needed"""
if type(lpte) == THREADENTRY32:
lpte = ctypes.byref(lpte)
return Thread32Next.ctypes_function(hSnapshot, lpte)
@Kernel32Proxy("Process32First", no_error_check)
@Kernel32Proxy("Process32First", no_error_check)
def Process32First(hSnapshot, lpte):
"""Set byref(lpte) if needed"""
if type(lpte) == THREADENTRY32:
lpte = ctypes.byref(lpte)
return Process32First.ctypes_function(hSnapshot, lpte)
@Kernel32Proxy("Process32Next", no_error_check)
@Kernel32Proxy("Process32Next", no_error_check)
def Process32Next(hSnapshot, lpte):
"""Set byref(lpte) if needed"""
if type(lpte) == THREADENTRY32:
lpte = ctypes.byref(lpte)
return Process32Next.ctypes_function(hSnapshot, lpte)
# File stuff
@Kernel32Proxy("WriteFile")
@Kernel32Proxy("WriteFile")
def WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite=None, lpNumberOfBytesWritten=None, lpOverlapped=None):
if nNumberOfBytesToWrite is None:
nNumberOfBytesToWrite = len(lpBuffer)
@@ -257,7 +269,6 @@ def WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite=None, lpNumberOfBytesWritte
lpNumberOfBytesWritten = ctypes.byref(DWORD())
return WriteFile.ctypes_function(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
###### ADVAPI32 ########
@Advapi32Proxy('OpenProcessToken')
@@ -270,23 +281,30 @@ def OpenProcessToken(ProcessHandle=None, DesiredAccess=NeededParameter, TokenHan
@Advapi32Proxy('LookupPrivilegeValueA')
def LookupPrivilegeValueA(lpSystemName=None, lpName=NeededParameter, lpLuid=NeededParameter):
return LookupPrivilegeValueA.ctypes_function(lpSystemName, lpName, lpLuid)
@Advapi32Proxy('LookupPrivilegeValueW')
def LookupPrivilegeValueW(lpSystemName=None, lpName=NeededParameter, lpLuid=NeededParameter):
return LookupPrivilegeValueW.ctypes_function(lpSystemName, lpName, lpLuid)
return LookupPrivilegeValueW.ctypes_function(lpSystemName, lpName, lpLuid)
@Advapi32Proxy('AdjustTokenPrivileges')
def AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges=False, NewState=NeededParameter, BufferLength=None, PreviousState=None, ReturnLength=None):
if BufferLength is None:
BufferLength = ctypes.sizeof(NewState)
return AdjustTokenPrivileges.ctypes_function(TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength)
# if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
# fprintf(stderr, "[-] The token does not have the specified privilege\n");
# return FALSE;
###### Iphlpapi (network list and stuff) #######
SetTcpEntry = TransparentIphlpapiProxy('SetTcpEntry')
@IphlpapiProxy('GetExtendedTcpTable')
def GetExtendedTcpTable(pTcpTable, pdwSize=None, bOrder=True, ulAf=NeededParameter, TableClass=TCP_TABLE_OWNER_PID_ALL, Reserved=0):
if pdwSize is None:
ctypes.sizeof(pTcpTable)
return GetExtendedTcpTable.ctypes_function(pTcpTable, pdwSize, bOrder, ulAf, TableClass, Reserved)
# Design 2
# Design 2 should use the automatics args
+1 -1
View File
@@ -121,7 +121,7 @@ def analyse_callback(callback):
def generate_stub_32(callback):
from simple_x86 import *
obj_id = analyse_callback(callback)
c_callback = ctypes.c_ulong.from_address(id(callback._objects['0']) + 3 * ctypes.sizeof(ctypes.c_void_p)).value
gstate_save_addr = allocator.reserve_int()
return_addr_save_addr = allocator.reserve_int()
+4 -1
View File
@@ -58,6 +58,10 @@ class Int3(X64Instruction):
mnemo = "int3"
code = "CC"
class Retf(X64Instruction):
mnemo = "retf"
code = "CB"
class SimpleRegInstructionGenerator(object):
name = ""
@@ -65,7 +69,6 @@ class SimpleRegInstructionGenerator(object):
class OneBindX64Instruction(X64Instruction):
biding = 1
class Mov_RAX_DX(OneBindX64Instruction):
name = 'Mov_RAX_DX'
+151
View File
@@ -0,0 +1,151 @@
import windows
import windows.k32testing
import ctypes
import socket
import struct
from windows.generated_def.winstructs import *
from windows.generated_def.windef import *
class TCP4Connection(MIB_TCPROW_OWNER_PID):
@property
def established(self):
return self.dwState == MIB_TCP_STATE_ESTAB
@property
def remote_port(self):
return socket.ntohs(self.dwRemotePort)
@property
def local_port(self):
return socket.ntohs(self.dwLocalPort)
@property
def local_addr(self):
return socket.inet_ntoa(struct.pack("<I", self.dwLocalAddr))
@property
def remote_addr(self):
return socket.inet_ntoa(struct.pack("<I", self.dwRemoteAddr))
@property
def remote_proto(self):
try:
return socket.getservbyport(self.remote_port, 'tcp')
except socket.error:
return self.remote_port
@property
def remote_host(self):
try:
return socket.gethostbyaddr(self.remote_addr)
except socket.error:
return self.remote_addr
def close(self):
closing = MIB_TCPROW()
closing.dwState = MIB_TCP_STATE_DELETE_TCB
closing.dwLocalAddr = self.dwLocalAddr
closing.dwLocalPort = self.dwLocalPort
closing.dwRemoteAddr = self.dwRemoteAddr
closing.dwRemotePort = self.dwRemotePort
return windows.k32testing.SetTcpEntry(ctypes.byref(closing))
def __repr__(self):
if not self.established:
return "<TCP IPV4 Listening socket on {0}:{1}>".format(self.local_addr, self.local_port)
return "<TCP IPV4 Connection {0}:{1} -> {2}:{3}>".format(self.local_addr, self.local_port, self.remote_addr, self.remote_port)
class TCP6Connection(MIB_TCP6ROW_OWNER_PID):
@staticmethod
def _str_ipv6_addr(addr):
return ":".join(c.encode('hex') for c in addr)
@property
def established(self):
return self.dwState == MIB_TCP_STATE_ESTAB
@property
def remote_port(self):
return socket.ntohs(self.dwRemotePort)
@property
def local_port(self):
return socket.ntohs(self.dwLocalPort)
@property
def local_addr(self):
return self._str_ipv6_addr(self.ucLocalAddr)
@property
def remote_addr(self):
return self._str_ipv6_addr(self.ucRemoteAddr)
@property
def remote_proto(self):
return self.remote_port
@property
def remote_host(self):
return self.remote_addr
def close(self):
raise NotImplementedError("Closing IPV6 connection non implemented")
def __repr__(self):
if not self.established:
return "<TCP IPV6 Listening socket on {0}:{1}>".format(self.local_addr, self.local_port)
return "<TCP IPV6 Connection {0}:{1} -> {2}:{3}>".format(self.local_addr, self.local_port, self.remote_addr, self.remote_port)
def get_MIB_TCPTABLE_OWNER_PID_from_buffer(buffer):
x = windows.generated_def.winstructs.MIB_TCPTABLE_OWNER_PID.from_buffer(buffer)
nb_entry = x.dwNumEntries
class _GENERATED_MIB_TCPTABLE_OWNER_PID(ctypes.Structure):
_fields_ = [
("dwNumEntries", DWORD),
("table", TCP4Connection * nb_entry),
]
return _GENERATED_MIB_TCPTABLE_OWNER_PID.from_buffer(buffer)
def get_MIB_TCP6TABLE_OWNER_PID_from_buffer(buffer):
x = windows.generated_def.winstructs.MIB_TCP6TABLE_OWNER_PID.from_buffer(buffer)
nb_entry = x.dwNumEntries
# Struct _MIB_TCP6TABLE_OWNER_PID definitions
class _GENERATED_MIB_TCP6TABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("table", TCP6Connection * nb_entry),
]
return _GENERATED_MIB_TCP6TABLE_OWNER_PID.from_buffer(buffer)
def get_tcp_ipv4_sockets():
size = ctypes.c_uint(0)
try:
windows.k32testing.GetExtendedTcpTable(None, ctypes.byref(size), ulAf=windows.generated_def.windef.AF_INET)
except windows.k32testing.IphlpapiError as e:
pass # Allow us to set size to the needed value
buffer = (ctypes.c_char * size.value)()
windows.k32testing.GetExtendedTcpTable(buffer, ctypes.byref(size), ulAf=windows.generated_def.windef.AF_INET)
t = get_MIB_TCPTABLE_OWNER_PID_from_buffer(buffer)
return list(t.table)
def get_tcp_ipv6_sockets():
size = ctypes.c_uint(0)
try:
windows.k32testing.GetExtendedTcpTable(None, ctypes.byref(size), ulAf=windows.generated_def.windef.AF_INET6)
except windows.k32testing.IphlpapiError as e:
pass # Allow us to set size to the needed value
buffer = (ctypes.c_char * size.value)()
windows.k32testing.GetExtendedTcpTable(buffer, ctypes.byref(size), ulAf=windows.generated_def.windef.AF_INET6)
t = get_MIB_TCP6TABLE_OWNER_PID_from_buffer(buffer)
return list(t.table)
+40 -39
View File
@@ -16,95 +16,96 @@ def RedefineCtypesStruct(struct, replacement):
_fields_ = transform_ctypes_fields(struct, replacement_)
NewStruct.__name__ = struct.__name__
return NewStruct
# type replacement based on name
def transform_ctypes_fields(struct, replacement):
return [(name, replacement.get(name, type)) for name, type in struct._fields_]
return [(name, replacement.get(name, type)) for name, type in struct._fields_]
def PEFile(baseaddr):
if windows.current_process.bitness == 32:
IMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG32
else:
IMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG64
class RVA(DWORD):
@property
def addr(self):
return baseaddr + self.value
def __repr__(self):
return "<DWORD {0} (RVA to '{1}')>".format(self.value, hex(self.addr))
class StringRVa(RVA):
@property
def str(self):
return ctypes.c_char_p(self.addr).value
def __repr__(self):
return "<DWORD {0} (String RVA to '{1}')>".format(self.value, self.str)
def __int__(self):
return self.value
class IMPORT_BY_NAME(ctypes.Structure):
_fields_ = [
("Hint", WORD),
("Name", BYTE)
]
]
class THUNK_DATA(ctypes.Union):
_fields_ = [
("Ordinal", PVOID),
("AddressOfData", PVOID)
]
class IATEntry(ctypes.Structure):
_fields_ = [
("value", PVOID)]
@classmethod
@classmethod
def create(cls, addr, ord, name):
self = cls.from_address(addr)
self.addr = addr
self.ord = ord
self.name = name
self.name = name
self.hook = None
self.nonhookvalue = self.value
return self
def __repr__(self):
return '<{0} "{1}" ordinal {2}>'.format(self.__class__.__name__, self.name, self.ord)
def set_hook(self, callback, types=None):
import hooks # TODO: set import at the beginning
hook = hooks.IATHook(self, callback, types)
self.hook = hook
hook.enable()
return hook
def remove_hook(self):
if self.hook is None:
return None
self.hook.disable()
self.hook = None
return True
class PEFile(object):
def __init__(self):
self.baseaddr = baseaddr
def get_DOS_HEADER(self):
return IMAGE_DOS_HEADER.from_address(baseaddr)
def get_NT_HEADER(self):
return self.get_DOS_HEADER().get_NT_HEADER()
def get_OptionalHeader(self):
return self.get_NT_HEADER().OptionalHeader
def get_DataDirectory(self):
return self.get_OptionalHeader().DataDirectory
def get_IMPORT_DESCRIPTORS(self):
import_datadir = self.get_DataDirectory()[IMAGE_DIRECTORY_ENTRY_IMPORT]
if import_datadir.VirtualAddress == 0:
@@ -117,15 +118,15 @@ def PEFile(baseaddr):
import_descriptor_addr += ctypes.sizeof(self.IMAGE_IMPORT_DESCRIPTOR)
current_import_descriptor = self.IMAGE_IMPORT_DESCRIPTOR.from_address(import_descriptor_addr)
return res
#def get_EXPORT_DIRECTORY(self):
# return self.get_OptionalHeader().get_EXPORT_DIRECTORY()
#@property
#def exports(self):
# return self.get_EXPORT_DIRECTORY().get_exports()
# TODO: get imports by parsing other modules exports if no INT
@property
def imports(self):
@@ -139,11 +140,11 @@ def PEFile(baseaddr):
iat_entry.ord = ord
res.setdefault(import_descriptor.Name.str.lower(),[]).extend(IAT)
return res
# Will be usable as `self.IMPORT_DESCRIPTOR`
class IMAGE_IMPORT_DESCRIPTOR(ctypes.Structure):
_fields_ = transform_ctypes_fields(IMAGE_IMPORT_DESCRIPTOR, {"Name" : StringRVa, "OriginalFirstThunk" : RVA, "FirstThunk" : RVA})
def get_INT(self):
if not self.OriginalFirstThunk.value:
return None
@@ -160,7 +161,7 @@ def PEFile(baseaddr):
int_addr += ctypes.sizeof(THUNK_DATA)
int_entry = THUNK_DATA.from_address(int_addr)
return res
def get_IAT(self):
iat_addr = self.FirstThunk.addr
iat_entry = THUNK_DATA.from_address(iat_addr)
@@ -169,10 +170,10 @@ def PEFile(baseaddr):
res.append(IATEntry.create(iat_addr, -1, "??"))
iat_addr += ctypes.sizeof(THUNK_DATA)
iat_entry = THUNK_DATA.from_address(iat_addr)
return res
return res
current_pe = PEFile()
class IMAGE_DOS_HEADER(ctypes.Structure):
_fields_ = [
("e_magic", CHAR * 2),
@@ -195,22 +196,22 @@ def PEFile(baseaddr):
("e_res2", WORD * 10),
("e_lfanew", DWORD),
]
def get_NT_HEADER(self):
if windows.current_process.bitness == 32:
return IMAGE_NT_HEADERS32.from_address(baseaddr + self.e_lfanew)
return IMAGE_NT_HEADERS64.from_address(baseaddr + self.e_lfanew)
#
#
# def get_EXPORT_DIRECTORY(self):
# export_directory_rva = self.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
# if export_directory_rva == 0:
# return None
# export_directory_addr = baseaddr + export_directory_rva
# return IMAGE_EXPORT_DIRECTORY.from_address(export_directory_addr)
#
#
#class IMAGE_EXPORT_DIRECTORY(ctypes.Structure):
# _fields_ = [
# ("Characteristics", DWORD),
@@ -225,7 +226,7 @@ def PEFile(baseaddr):
# ("AddressOfNames", RVA),
# ("AddressOfNameOrdinals", RVA),
# ]
#
#
# def get_exports(self):
# NameOrdinals = (WORD * self.NumberOfNames).from_address(self.AddressOfNameOrdinals.addr)
# NameOrdinals = list(NameOrdinals)
+202
View File
@@ -0,0 +1,202 @@
import struct
import ctypes
import windows
import windows.native_exec.simple_x64 as x64
from generated_def.winstructs import *
# Special code for syswow64 process
CS_32bits = 0x23
CS_64bits = 0x33
# See assembly into doc/NtCreateThreadStub_64b.asm
Pretty_NtCreateThreadStub = """
50 50 53 51 52 56 57 41 50 41 51 41 52 41 53 41
54 41 55 48 C7 C0 00 00 00 00 50 48 B8 54 68 72
65 61 64 45 78 50 48 B8 4E 74 43 72 65 61 74 65
50 4C 8B DC 48 C7 C3 61 72 79 41 53 48 BB 4C 6F
61 64 4C 69 62 72 53 4C 8B E4 65 48 8B 04 25 60
00 00 00 48 8B 40 18 48 8B 40 20 48 8B D0 48 8B
C2 48 8B 58 20 48 23 DB 74 14 48 8B 48 50 48 8B
09 81 F9 6E 00 74 00 74 0B 48 8B 10 EB E0 68 42
42 42 42 C3 8B 43 3C 48 03 C3 48 83 C0 18 8B 48
70 48 03 CB 48 8B C1 50 8B 48 18 4C 8B E9 8B 50
20 48 03 D3 48 33 C9 8B 34 8A 48 03 F3 51 49 8B
FB 48 C7 C1 11 00 00 00 F3 A6 8B C1 59 48 FF C1
85 C0 75 E3 48 FF C9 58 8B 50 24 48 03 D3 66 8B
0C 4A 48 81 E1 FF FF 00 00 8B 50 1C 48 03 D3 8B
14 8A 48 03 D3 4C 8B EA 6A 00 48 8B CC 48 C7 C2
FF FF 1F 00 49 C7 C0 00 00 00 00 49 B9 40 40 40
40 40 40 40 40 48 C7 C0 00 00 00 00 50 50 50 50
50 48 B8 42 42 42 42 42 42 42 42 50 48 B8 41 41
41 41 41 41 41 41 50 41 51 41 50 52 51 41 FF D5
48 89 84 24 E8 00 00 00 48 83 C4 40 48 83 C4 28
48 83 C4 20 41 5D 41 5C 41 5B 41 5A 41 59 41 58
5F 5E 5A 59 5B 58 58
"""
NtCreateThreadStub = Pretty_NtCreateThreadStub.replace(" ", "").replace("\n", "").decode('hex')
def genere_return_32bits_stub(ret_addr):
ret_32b = x64.MultipleInstr()
ret_32b += x64.Mov_RCX_X((CS_32bits << 32) + ret_addr)
ret_32b += x64.Push_RCX()
ret_32b += x64.Retf()
return ret_32b.get_code()
# The format of a jump to 64bits mode
dummy_jump = "\xea" + struct.pack("<I", 0) + chr(CS_64bits) + "\x00\x00"
def execute_64bits_code_from_syswow(shellcode):
if not windows.current_process.is_wow_64:
raise ValueError("Calling execute_64bits_code_from_syswow from non-syswow process")
addr = windows.k32testing.VirtualAlloc(dwSize=0x1000)
# post-exec 32bits stub (xor eax, eax; ret)
ret = "\xC3"
ret_addr = addr
shell_code_addr = ret_addr + len(ret) + len(dummy_jump)
# ljmp
jump = "\xea" + struct.pack("<I", shell_code_addr) + chr(CS_64bits) + "\x00\x00"
jump_addr = ret_addr + len(ret)
# Return to 32bits stub
shellcode += genere_return_32bits_stub(ret_addr)
# WRITE ALL THE STUBS
windows.current_process.write_memory(ret_addr, ret)
windows.current_process.write_memory(jump_addr, jump)
windows.current_process.write_memory(shell_code_addr, shellcode)
# Execute
exec_stub = ctypes.CFUNCTYPE(HRESULT)(jump_addr)
return exec_stub()
def NtCreateThreadEx_32_to_64(process, addr, param):
shellcode = NtCreateThreadStub.replace("\x40" * 8, struct.pack("<Q", process.handle))
shellcode = shellcode.replace("\x41" * 8, struct.pack("<Q", addr))
shellcode = shellcode.replace("\x42" * 8, struct.pack("<Q", param))
return execute_64bits_code_from_syswow(shellcode)
# TODO : implem remote PEB parsing
class RemotePointerBase(ULONG64):
pass
class Remote_wchar_p(RemotePointerBase):
def __init__(self, *args):
self.proc = None
super(RemotePointerImp, self).__init__(*args)
def str(self):
addr = self.value
buffer = (ctypes.c_wchar * 255)()
self.proc.read_memory_into(self.value, buffer)
return str(ctypes.c_wchar_p(buffer[:]).value)
class Remote_LIST_ENTRY_PTR(RemotePointerBase):
def __init__(self, *args):
self.proc = None
super(RemotePointerImp, self).__init__(*args)
def TO_LDR_ENTRY(self):
v = RemotePointer(LDR_DATA_TABLE_ENTRY64)(self.value - sizeof(ULONG64) * 2)
v.proc = self.proc
return v
def RemotePointer(struct):
class RemotePointerImp(RemotePointerBase):
def __init__(self, *args):
self.proc = None
super(RemotePointerImp, self).__init__(*args)
def contents(self):
if self.proc is None:
raise ValueError("Non binded :(")
s = struct(self.proc)
self.proc.read_memory_into(self.value, s)
print("set proc via contents for {0}".format(s))
return s
return RemotePointerImp
class RemoteStructure(Structure):
def __init__(self, proc):
self.proc = proc
def __getattribute__(self, value):
print(value)
if value in ["_fields_", "proc"]:
return super(RemoteStructure, self).__getattribute__(value)
d = dict(self._fields_)
t = d.get(value, type(None))
field = super(RemoteStructure, self).__getattribute__(value)
if isinstance(field, (RemoteStructure, RemotePointerBase)):
print("Set proc for {0}".format(field))
field.proc = self.proc
return field
# Struct _LSA_UNICODE_STRING definitions
class _LSA_UNICODE_STRING(RemoteStructure):
_fields_ = [
("Length", USHORT),
("MaximumLength", USHORT),
("Buffer", Remote_wchar_p),
]
PUNICODE_STRING = POINTER(_LSA_UNICODE_STRING)
UNICODE_STRING = _LSA_UNICODE_STRING
LSA_UNICODE_STRING = _LSA_UNICODE_STRING
PLSA_UNICODE_STRING = POINTER(_LSA_UNICODE_STRING)
class _LIST_ENTRY64(RemoteStructure): pass
_LIST_ENTRY64._fields_ = [
("Flink", Remote_LIST_ENTRY_PTR),
("Blink", Remote_LIST_ENTRY_PTR),
]
LIST_ENTRY64 = _LIST_ENTRY64
# Struct _LDR_DATA_TABLE_ENTRY definitions
class _LDR_DATA_TABLE_ENTRY64(RemoteStructure):
_fields_ = [
("Reserved1", ULONG64 * 2),
("InMemoryOrderLinks", _LIST_ENTRY64),
("Reserved2", ULONG64 * 2),
("DllBase", ULONG64),
("EntryPoint", ULONG64),
("Reserved3", ULONG64),
("FullDllName", UNICODE_STRING),
("BaseDllName", UNICODE_STRING),
("Reserved5", ULONG64 * 3),
("CheckSum", ULONG),
("TimeDateStamp", ULONG),
]
LDR_DATA_TABLE_ENTRY64 = _LDR_DATA_TABLE_ENTRY64
class _PEB_LDR_DATA64(RemoteStructure):
_fields_ = [
("Reserved1", BYTE * 8),
("Reserved2", ULONG64 * 3),
("InMemoryOrderModuleList", LIST_ENTRY64),
]
class _PEB64(RemoteStructure):
_fields_ = [
("Reserved1", BYTE * 2),
("BeingDebugged", BYTE),
("Reserved2", BYTE * 1),
("Reserved3", ULONG64 * 2),
("Ldr", RemotePointer(_PEB_LDR_DATA64)),
("ProcessParameters", ULONG64),
("Reserved4", BYTE * 104),
("Reserved5", ULONG64 * 52),
("PostProcessInitRoutine", ULONG64),
("Reserved6", BYTE * 128),
("Reserved7", ULONG64 * 1),
("SessionId", ULONG),
]
PEB64 = _PEB64
+101 -77
View File
@@ -21,21 +21,21 @@ class AutoHandle(object):
return self._handle
self._handle = self._get_handle()
return self._handle
def __del__(self):
if hasattr(self, "_handle"):
kernel32proxy.CloseHandle(self._handle)
kernel32proxy.CloseHandle(self._handle)
class System(object):
@property
def processes(self):
return utils.enumerate_processes()
@property
def threads(self):
return utils.enumerate_threads()
@property
def bitness(self):
if os.environ["PROCESSOR_ARCHITECTURE"].lower() != "x86":
@@ -43,38 +43,37 @@ class System(object):
if "PROCESSOR_ARCHITEW6432" in os.environ:
return 64
return 32
# May have a common class with WinProcess for is_wow_64 and stuff
class WinThread(THREADENTRY32, AutoHandle):
class WinThread(THREADENTRY32, AutoHandle):
@property
def tid(self):
return self.th32ThreadID
@property
def owner(self):
if hasattr(self, "_owner"):
return self._owner
self._owner = [process for process in utils.enumerate_processes() if process.pid == self.th32OwnerProcessID][0]
return self._owner
def _get_handle(self):
return kernel32proxy.OpenThread(dwThreadId=self.tid)
return kernel32proxy.OpenThread(dwThreadId=self.tid)
def __repr__(self):
return '<{0} {1} owner "{2}" at {3}>'.format(self.__class__.__name__, self.tid, self.owner.name, hex(id(self)))
class CurrentProcess(object):
get_peb = None
get_peb_32_code = '64a130000000c3'.decode('hex')
# mov rax,QWORD PTR gs:0x60
# ret
get_peb_64_code = "65488B042560000000C3".decode('hex')
def get_peb_builtin(self):
if self.get_peb is not None:
return self.get_peb
@@ -84,48 +83,64 @@ class CurrentProcess(object):
get_peb = native_exec.create_function(self.get_peb_64_code, [PVOID])
self.get_peb = get_peb
return get_peb
@property
@property
def peb(self):
return PEB.from_address(self.get_peb_builtin()())
@property
def bitness(self):
"""Return 32 or 64"""
import platform
bits = platform.architecture()[0]
return int(bits[:2])
@property
def is_wow_64(self):
return utils.is_wow_64(kernel32proxy.GetCurrentProcess())
return utils.is_wow_64(kernel32proxy.GetCurrentProcess())
def virtual_alloc(self, size):
return kernel32proxy.VirtualAlloc(dwSize=size)
def write_memory(self, addr, data):
buffertype = (c_char * len(data)).from_address(addr)
buffertype[:len(data)] = data
return True
def read_memory(self, addr, size):
buffer = (c_char * size).from_address(addr)
return buffer[:]
class WinProcess(PROCESSENTRY32, AutoHandle):
is_pythondll_injected = 0
is_remote_slave_running = False
@property
def name(self):
return self.szExeFile[:]
@property
@property
def pid(self):
return self.th32ProcessID
@property
def ppid(self):
return self.th32ParentProcessID
@property
def threads(self):
return [thread for thread in utils.enumerate_threads() if thread.th32OwnerProcessID == self.pid]
def _get_handle(self):
return kernel32proxy.OpenProcess(dwProcessId=self.pid)
def __repr__(self):
return '<{0} "{1}" pid {2} at {3}>'.format(self.__class__.__name__, self.name, self.pid, hex(id(self)))
@property
def is_wow_64(self):
return utils.is_wow_64(self.handle)
return utils.is_wow_64(self.handle)
@property
def bitness(self):
if windows.system.bitness == 32:
@@ -133,106 +148,115 @@ class WinProcess(PROCESSENTRY32, AutoHandle):
if self.is_wow_64:
return 32
return 64
def virtual_alloc(self, size):
return kernel32proxy.VirtualAllocEx(self.handle, dwSize=size)
def write_memory(self, addr, data):
return kernel32proxy.WriteProcessMemory(self.handle, addr, lpBuffer=data)
def low_read_memory(self, addr, buffer_addr, size):
if windows.current_process.bitness == 32 and self.bitness == 64:
NtWow64ReadVirtualMemory64Addr = windows.utils.get_func_addr("ntdll.dll", "NtWow64ReadVirtualMemory64")
NtWow64ReadVirtualMemory64 = WINFUNCTYPE(HRESULT, HANDLE, ULONG64, PVOID, ULONG64, PULONG64)(NtWow64ReadVirtualMemory64Addr)
return NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size, None)
return kernel32proxy.ReadProcessMemory(self.handle, addr, lpBuffer=buffer_addr, nSize=size)
def read_memory(self, addr, size):
return kernel32proxy.ReadProcessMemory(self.handle, addr, nSize=size)
## CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId):
#CreateRemoteThreadPrototype = WINFUNCTYPE(HANDLE, HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD)
def NtCreateThreadEx(self, addr, param):
print("CALLING SPECIAL NtCreateThreadEx")
NtCreateThreadExAddr = utils.get_func_addr("ntdll.dll", "NtCreateThreadEx")
NtCreateThreadEx = WINFUNCTYPE(HRESULT, PHANDLE, LPSECURITY_ATTRIBUTES, PVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID, BOOL, DWORD, DWORD, DWORD, PVOID)(NtCreateThreadExAddr)
thread_handle = HANDLE()
res = NtCreateThreadEx(byref(thread_handle), None, None, self.handle, addr, param, False, 0, 0, 0, None)
print("RES = {0}".format(hex(res & 0xffffffff)))
if res:
raise WinError()
def RtlCreateUserThread(self, addr, param):
print("CALLING SPECIAL RtlCreateUserThread")
RtlCreateUserThreadAddr = utils.get_func_addr("ntdll.dll", "RtlCreateUserThread")
RtlCreateUserThread = WINFUNCTYPE(HRESULT, HANDLE, LPSECURITY_ATTRIBUTES, BOOL, ULONG, PULONG, PULONG, PVOID, PVOID, PHANDLE, PVOID)(RtlCreateUserThreadAddr)
thread_handle = HANDLE()
tmp1 = DWORD()
tmp2 = DWORD()
res = RtlCreateUserThread(self.handle, None, False, 0, None, None, addr, param, None, None)
print("RES = {0}".format(hex(res & 0xffffffff)))
if res:
raise WinError()
buffer = ctypes.create_string_buffer(size)
self.low_read_memory(addr, ctypes.byref(buffer), size)
return buffer[:]
def read_memory_into(self, addr, struct):
self.low_read_memory(addr, ctypes.byref(struct), ctypes.sizeof(struct))
return struct
def create_thread(self, addr, param):
if windows.current_process.bitness == 32 and self.bitness == 64:
raise NotImplementedError("Injection 32 to 64")
return kernel32proxy.CreateRemoteThread(hProcess=self.handle, lpStartAddress=addr, lpParameter=param)
return windows.syswow64.NtCreateThreadEx_32_to_64(self, addr, param)
return kernel32proxy.CreateRemoteThread(hProcess=self.handle, lpStartAddress=addr, lpParameter=param)
def load_library(self, dll_path):
x = self.virtual_alloc(0x1000)
self.write_memory(x, dll_path)
LoadLibrary = utils.get_func_addr('kernel32', 'LoadLibraryA')
return self.create_thread(LoadLibrary, x)
def execute(self, code):
x = self.virtual_alloc(len(code))
self.write_memory(x, code)
return self.create_thread(x, 0)
def execute_python(self, pycode):
return injection.execute_python_code(self, pycode)
#def NtCreateThreadEx(self, addr, param):
# print("CALLING SPECIAL NtCreateThreadEx")
# NtCreateThreadExAddr = utils.get_func_addr("ntdll.dll", "NtCreateThreadEx")
# NtCreateThreadEx = WINFUNCTYPE(HRESULT, PHANDLE, DWORD, PVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID, BOOL, DWORD, DWORD, DWORD, PVOID)(NtCreateThreadExAddr)
# thread_handle = HANDLE()
# res = NtCreateThreadEx(byref(thread_handle), 0x1fffff, None, self.handle, addr, param, False, 0, 0, 0, None)
# print("RES = {0}".format(hex(res & 0xffffffff)))
# if res:
# raise WinError()
#
#def RtlCreateUserThread(self, addr, param):
# print("CALLING SPECIAL RtlCreateUserThread")
# RtlCreateUserThreadAddr = utils.get_func_addr("ntdll.dll", "RtlCreateUserThread")
# RtlCreateUserThread = WINFUNCTYPE(HRESULT, HANDLE, LPSECURITY_ATTRIBUTES, BOOL, ULONG, PULONG, PULONG, PVOID, PVOID, PHANDLE, PVOID)(RtlCreateUserThreadAddr)
# thread_handle = HANDLE()
# tmp1 = DWORD()
# tmp2 = DWORD()
# res = RtlCreateUserThread(self.handle, None, False, 0, None, None, addr, param, None, None)
# print("RES = {0}".format(hex(res & 0xffffffff)))
# if res:
# raise WinError()
class LoadedModule(LDR_DATA_TABLE_ENTRY):
@property
def baseaddr(self):
return self.DllBase
@property
def name(self):
return self.BaseDllName.Buffer
@property
def fullname(self):
return self.FullDllName.Buffer
def __repr__(self):
return '<{0} "{1}" at {2}>'.format(self.__class__.__name__, self.name, hex(id(self)))
@property
def pe(self):
return pe_parse.PEFile(self.baseaddr)
class WinUnicodeString(LSA_UNICODE_STRING):
def __repr__(self):
return """<{0} "{1}" at {2}>""".format(type(self).__name__, self.Buffer, hex(id(self)))
class LIST_ENTRY_PTR(PVOID):
def TO_LDR_ENTRY(self):
return LDR_DATA_TABLE_ENTRY.from_address(self.value - sizeof(PVOID) * 2)
# May want to have all known fields..
# May want to have all known fields..
class PEB(PEB):
@property
def imagepath(self):
raw_imagepath = self.ProcessParameters.contents.ImagePathName
return WinUnicodeString.from_address(ctypes.addressof(raw_imagepath))
@property
def commandline(self):
# This or changing the __repr__ of LSA_UNICODE_STRING
raw_cmd = self.ProcessParameters.contents.CommandLine
return WinUnicodeString.from_address(ctypes.addressof(raw_cmd))
@property
def modules(self):
res = []