mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add TCP connections + Syswow64 injection
This commit is contained in:
+32
-1
@@ -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)
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 = []
|
||||
|
||||
Reference in New Issue
Block a user