mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add LOT of doc + play on vertored exception
This commit is contained in:
+16
-2
@@ -1,8 +1,22 @@
|
||||
"""
|
||||
Windows for Python
|
||||
A lot of python object to help navigate windows stuff
|
||||
|
||||
Exported:
|
||||
|
||||
system : :class:`windows.winobject.System`
|
||||
|
||||
current_process : :class:`windows.winobject.CurrentProcess`
|
||||
|
||||
current_thread : :class:`windows.winobject.CurrentThread`
|
||||
"""
|
||||
|
||||
import k32testing
|
||||
from winobject import System, CurrentProcess
|
||||
from winobject import System, CurrentProcess, CurrentThread
|
||||
from utils import VirtualProtected
|
||||
|
||||
system = System()
|
||||
current_process = CurrentProcess()
|
||||
current_thread = CurrentThread()
|
||||
|
||||
__all__ = ["system", "VirtualProtected", 'current_process']
|
||||
__all__ = ["system", "VirtualProtected", 'current_process', 'current_thread']
|
||||
@@ -0,0 +1,151 @@
|
||||
.CODE
|
||||
|
||||
start:
|
||||
|
||||
MY_FUNC PROC
|
||||
call func
|
||||
ret
|
||||
func:
|
||||
push rax ;Padding for calling alligned on 16 bytes + ret value
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
;TODO save the QUEEN (and the registers !)
|
||||
mov rax, 5050505050505050h ; libname
|
||||
mov r11, rax
|
||||
mov rax, 5151515151515151h ; function name
|
||||
mov r12, rax
|
||||
;String pushed !
|
||||
mov rax, GS:[60h] ; PEB
|
||||
mov rax, [rax + 6 * 4] ; RAX = ldr (+ 6 for 64 cause of 2 ptr)
|
||||
mov rax, [rax + 8 * 4] ; RAX on the first elt of the list (first module)
|
||||
mov rdx, rax
|
||||
a_dest:
|
||||
mov rax, rdx
|
||||
mov rbx, [rax + 4 * 8] ;RBX : first base ! (base of current module)
|
||||
and rbx, rbx ;If no more Module : not fail = fail
|
||||
jz a_fail
|
||||
mov rcx, [rax + 10 * 8] ;RCX = NAME (UNICODE_STRING.Buffer)
|
||||
|
||||
mov rdi, rcx
|
||||
call strlen
|
||||
mov rdi, rcx ; set RDI to good value
|
||||
mov rcx, rax
|
||||
mov rsi, r11
|
||||
repe cmpsw ;cmp with current dll name (unicode)
|
||||
test rcx, rcx
|
||||
jz dll_found
|
||||
mov rdx, [rdx]
|
||||
jmp a_dest
|
||||
a_fail:
|
||||
push 42424242h
|
||||
ret
|
||||
dll_found: ;Cool ! : here rbx = base
|
||||
mov eax, [rbx + 15 * 4] ;rax = PEBASE RVA
|
||||
add rax, rbx ;RAX = PEBASE
|
||||
add rax, 24 ;OPTIONAL HEADER
|
||||
mov ecx, [rax + 112] ;rcx = RVA export dir
|
||||
add rcx, rbx ;rcx = export_dir
|
||||
mov rax, rcx ;RAX = export_dir
|
||||
push rax ;Save it for after function search
|
||||
; EBX = BASE | EAX = EXPORT DIR
|
||||
mov ecx, [rax + 6 * 4]
|
||||
mov r13, rcx ;r13 = NB names
|
||||
mov edx, [rax + 8 * 4] ; EDX = names array RVA
|
||||
add rdx, rbx
|
||||
xor rcx, rcx
|
||||
|
||||
search_loop:
|
||||
mov esi, [rdx + rcx * 4] ;Get function name RVA
|
||||
add rsi, rbx ;Get name addr
|
||||
push rcx ;Save current index (could use x64 register)
|
||||
mov rdi, r11
|
||||
mov rcx, 17 ;We know we want NtCreateThreadEx
|
||||
repe cmpsb ;cmp with current export
|
||||
mov eax, ecx
|
||||
pop rcx ;Restore current function index
|
||||
inc rcx
|
||||
test eax, eax
|
||||
jnz search_loop ;If not found not handled : WTF GetProcAddress not in Kernel32...
|
||||
; Func found !
|
||||
dec rcx
|
||||
; rcx is offset of the name, need to find the offset of the function
|
||||
pop rax ;Restore export_dir addr
|
||||
mov edx, [rax + 9 * 4] ;EDX = AddressOfNameOrdinals RVX
|
||||
add rdx, rbx ;AddressOfNameOrdinals + base
|
||||
mov cx, [rdx + rcx * 2] ; ecx = Ieme ordinal (short array)
|
||||
and rcx, 0ffffh
|
||||
mov edx, [rax + 7 * 4] ; AddressOfFunctions RVA
|
||||
add rdx, rbx ; AddressOfFunctions + base
|
||||
mov edx, [rdx + rcx * 4] ;functions[ecx] -> functions[ordinals[i]]
|
||||
add rdx, rbx
|
||||
mov r13, rdx ; r13 : REAL FUNC ADD
|
||||
|
||||
; room for the thread handle
|
||||
push 0
|
||||
mov rcx, rsp ; arg1
|
||||
mov rdx, 1fffffh ; arg2
|
||||
mov r8, 0h ; arg3
|
||||
mov r9, 4040404040404040h ; arg4 (handle)
|
||||
|
||||
mov rax, 0h
|
||||
push rax ; arg11
|
||||
push rax ; arg10
|
||||
push rax ; arg9
|
||||
push rax ; arg8
|
||||
push rax ; arg7
|
||||
mov rax, 4242424242424242h
|
||||
push rax ; arg6 (param)
|
||||
mov rax, 4141414141414141h
|
||||
push rax ; arg5 (addr)
|
||||
|
||||
; reserve space for register (calling convention)
|
||||
push r9
|
||||
push r8
|
||||
push rdx
|
||||
push rcx
|
||||
call r13
|
||||
; Write return value in first stack value pushed
|
||||
mov [rsp + 29 * 8], rax
|
||||
; TODO CLEAN stack :D
|
||||
add rsp, 8 * 8
|
||||
add rsp, 32 + 8
|
||||
add rsp, 32
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
pop rax ; Return value
|
||||
ret
|
||||
strlen:; arg in RDI
|
||||
push rcx
|
||||
xor rax, rax
|
||||
xor rcx, rcx
|
||||
dec rcx
|
||||
repne scasw
|
||||
not rcx
|
||||
dec rcx
|
||||
mov rax, rcx
|
||||
pop rcx
|
||||
ret
|
||||
MY_FUNC ENDP
|
||||
END
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
.CODE
|
||||
|
||||
start:
|
||||
|
||||
MY_FUNC PROC
|
||||
push rax ;Padding for calling alligned on 16 bytes + ret value
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
;TODO save the QUEEN (and the registers !)
|
||||
mov rax, 0h
|
||||
push rax
|
||||
mov rax, 7845646165726854h
|
||||
push rax
|
||||
mov rax, 657461657243744eh
|
||||
push rax
|
||||
mov r11, rsp ;R11 NtCreateThreadEx
|
||||
mov rbx, 41797261h
|
||||
push rbx
|
||||
mov rbx, 7262694c64616f4ch
|
||||
push rbx
|
||||
mov r12, rsp ;R12 : LoadLib
|
||||
;String pushed !
|
||||
;mov rax, 0x60
|
||||
;GS mov rax, [rax] ;PEB!
|
||||
mov rax, GS:[60h]
|
||||
mov rax, [rax + 6 * 4] ; RAX = ldr (+ 6 for 64 cause of 2 ptr)
|
||||
mov rax, [rax + 8 * 4] ; RAX on the first elt of the list (first module)
|
||||
mov rdx, rax
|
||||
a_dest:
|
||||
mov rax, rdx
|
||||
mov rbx, [rax + 4 * 8] ;RBX : first base ! (base of current module)
|
||||
and rbx, rbx ;If no more Module : not fail = fail
|
||||
jz a_fail
|
||||
mov rcx, [rax + 10 * 8] ;RCX = NAME (UNICODE_STRING.Buffer)
|
||||
|
||||
mov rcx, [rcx] ;GET WCHAR
|
||||
cmp ecx, 74006eh ;ntdll if : ecx == 74006eh (nt unicode)
|
||||
jz dll_found
|
||||
mov rdx, [rax]
|
||||
jmp a_dest
|
||||
a_fail:
|
||||
push 42424242h
|
||||
ret
|
||||
dll_found: ;Cool ! : here rbx = base
|
||||
mov eax, [rbx + 15 * 4] ;rax = PEBASE RVA
|
||||
add rax, rbx ;RAX = PEBASE
|
||||
add rax, 24 ;OPTIONAL HEADER
|
||||
mov ecx, [rax + 112] ;rcx = RVA export dir
|
||||
add rcx, rbx ;rcx = export_dir
|
||||
mov rax, rcx ;RAX = export_dir
|
||||
push rax ;Save it for after function search
|
||||
; EBX = BASE | EAX = EXPORT DIR
|
||||
mov ecx, [rax + 6 * 4]
|
||||
mov r13, rcx ;r13 = NB names
|
||||
mov edx, [rax + 8 * 4] ; EDX = names array RVA
|
||||
add rdx, rbx
|
||||
xor rcx, rcx
|
||||
search_loop:
|
||||
mov esi, [rdx + rcx * 4] ;Get function name RVA
|
||||
add rsi, rbx ;Get name addr
|
||||
push rcx ;Save current index (could use x64 register)
|
||||
mov rdi, r11
|
||||
mov rcx, 17 ;We know we want NtCreateThreadEx
|
||||
repe cmpsb ;cmp with current export
|
||||
mov eax, ecx
|
||||
pop rcx ;Restore current function index
|
||||
inc rcx
|
||||
test eax, eax
|
||||
jnz search_loop ;If not found not handled : WTF GetProcAddress not in Kernel32...
|
||||
; Func found !
|
||||
dec rcx
|
||||
; rcx is offset of the name, need to find the offset of the function
|
||||
pop rax ;Restore export_dir addr
|
||||
mov edx, [rax + 9 * 4] ;EDX = AddressOfNameOrdinals RVX
|
||||
add rdx, rbx ;AddressOfNameOrdinals + base
|
||||
mov cx, [rdx + rcx * 2] ; ecx = Ieme ordinal (short array)
|
||||
and rcx, 0ffffh
|
||||
mov edx, [rax + 7 * 4] ; AddressOfFunctions RVA
|
||||
add rdx, rbx ; AddressOfFunctions + base
|
||||
mov edx, [rdx + rcx * 4] ;functions[ecx] -> functions[ordinals[i]]
|
||||
add rdx, rbx
|
||||
mov r13, rdx ; r13 : REAL FUNC ADD
|
||||
|
||||
|
||||
; room for the thread handle
|
||||
push 0
|
||||
mov rcx, rsp ; arg1
|
||||
mov rdx, 1fffffh ; arg2
|
||||
mov r8, 0h ; arg3
|
||||
mov r9, 4040404040404040h ; arg4 (handle)
|
||||
|
||||
mov rax, 0h
|
||||
push rax ; arg11
|
||||
push rax ; arg10
|
||||
push rax ; arg9
|
||||
push rax ; arg8
|
||||
push rax ; arg7
|
||||
mov rax, 4242424242424242h
|
||||
push rax ; arg6 (param)
|
||||
mov rax, 4141414141414141h
|
||||
push rax ; arg5 (addr)
|
||||
|
||||
; reserve space for register (calling convention)
|
||||
push r9
|
||||
push r8
|
||||
push rdx
|
||||
push rcx
|
||||
call r13
|
||||
; Write return value in first stack value pushed
|
||||
mov [rsp + 29 * 8], rax
|
||||
; TODO CLEAN stack :D
|
||||
add rsp, 8 * 8
|
||||
add rsp, 32 + 8
|
||||
add rsp, 32
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
pop rax ; Return value
|
||||
|
||||
MY_FUNC ENDP
|
||||
END
|
||||
@@ -0,0 +1,27 @@
|
||||
import windows
|
||||
import winstructs
|
||||
|
||||
def bitness():
|
||||
"""Return 32 or 64"""
|
||||
import platform
|
||||
bits = platform.architecture()[0]
|
||||
return int(bits[:2])
|
||||
|
||||
# Use windows.current_process.bitness ? need to fix problem of this imported before the creation of windows.current_process
|
||||
if bitness() == 32:
|
||||
winstructs.CONTEXT = winstructs.CONTEXT32
|
||||
winstructs.PCONTEXT = winstructs.PCONTEXT32
|
||||
winstructs.LPCONTEXT = winstructs.LPCONTEXT32
|
||||
|
||||
winstructs.EXCEPTION_POINTERS = winstructs.EXCEPTION_POINTERS32
|
||||
winstructs.PEXCEPTION_POINTERS = winstructs.PEXCEPTION_POINTERS32
|
||||
else:
|
||||
winstructs.CONTEXT = winstructs.CONTEXT64
|
||||
winstructs.PCONTEXT = winstructs.PCONTEXT64
|
||||
winstructs.LPCONTEXT = winstructs.LPCONTEXT64
|
||||
|
||||
winstructs.EXCEPTION_POINTERS = winstructs.EXCEPTION_POINTERS64
|
||||
winstructs.PEXCEPTION_POINTERS = winstructs.PEXCEPTION_POINTERS64
|
||||
|
||||
import winfuncs
|
||||
|
||||
|
||||
+88
-1
@@ -9,6 +9,8 @@ class Flag(long):
|
||||
|
||||
def __repr__(self):
|
||||
return "{0}({1})".format(self.name, hex(self))
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
NULL = Flag("NULL", 0)
|
||||
MAX_PATH = Flag("MAX_PATH", 260)
|
||||
@@ -16,6 +18,7 @@ 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)
|
||||
INFINITE = Flag("INFINITE", 0xFFFFFFFF)
|
||||
STD_INPUT_HANDLE = Flag("STD_INPUT_HANDLE", -10)
|
||||
STD_OUTPUT_HANDLE = Flag("STD_OUTPUT_HANDLE", -11)
|
||||
STD_ERROR_HANDLE = Flag("STD_ERROR_HANDLE", -12)
|
||||
@@ -273,4 +276,88 @@ 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)
|
||||
AF_NETDES = Flag("AF_NETDES", 28)
|
||||
EXCEPTION_NONCONTINUABLE = Flag("EXCEPTION_NONCONTINUABLE", 0x1)
|
||||
EXCEPTION_MAXIMUM_PARAMETERS = Flag("EXCEPTION_MAXIMUM_PARAMETERS", 15)
|
||||
STATUS_WAIT_0 = Flag("STATUS_WAIT_0", ( 0x00000000 ))
|
||||
STATUS_ABANDONED_WAIT_0 = Flag("STATUS_ABANDONED_WAIT_0", ( 0x00000080 ))
|
||||
STATUS_USER_APC = Flag("STATUS_USER_APC", ( 0x000000C0 ))
|
||||
STATUS_TIMEOUT = Flag("STATUS_TIMEOUT", ( 0x00000102 ))
|
||||
STATUS_PENDING = Flag("STATUS_PENDING", ( 0x00000103 ))
|
||||
DBG_EXCEPTION_HANDLED = Flag("DBG_EXCEPTION_HANDLED", ( 0x00010001 ))
|
||||
DBG_CONTINUE = Flag("DBG_CONTINUE", ( 0x00010002 ))
|
||||
STATUS_SEGMENT_NOTIFICATION = Flag("STATUS_SEGMENT_NOTIFICATION", ( 0x40000005 ))
|
||||
DBG_TERMINATE_THREAD = Flag("DBG_TERMINATE_THREAD", ( 0x40010003 ))
|
||||
DBG_TERMINATE_PROCESS = Flag("DBG_TERMINATE_PROCESS", ( 0x40010004 ))
|
||||
DBG_CONTROL_C = Flag("DBG_CONTROL_C", ( 0x40010005 ))
|
||||
DBG_PRINTEXCEPTION_C = Flag("DBG_PRINTEXCEPTION_C", ( 0x40010006 ))
|
||||
DBG_RIPEXCEPTION = Flag("DBG_RIPEXCEPTION", ( 0x40010007 ))
|
||||
DBG_CONTROL_BREAK = Flag("DBG_CONTROL_BREAK", ( 0x40010008 ))
|
||||
DBG_COMMAND_EXCEPTION = Flag("DBG_COMMAND_EXCEPTION", ( 0x40010009 ))
|
||||
STATUS_GUARD_PAGE_VIOLATION = Flag("STATUS_GUARD_PAGE_VIOLATION", ( 0x80000001 ))
|
||||
STATUS_DATATYPE_MISALIGNMENT = Flag("STATUS_DATATYPE_MISALIGNMENT", ( 0x80000002 ))
|
||||
STATUS_BREAKPOINT = Flag("STATUS_BREAKPOINT", ( 0x80000003 ))
|
||||
STATUS_SINGLE_STEP = Flag("STATUS_SINGLE_STEP", ( 0x80000004 ))
|
||||
STATUS_LONGJUMP = Flag("STATUS_LONGJUMP", ( 0x80000026 ))
|
||||
STATUS_UNWIND_CONSOLIDATE = Flag("STATUS_UNWIND_CONSOLIDATE", ( 0x80000029 ))
|
||||
DBG_EXCEPTION_NOT_HANDLED = Flag("DBG_EXCEPTION_NOT_HANDLED", ( 0x80010001 ))
|
||||
STATUS_ACCESS_VIOLATION = Flag("STATUS_ACCESS_VIOLATION", ( 0xC0000005 ))
|
||||
STATUS_IN_PAGE_ERROR = Flag("STATUS_IN_PAGE_ERROR", ( 0xC0000006 ))
|
||||
STATUS_INVALID_HANDLE = Flag("STATUS_INVALID_HANDLE", ( 0xC0000008 ))
|
||||
STATUS_INVALID_PARAMETER = Flag("STATUS_INVALID_PARAMETER", ( 0xC000000D ))
|
||||
STATUS_NO_MEMORY = Flag("STATUS_NO_MEMORY", ( 0xC0000017 ))
|
||||
STATUS_ILLEGAL_INSTRUCTION = Flag("STATUS_ILLEGAL_INSTRUCTION", ( 0xC000001D ))
|
||||
STATUS_NONCONTINUABLE_EXCEPTION = Flag("STATUS_NONCONTINUABLE_EXCEPTION", ( 0xC0000025 ))
|
||||
STATUS_INVALID_DISPOSITION = Flag("STATUS_INVALID_DISPOSITION", ( 0xC0000026 ))
|
||||
STATUS_ARRAY_BOUNDS_EXCEEDED = Flag("STATUS_ARRAY_BOUNDS_EXCEEDED", ( 0xC000008C ))
|
||||
STATUS_FLOAT_DENORMAL_OPERAND = Flag("STATUS_FLOAT_DENORMAL_OPERAND", ( 0xC000008D ))
|
||||
STATUS_FLOAT_DIVIDE_BY_ZERO = Flag("STATUS_FLOAT_DIVIDE_BY_ZERO", ( 0xC000008E ))
|
||||
STATUS_FLOAT_INEXACT_RESULT = Flag("STATUS_FLOAT_INEXACT_RESULT", ( 0xC000008F ))
|
||||
STATUS_FLOAT_INVALID_OPERATION = Flag("STATUS_FLOAT_INVALID_OPERATION", ( 0xC0000090 ))
|
||||
STATUS_FLOAT_OVERFLOW = Flag("STATUS_FLOAT_OVERFLOW", ( 0xC0000091 ))
|
||||
STATUS_FLOAT_STACK_CHECK = Flag("STATUS_FLOAT_STACK_CHECK", ( 0xC0000092 ))
|
||||
STATUS_FLOAT_UNDERFLOW = Flag("STATUS_FLOAT_UNDERFLOW", ( 0xC0000093 ))
|
||||
STATUS_INTEGER_DIVIDE_BY_ZERO = Flag("STATUS_INTEGER_DIVIDE_BY_ZERO", ( 0xC0000094 ))
|
||||
STATUS_INTEGER_OVERFLOW = Flag("STATUS_INTEGER_OVERFLOW", ( 0xC0000095 ))
|
||||
STATUS_PRIVILEGED_INSTRUCTION = Flag("STATUS_PRIVILEGED_INSTRUCTION", ( 0xC0000096 ))
|
||||
STATUS_STACK_OVERFLOW = Flag("STATUS_STACK_OVERFLOW", ( 0xC00000FD ))
|
||||
STATUS_DLL_NOT_FOUND = Flag("STATUS_DLL_NOT_FOUND", ( 0xC0000135 ))
|
||||
STATUS_ORDINAL_NOT_FOUND = Flag("STATUS_ORDINAL_NOT_FOUND", ( 0xC0000138 ))
|
||||
STATUS_ENTRYPOINT_NOT_FOUND = Flag("STATUS_ENTRYPOINT_NOT_FOUND", ( 0xC0000139 ))
|
||||
STATUS_CONTROL_C_EXIT = Flag("STATUS_CONTROL_C_EXIT", ( 0xC000013A ))
|
||||
STATUS_DLL_INIT_FAILED = Flag("STATUS_DLL_INIT_FAILED", ( 0xC0000142 ))
|
||||
STATUS_FLOAT_MULTIPLE_FAULTS = Flag("STATUS_FLOAT_MULTIPLE_FAULTS", ( 0xC00002B4 ))
|
||||
STATUS_FLOAT_MULTIPLE_TRAPS = Flag("STATUS_FLOAT_MULTIPLE_TRAPS", ( 0xC00002B5 ))
|
||||
STATUS_REG_NAT_CONSUMPTION = Flag("STATUS_REG_NAT_CONSUMPTION", ( 0xC00002C9 ))
|
||||
STATUS_STACK_BUFFER_OVERRUN = Flag("STATUS_STACK_BUFFER_OVERRUN", ( 0xC0000409 ))
|
||||
STATUS_INVALID_CRUNTIME_PARAMETER = Flag("STATUS_INVALID_CRUNTIME_PARAMETER", ( 0xC0000417 ))
|
||||
STATUS_ASSERTION_FAILURE = Flag("STATUS_ASSERTION_FAILURE", ( 0xC0000420 ))
|
||||
WAIT_IO_COMPLETION = Flag("WAIT_IO_COMPLETION", STATUS_USER_APC)
|
||||
STILL_ACTIVE = Flag("STILL_ACTIVE", STATUS_PENDING)
|
||||
EXCEPTION_ACCESS_VIOLATION = Flag("EXCEPTION_ACCESS_VIOLATION", STATUS_ACCESS_VIOLATION)
|
||||
EXCEPTION_DATATYPE_MISALIGNMENT = Flag("EXCEPTION_DATATYPE_MISALIGNMENT", STATUS_DATATYPE_MISALIGNMENT)
|
||||
EXCEPTION_BREAKPOINT = Flag("EXCEPTION_BREAKPOINT", STATUS_BREAKPOINT)
|
||||
EXCEPTION_SINGLE_STEP = Flag("EXCEPTION_SINGLE_STEP", STATUS_SINGLE_STEP)
|
||||
EXCEPTION_ARRAY_BOUNDS_EXCEEDED = Flag("EXCEPTION_ARRAY_BOUNDS_EXCEEDED", STATUS_ARRAY_BOUNDS_EXCEEDED)
|
||||
EXCEPTION_FLT_DENORMAL_OPERAND = Flag("EXCEPTION_FLT_DENORMAL_OPERAND", STATUS_FLOAT_DENORMAL_OPERAND)
|
||||
EXCEPTION_FLT_DIVIDE_BY_ZERO = Flag("EXCEPTION_FLT_DIVIDE_BY_ZERO", STATUS_FLOAT_DIVIDE_BY_ZERO)
|
||||
EXCEPTION_FLT_INEXACT_RESULT = Flag("EXCEPTION_FLT_INEXACT_RESULT", STATUS_FLOAT_INEXACT_RESULT)
|
||||
EXCEPTION_FLT_INVALID_OPERATION = Flag("EXCEPTION_FLT_INVALID_OPERATION", STATUS_FLOAT_INVALID_OPERATION)
|
||||
EXCEPTION_FLT_OVERFLOW = Flag("EXCEPTION_FLT_OVERFLOW", STATUS_FLOAT_OVERFLOW)
|
||||
EXCEPTION_FLT_STACK_CHECK = Flag("EXCEPTION_FLT_STACK_CHECK", STATUS_FLOAT_STACK_CHECK)
|
||||
EXCEPTION_FLT_UNDERFLOW = Flag("EXCEPTION_FLT_UNDERFLOW", STATUS_FLOAT_UNDERFLOW)
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO = Flag("EXCEPTION_INT_DIVIDE_BY_ZERO", STATUS_INTEGER_DIVIDE_BY_ZERO)
|
||||
EXCEPTION_INT_OVERFLOW = Flag("EXCEPTION_INT_OVERFLOW", STATUS_INTEGER_OVERFLOW)
|
||||
EXCEPTION_PRIV_INSTRUCTION = Flag("EXCEPTION_PRIV_INSTRUCTION", STATUS_PRIVILEGED_INSTRUCTION)
|
||||
EXCEPTION_IN_PAGE_ERROR = Flag("EXCEPTION_IN_PAGE_ERROR", STATUS_IN_PAGE_ERROR)
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION = Flag("EXCEPTION_ILLEGAL_INSTRUCTION", STATUS_ILLEGAL_INSTRUCTION)
|
||||
EXCEPTION_NONCONTINUABLE_EXCEPTION = Flag("EXCEPTION_NONCONTINUABLE_EXCEPTION", STATUS_NONCONTINUABLE_EXCEPTION)
|
||||
EXCEPTION_STACK_OVERFLOW = Flag("EXCEPTION_STACK_OVERFLOW", STATUS_STACK_OVERFLOW)
|
||||
EXCEPTION_INVALID_DISPOSITION = Flag("EXCEPTION_INVALID_DISPOSITION", STATUS_INVALID_DISPOSITION)
|
||||
EXCEPTION_GUARD_PAGE = Flag("EXCEPTION_GUARD_PAGE", STATUS_GUARD_PAGE_VIOLATION)
|
||||
EXCEPTION_INVALID_HANDLE = Flag("EXCEPTION_INVALID_HANDLE", STATUS_INVALID_HANDLE)
|
||||
EXCEPTION_POSSIBLE_DEADLOCK = Flag("EXCEPTION_POSSIBLE_DEADLOCK", STATUS_POSSIBLE_DEADLOCK)
|
||||
CONTROL_C_EXIT = Flag("CONTROL_C_EXIT", STATUS_CONTROL_C_EXIT)
|
||||
EXCEPTION_EXECUTE_HANDLER = Flag("EXCEPTION_EXECUTE_HANDLER", 1)
|
||||
EXCEPTION_CONTINUE_SEARCH = Flag("EXCEPTION_CONTINUE_SEARCH", 0)
|
||||
EXCEPTION_CONTINUE_EXECUTION = Flag("EXCEPTION_CONTINUE_EXECUTION", -1)
|
||||
@@ -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', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry']
|
||||
functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', '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', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject']
|
||||
|
||||
# ExitProcess(uExitCode):
|
||||
ExitProcessPrototype = WINFUNCTYPE(VOID, UINT)
|
||||
@@ -53,6 +53,10 @@ GetModuleFileNameAParams = ((1, 'hModule'), (1, 'lpFilename'), (1, 'nSize'))
|
||||
GetModuleFileNameWPrototype = WINFUNCTYPE(DWORD, HMODULE, LPWSTR, DWORD)
|
||||
GetModuleFileNameWParams = ((1, 'hModule'), (1, 'lpFilename'), (1, 'nSize'))
|
||||
|
||||
# CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId):
|
||||
CreateThreadPrototype = WINFUNCTYPE(HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD)
|
||||
CreateThreadParams = ((1, 'lpThreadAttributes'), (1, 'dwStackSize'), (1, 'lpStartAddress'), (1, 'lpParameter'), (1, 'dwCreationFlags'), (1, 'lpThreadId'))
|
||||
|
||||
# CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId):
|
||||
CreateRemoteThreadPrototype = WINFUNCTYPE(HANDLE, HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD)
|
||||
CreateRemoteThreadParams = ((1, 'hProcess'), (1, 'lpThreadAttributes'), (1, 'dwStackSize'), (1, 'lpStartAddress'), (1, 'lpParameter'), (1, 'dwCreationFlags'), (1, 'lpThreadId'))
|
||||
@@ -74,7 +78,7 @@ GetThreadContextPrototype = WINFUNCTYPE(BOOL, HANDLE, LPCONTEXT)
|
||||
GetThreadContextParams = ((1, 'hThread'), (1, 'lpContext'))
|
||||
|
||||
# SetThreadContext(hThread, lpContext):
|
||||
SetThreadContextPrototype = WINFUNCTYPE(BOOL, HANDLE, POINTER(CONTEXT))
|
||||
SetThreadContextPrototype = WINFUNCTYPE(BOOL, HANDLE, LPCONTEXT)
|
||||
SetThreadContextParams = ((1, 'hThread'), (1, 'lpContext'))
|
||||
|
||||
# OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId):
|
||||
@@ -189,6 +193,10 @@ GetVersionParams = ()
|
||||
GetCurrentThreadPrototype = WINFUNCTYPE(HANDLE)
|
||||
GetCurrentThreadParams = ()
|
||||
|
||||
# GetCurrentThreadId():
|
||||
GetCurrentThreadIdPrototype = WINFUNCTYPE(DWORD)
|
||||
GetCurrentThreadIdParams = ()
|
||||
|
||||
# GetCurrentProcessorNumber():
|
||||
GetCurrentProcessorNumberPrototype = WINFUNCTYPE(DWORD)
|
||||
GetCurrentProcessorNumberParams = ()
|
||||
@@ -225,3 +233,35 @@ GetExtendedUdpTableParams = ((1, 'pUdpTable'), (1, 'pdwSize'), (1, 'bOrder'), (1
|
||||
SetTcpEntryPrototype = WINFUNCTYPE(DWORD, PMIB_TCPROW)
|
||||
SetTcpEntryParams = ((1, 'pTcpRow'),)
|
||||
|
||||
# AddVectoredContinueHandler(FirstHandler, VectoredHandler):
|
||||
AddVectoredContinueHandlerPrototype = WINFUNCTYPE(PVOID, ULONG, PVECTORED_EXCEPTION_HANDLER)
|
||||
AddVectoredContinueHandlerParams = ((1, 'FirstHandler'), (1, 'VectoredHandler'))
|
||||
|
||||
# AddVectoredExceptionHandler(FirstHandler, VectoredHandler):
|
||||
AddVectoredExceptionHandlerPrototype = WINFUNCTYPE(PVOID, ULONG, PVECTORED_EXCEPTION_HANDLER)
|
||||
AddVectoredExceptionHandlerParams = ((1, 'FirstHandler'), (1, 'VectoredHandler'))
|
||||
|
||||
# TerminateThread(hThread, dwExitCode):
|
||||
TerminateThreadPrototype = WINFUNCTYPE(BOOL, HANDLE, DWORD)
|
||||
TerminateThreadParams = ((1, 'hThread'), (1, 'dwExitCode'))
|
||||
|
||||
# ExitThread(dwExitCode):
|
||||
ExitThreadPrototype = WINFUNCTYPE(VOID, DWORD)
|
||||
ExitThreadParams = ((1, 'dwExitCode'),)
|
||||
|
||||
# RemoveVectoredExceptionHandler(Handler):
|
||||
RemoveVectoredExceptionHandlerPrototype = WINFUNCTYPE(ULONG, PVOID)
|
||||
RemoveVectoredExceptionHandlerParams = ((1, 'Handler'),)
|
||||
|
||||
# ResumeThread(hThread):
|
||||
ResumeThreadPrototype = WINFUNCTYPE(DWORD, HANDLE)
|
||||
ResumeThreadParams = ((1, 'hThread'),)
|
||||
|
||||
# SuspendThread(hThread):
|
||||
SuspendThreadPrototype = WINFUNCTYPE(DWORD, HANDLE)
|
||||
SuspendThreadParams = ((1, 'hThread'),)
|
||||
|
||||
# WaitForSingleObject(hHandle, dwMilliseconds):
|
||||
WaitForSingleObjectPrototype = WINFUNCTYPE(DWORD, HANDLE, DWORD)
|
||||
WaitForSingleObjectParams = ((1, 'hHandle'), (1, 'dwMilliseconds'))
|
||||
|
||||
|
||||
+155
-7
@@ -18,13 +18,17 @@ CHAR = c_char
|
||||
UCHAR = c_char
|
||||
FARPROC = PVOID
|
||||
HGLOBAL = PVOID
|
||||
PVECTORED_EXCEPTION_HANDLER = PVOID
|
||||
ULONGLONG = c_ulonglong
|
||||
LONGLONG = c_longlong
|
||||
ULONG64 = c_ulonglong
|
||||
DWORD64 = ULONG64
|
||||
PULONG64 = POINTER(ULONG64)
|
||||
PHANDLE = POINTER(HANDLE)
|
||||
LPCONTEXT = PVOID
|
||||
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', '_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']
|
||||
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', '_CONTEXT32', '_M128A', '_CONTEXT64', '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', '_EXCEPTION_RECORD', '_EXCEPTION_POINTERS64', '_EXCEPTION_POINTERS32']
|
||||
|
||||
enums = ['_SYSTEM_INFORMATION_CLASS', '_TCP_TABLE_CLASS', '_UDP_TABLE_CLASS', '_MIB_TCP_STATE']
|
||||
|
||||
@@ -153,22 +157,53 @@ MIB_TCP_STATE_TIME_WAIT = 0xb
|
||||
MIB_TCP_STATE_DELETE_TCB = 0xc
|
||||
# Struct _LIST_ENTRY definitions
|
||||
# Self referencing struct tricks
|
||||
|
||||
import ctypes
|
||||
|
||||
def pretty_print_ctypes_type(t):
|
||||
format = "{0}"
|
||||
if issubclass(t, ctypes.Array):
|
||||
format = "[{0}" + "* {0}]".format(t._length_)
|
||||
t = t._type_
|
||||
|
||||
if issubclass(t, ctypes._Pointer):
|
||||
format = format.format("Pointer({0})")
|
||||
t = t._type_
|
||||
|
||||
if issubclass(t, ctypes.Structure):
|
||||
return format.format(":class:`{0}`".format(t.__name__))
|
||||
return t
|
||||
|
||||
def autodoc_ctypes_struct(struct):
|
||||
doc = ["fields:"]
|
||||
for name, type in struct._fields_:
|
||||
doc.append(" {0} -> {1}".format(name, pretty_print_ctypes_type(type)))
|
||||
|
||||
struct.__doc__ = "\n\n".join(doc)
|
||||
return struct
|
||||
|
||||
|
||||
class _LIST_ENTRY(Structure): pass
|
||||
_LIST_ENTRY._fields_ = [
|
||||
("Flink", POINTER(_LIST_ENTRY)),
|
||||
("Blink", POINTER(_LIST_ENTRY)),
|
||||
]
|
||||
|
||||
_LIST_ENTRY = autodoc_ctypes_struct(_LIST_ENTRY)
|
||||
|
||||
PLIST_ENTRY = POINTER(_LIST_ENTRY)
|
||||
LIST_ENTRY = _LIST_ENTRY
|
||||
PRLIST_ENTRY = POINTER(_LIST_ENTRY)
|
||||
|
||||
# Struct _PEB_LDR_DATA definitions
|
||||
@autodoc_ctypes_struct
|
||||
class _PEB_LDR_DATA(Structure):
|
||||
_fields_ = [
|
||||
_fields_ = [
|
||||
("Reserved1", BYTE * 8),
|
||||
("Reserved2", PVOID * 3),
|
||||
("InMemoryOrderModuleList", LIST_ENTRY),
|
||||
]
|
||||
|
||||
PPEB_LDR_DATA = POINTER(_PEB_LDR_DATA)
|
||||
PEB_LDR_DATA = _PEB_LDR_DATA
|
||||
|
||||
@@ -196,6 +231,7 @@ PRTL_USER_PROCESS_PARAMETERS = POINTER(_RTL_USER_PROCESS_PARAMETERS)
|
||||
RTL_USER_PROCESS_PARAMETERS = _RTL_USER_PROCESS_PARAMETERS
|
||||
|
||||
# Struct _PEB definitions
|
||||
@autodoc_ctypes_struct
|
||||
class _PEB(Structure):
|
||||
_fields_ = [
|
||||
("Reserved1", BYTE * 2),
|
||||
@@ -522,8 +558,8 @@ class _FLOATING_SAVE_AREA(Structure):
|
||||
]
|
||||
FLOATING_SAVE_AREA = _FLOATING_SAVE_AREA
|
||||
|
||||
# Struct _CONTEXT definitions
|
||||
class _CONTEXT(Structure):
|
||||
# Struct _CONTEXT32 definitions
|
||||
class _CONTEXT32(Structure):
|
||||
_fields_ = [
|
||||
("ContextFlags", DWORD),
|
||||
("Dr0", DWORD),
|
||||
@@ -551,9 +587,89 @@ class _CONTEXT(Structure):
|
||||
("SegSs", DWORD),
|
||||
("ExtendedRegisters", BYTE * 512),
|
||||
]
|
||||
PCONTEXT = POINTER(_CONTEXT)
|
||||
LPCONTEXT = POINTER(_CONTEXT)
|
||||
CONTEXT = _CONTEXT
|
||||
PCONTEXT32 = POINTER(_CONTEXT32)
|
||||
CONTEXT32 = _CONTEXT32
|
||||
LPCONTEXT32 = POINTER(_CONTEXT32)
|
||||
|
||||
# Struct _M128A definitions
|
||||
class _M128A(Structure):
|
||||
_fields_ = [
|
||||
("Low", ULONGLONG),
|
||||
("High", LONGLONG),
|
||||
]
|
||||
M128A = _M128A
|
||||
PM128A = POINTER(_M128A)
|
||||
|
||||
# Struct _CONTEXT64 definitions
|
||||
class _CONTEXT64(Structure):
|
||||
_fields_ = [
|
||||
("P1Home", DWORD64),
|
||||
("P2Home", DWORD64),
|
||||
("P3Home", DWORD64),
|
||||
("P4Home", DWORD64),
|
||||
("P5Home", DWORD64),
|
||||
("P6Home", DWORD64),
|
||||
("ContextFlags", DWORD),
|
||||
("MxCsr", DWORD),
|
||||
("SegCs", WORD),
|
||||
("SegDs", WORD),
|
||||
("SegEs", WORD),
|
||||
("SegFs", WORD),
|
||||
("SegGs", WORD),
|
||||
("SegSs", WORD),
|
||||
("EFlags", DWORD),
|
||||
("Dr0", DWORD64),
|
||||
("Dr1", DWORD64),
|
||||
("Dr2", DWORD64),
|
||||
("Dr3", DWORD64),
|
||||
("Dr6", DWORD64),
|
||||
("Dr7", DWORD64),
|
||||
("Rax", DWORD64),
|
||||
("Rcx", DWORD64),
|
||||
("Rdx", DWORD64),
|
||||
("Rbx", DWORD64),
|
||||
("Rsp", DWORD64),
|
||||
("Rbp", DWORD64),
|
||||
("Rsi", DWORD64),
|
||||
("Rdi", DWORD64),
|
||||
("R8", DWORD64),
|
||||
("R9", DWORD64),
|
||||
("R10", DWORD64),
|
||||
("R11", DWORD64),
|
||||
("R12", DWORD64),
|
||||
("R13", DWORD64),
|
||||
("R14", DWORD64),
|
||||
("R15", DWORD64),
|
||||
("Rip", DWORD64),
|
||||
("Header", M128A * 2),
|
||||
("Legacy", M128A * 8),
|
||||
("Xmm0", M128A),
|
||||
("Xmm1", M128A),
|
||||
("Xmm2", M128A),
|
||||
("Xmm3", M128A),
|
||||
("Xmm4", M128A),
|
||||
("Xmm5", M128A),
|
||||
("Xmm6", M128A),
|
||||
("Xmm7", M128A),
|
||||
("Xmm8", M128A),
|
||||
("Xmm9", M128A),
|
||||
("Xmm10", M128A),
|
||||
("Xmm11", M128A),
|
||||
("Xmm12", M128A),
|
||||
("Xmm13", M128A),
|
||||
("Xmm14", M128A),
|
||||
("Xmm15", M128A),
|
||||
("VectorRegister", M128A * 26),
|
||||
("VectorControl", DWORD64),
|
||||
("DebugControl", DWORD64),
|
||||
("LastBranchToRip", DWORD64),
|
||||
("LastBranchFromRip", DWORD64),
|
||||
("LastExceptionToRip", DWORD64),
|
||||
("LastExceptionFromRip", DWORD64),
|
||||
]
|
||||
PCONTEXT64 = POINTER(_CONTEXT64)
|
||||
CONTEXT64 = _CONTEXT64
|
||||
LPCONTEXT64 = POINTER(_CONTEXT64)
|
||||
|
||||
# Struct tagPROCESSENTRY32W definitions
|
||||
class tagPROCESSENTRY32W(Structure):
|
||||
@@ -811,3 +927,35 @@ class _MIB_TCPROW(Structure):
|
||||
MIB_TCPROW = _MIB_TCPROW
|
||||
PMIB_TCPROW = POINTER(_MIB_TCPROW)
|
||||
|
||||
# Struct _EXCEPTION_RECORD definitions
|
||||
# Self referencing struct tricks
|
||||
class _EXCEPTION_RECORD(Structure): pass
|
||||
_EXCEPTION_RECORD._fields_ = [
|
||||
("ExceptionCode", DWORD),
|
||||
("ExceptionFlags", DWORD),
|
||||
("ExceptionRecord", POINTER(_EXCEPTION_RECORD)),
|
||||
("ExceptionAddress", PVOID),
|
||||
("NumberParameters", DWORD),
|
||||
("ExceptionInformation", ULONG_PTR * EXCEPTION_MAXIMUM_PARAMETERS),
|
||||
]
|
||||
PEXCEPTION_RECORD = POINTER(_EXCEPTION_RECORD)
|
||||
EXCEPTION_RECORD = _EXCEPTION_RECORD
|
||||
|
||||
# Struct _EXCEPTION_POINTERS64 definitions
|
||||
class _EXCEPTION_POINTERS64(Structure):
|
||||
_fields_ = [
|
||||
("ExceptionRecord", PEXCEPTION_RECORD),
|
||||
("ContextRecord", PCONTEXT64),
|
||||
]
|
||||
EXCEPTION_POINTERS64 = _EXCEPTION_POINTERS64
|
||||
PEXCEPTION_POINTERS64 = POINTER(_EXCEPTION_POINTERS64)
|
||||
|
||||
# Struct _EXCEPTION_POINTERS32 definitions
|
||||
class _EXCEPTION_POINTERS32(Structure):
|
||||
_fields_ = [
|
||||
("ExceptionRecord", PEXCEPTION_RECORD),
|
||||
("ContextRecord", PCONTEXT32),
|
||||
]
|
||||
PEXCEPTION_POINTERS32 = POINTER(_EXCEPTION_POINTERS32)
|
||||
EXCEPTION_POINTERS32 = _EXCEPTION_POINTERS32
|
||||
|
||||
|
||||
@@ -10,38 +10,37 @@ from windows.generated_def.winstructs import *
|
||||
class Callback(object):
|
||||
def __init__(self, *types):
|
||||
self.types = types
|
||||
|
||||
|
||||
def __call__(self, func):
|
||||
func._types_info = self.types
|
||||
return func
|
||||
|
||||
|
||||
class KnownCallback(object):
|
||||
types = ()
|
||||
|
||||
def __call__(self, func):
|
||||
func._types_info = self.types
|
||||
return func
|
||||
|
||||
|
||||
def add_callback_to_module(callback):
|
||||
setattr(sys.modules[__name__], type(callback).__name__, callback)
|
||||
|
||||
|
||||
# Generate IATCallback decorator for all known functions
|
||||
for func in winfuncs.functions:
|
||||
prototype = getattr(winfuncs, func + "Prototype")
|
||||
prototype = getattr(winfuncs, func + "Prototype")
|
||||
callback_name = func + "Callback"
|
||||
|
||||
|
||||
class CallBackDeclaration(KnownCallback):
|
||||
types = (prototype._restype_,) + prototype._argtypes_
|
||||
|
||||
|
||||
CallBackDeclaration.__name__ = callback_name
|
||||
add_callback_to_module(CallBackDeclaration())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class IATHook(object):
|
||||
"""Look at my hook <3"""
|
||||
|
||||
#callback_inject = python_native_execution.CallbackInjector()
|
||||
|
||||
def __init__(self, IAT_entry, callback, types=None):
|
||||
if types is None:
|
||||
if not hasattr(callback, "_types_info"):
|
||||
@@ -63,17 +62,17 @@ class IATHook(object):
|
||||
else:
|
||||
res.append(type)
|
||||
return res
|
||||
|
||||
|
||||
def enable(self):
|
||||
with utils.VirtualProtected(self.entry.addr, ctypes.sizeof(PVOID), windef.PAGE_EXECUTE_READWRITE):
|
||||
self.entry.value = self.stub
|
||||
self.is_enable = True
|
||||
|
||||
|
||||
def disable(self):
|
||||
with utils.VirtualProtected(self.entry.addr, ctypes.sizeof(PVOID), windef.PAGE_EXECUTE_READWRITE):
|
||||
self.entry.value = self.entry.nonhookvalue
|
||||
self.is_enable = False
|
||||
|
||||
|
||||
def hook_callback(self, *args):
|
||||
original_args = args
|
||||
adapted_args = []
|
||||
|
||||
@@ -141,6 +141,12 @@ GetCurrentThread = TransparentKernel32Proxy("GetCurrentThread")
|
||||
AllocConsole = TransparentKernel32Proxy("AllocConsole")
|
||||
GetStdHandle = TransparentKernel32Proxy("GetStdHandle")
|
||||
SetStdHandle = TransparentKernel32Proxy("SetStdHandle")
|
||||
GetCurrentThreadId = TransparentKernel32Proxy("GetCurrentThreadId")
|
||||
|
||||
TerminateThread = TransparentKernel32Proxy("TerminateThread")
|
||||
ExitThread = TransparentKernel32Proxy("ExitThread")
|
||||
SuspendThread = TransparentKernel32Proxy("SuspendThread")
|
||||
ResumeThread = TransparentKernel32Proxy("ResumeThread")
|
||||
|
||||
# This kind of function could be fully done by using paramflags
|
||||
@Kernel32Proxy("VirtualAlloc")
|
||||
@@ -151,6 +157,10 @@ def VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMM
|
||||
def VirtualAllocEx(hProcess, lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT, flProtect=PAGE_EXECUTE_READWRITE):
|
||||
return VirtualAllocEx.ctypes_function(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
|
||||
|
||||
@Kernel32Proxy("CreateThread")
|
||||
def CreateThread(lpThreadAttributes=None, dwStackSize=0, lpStartAddress=NeededParameter, lpParameter=NeededParameter, dwCreationFlags=0, lpThreadId=None):
|
||||
return CreateThread.ctypes_function(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)
|
||||
|
||||
@Kernel32Proxy("CreateRemoteThread")
|
||||
def CreateRemoteThread(hProcess=NeededParameter, lpThreadAttributes=None, dwStackSize=0,
|
||||
lpStartAddress=NeededParameter, lpParameter=NeededParameter, dwCreationFlags=0, lpThreadId=None):
|
||||
@@ -269,6 +279,23 @@ def WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite=None, lpNumberOfBytesWritte
|
||||
lpNumberOfBytesWritten = ctypes.byref(DWORD())
|
||||
return WriteFile.ctypes_function(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
|
||||
|
||||
# Exception stuff
|
||||
@Kernel32Proxy("AddVectoredContinueHandler")
|
||||
def AddVectoredContinueHandler(FirstHandler=1, VectoredHandler=NeededParameter):
|
||||
return AddVectoredContinueHandler.ctypes_function(FirstHandler, VectoredHandler)
|
||||
|
||||
@Kernel32Proxy("AddVectoredExceptionHandler")
|
||||
def AddVectoredExceptionHandler(FirstHandler=1, VectoredHandler=NeededParameter):
|
||||
return AddVectoredExceptionHandler.ctypes_function(FirstHandler, VectoredHandler)
|
||||
|
||||
@Kernel32Proxy("RemoveVectoredExceptionHandler")
|
||||
def RemoveVectoredExceptionHandler(Handler):
|
||||
return RemoveVectoredExceptionHandler.ctypes_function(Handler)
|
||||
|
||||
@Kernel32Proxy("WaitForSingleObject")
|
||||
def WaitForSingleObject(hHandle, dwMilliseconds=INFINITE):
|
||||
return WaitForSingleObject.ctypes_function(hHandle, dwMilliseconds)
|
||||
|
||||
###### ADVAPI32 ########
|
||||
|
||||
@Advapi32Proxy('OpenProcessToken')
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% source
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
echo. coverage to run coverage check of the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
REM Check if sphinx-build is available and fallback to Python version if any
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 goto sphinx_python
|
||||
goto sphinx_ok
|
||||
|
||||
:sphinx_python
|
||||
|
||||
set SPHINXBUILD=python -m sphinx.__init__
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:sphinx_ok
|
||||
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PyWindows.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PyWindows.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "coverage" (
|
||||
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of coverage in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/coverage/python.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
@@ -1,2 +1 @@
|
||||
from native_function import generate_callback_stub, create_function
|
||||
|
||||
from native_function import generate_callback_stub, create_function
|
||||
@@ -314,6 +314,13 @@ def generate_callback_stub(callback, types):
|
||||
generate_callback_stub.l = []
|
||||
|
||||
def create_function(code, types):
|
||||
"""Create a python function that call raw machine code
|
||||
|
||||
:param str code: Raw machine code that will be called
|
||||
:param list types: Return type and parameters type (see :mod:`ctypes`)
|
||||
:return: the created function
|
||||
:rtype: function
|
||||
"""
|
||||
func_type = ctypes.CFUNCTYPE(*types)
|
||||
addr = allocator.write_code(code)
|
||||
return func_type(addr)
|
||||
|
||||
@@ -8,9 +8,23 @@ from simple_x86 import MultipleInstr
|
||||
# This code should really be rewritten..
|
||||
|
||||
this_module = sys.modules[__name__]
|
||||
|
||||
generated_instruction = []
|
||||
|
||||
def add_instruction(name, instruction):
|
||||
generated_instruction.append((name, instruction))
|
||||
setattr(this_module, name, instruction)
|
||||
|
||||
def generate_module_doc():
|
||||
doc_lines = ["Here is the list of instruction in the modules:\n\n"]
|
||||
for name, instruction in generated_instruction:
|
||||
doc_lines.append(" | {0} -> <{1}>".format(name, instruction.mnemo))
|
||||
|
||||
this_module.__doc__ = "\n".join(doc_lines)
|
||||
|
||||
reg_order = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI']
|
||||
reg_opcode = {v : format(i, "03b") for i, v in enumerate(reg_order)}
|
||||
|
||||
|
||||
reg_order = ['RAX', 'RCX', 'RDX', 'RBX', 'RSP', 'RBP', 'RSI', 'RDI']
|
||||
reg_opcode = {v : format(i, "03b") for i, v in enumerate(reg_order)}
|
||||
@@ -54,14 +68,20 @@ class Ret(X64Instruction):
|
||||
mnemo = "ret"
|
||||
code = "C3"
|
||||
|
||||
generated_instruction.append(("Ret", Ret))
|
||||
|
||||
class Int3(X64Instruction):
|
||||
mnemo = "int3"
|
||||
code = "CC"
|
||||
|
||||
generated_instruction.append(("Int3", Int3))
|
||||
|
||||
class Retf(X64Instruction):
|
||||
mnemo = "retf"
|
||||
code = "CB"
|
||||
|
||||
generated_instruction.append(("Retf", Retf))
|
||||
|
||||
|
||||
class SimpleRegInstructionGenerator(object):
|
||||
name = ""
|
||||
@@ -75,10 +95,14 @@ class Mov_RAX_DX(OneBindX64Instruction):
|
||||
mnemo = 'mov rax, [{0}]'
|
||||
code = "48 a1 11 11 11 11 11 11 11 11"
|
||||
|
||||
generated_instruction.append(("Mov_RAX_DX", Mov_RAX_DX))
|
||||
|
||||
class Mov_DX_RAX(OneBindX64Instruction):
|
||||
name = 'Mov_DX_RAX'
|
||||
mnemo = 'mov [{0}], rax'
|
||||
code = "48 a3 11 11 11 11 11 11 11 11"
|
||||
|
||||
generated_instruction.append(("Mov_DX_RAX", Mov_DX_RAX))
|
||||
|
||||
def generate_simple_reg_instruction(instr_cls, include_new_reg=False):
|
||||
for reg_name, reg_bits in reg_opcode.items():
|
||||
@@ -214,4 +238,6 @@ def generate_reg_reg_deref():
|
||||
|
||||
|
||||
generate_reg_reg_deref()
|
||||
|
||||
generate_module_doc()
|
||||
|
||||
|
||||
@@ -4,8 +4,19 @@ import sys
|
||||
|
||||
this_module = sys.modules[__name__]
|
||||
|
||||
generated_instruction = []
|
||||
|
||||
|
||||
def add_instruction(name, instruction):
|
||||
generated_instruction.append((name, instruction))
|
||||
setattr(this_module, name, instruction)
|
||||
|
||||
def generate_module_doc():
|
||||
doc_lines = ["Here is the list of instruction in the modules:\n\n"]
|
||||
for name, instruction in generated_instruction:
|
||||
doc_lines.append(" | {0} -> <{1}>".format(name, instruction.mnemo))
|
||||
|
||||
this_module.__doc__ = "\n".join(doc_lines)
|
||||
|
||||
reg_order = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI']
|
||||
reg_opcode = {v : format(i, "03b") for i, v in enumerate(reg_order)}
|
||||
@@ -43,10 +54,13 @@ class Ret(X86Instruction):
|
||||
mnemo = "ret"
|
||||
code = "C3"
|
||||
|
||||
generated_instruction.append(("Ret", Ret))
|
||||
|
||||
class Int3(X86Instruction):
|
||||
mnemo = "int3"
|
||||
code = "CC"
|
||||
|
||||
|
||||
generated_instruction.append(("Int3", Int3))
|
||||
|
||||
class SimpleRegInstructionGenerator(object):
|
||||
name = ""
|
||||
@@ -60,7 +74,8 @@ class OneBindX86Instruction(X86Instruction):
|
||||
class Push_X(OneBindX86Instruction):
|
||||
mnemo = "push {0}"
|
||||
code = "68 11 11 11 11"
|
||||
|
||||
|
||||
generated_instruction.append(("Push_X", Push_X))
|
||||
|
||||
def generate_simple_reg_instruction(instr_cls):
|
||||
for reg_name, reg_bits in reg_opcode.items():
|
||||
@@ -268,4 +283,8 @@ class MultipleInstr(object):
|
||||
|
||||
def get_mnemo(self):
|
||||
return "\n".join(i.get_mnemo() for i in self.instrs)
|
||||
|
||||
|
||||
|
||||
generate_module_doc()
|
||||
|
||||
+34
-34
@@ -9,102 +9,102 @@ from windows.generated_def.windef import *
|
||||
|
||||
|
||||
class TCP4Connection(MIB_TCPROW_OWNER_PID):
|
||||
|
||||
@property
|
||||
|
||||
@property
|
||||
def established(self):
|
||||
return self.dwState == MIB_TCP_STATE_ESTAB
|
||||
|
||||
@property
|
||||
|
||||
@property
|
||||
def remote_port(self):
|
||||
return socket.ntohs(self.dwRemotePort)
|
||||
|
||||
@property
|
||||
|
||||
@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
|
||||
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
|
||||
@staticmethod
|
||||
def _str_ipv6_addr(addr):
|
||||
return ":".join(c.encode('hex') for c in addr)
|
||||
|
||||
@property
|
||||
|
||||
@property
|
||||
def established(self):
|
||||
return self.dwState == MIB_TCP_STATE_ESTAB
|
||||
|
||||
@property
|
||||
|
||||
@property
|
||||
def remote_port(self):
|
||||
return socket.ntohs(self.dwRemotePort)
|
||||
|
||||
@property
|
||||
|
||||
@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")
|
||||
|
||||
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),
|
||||
@@ -121,11 +121,11 @@ def get_MIB_TCP6TABLE_OWNER_PID_from_buffer(buffer):
|
||||
_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:
|
||||
@@ -136,7 +136,7 @@ def get_tcp_ipv4_sockets():
|
||||
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:
|
||||
|
||||
+5
-3
@@ -1,5 +1,6 @@
|
||||
import ctypes
|
||||
import windows
|
||||
import hooks
|
||||
|
||||
from generated_def.winstructs import *
|
||||
|
||||
@@ -77,7 +78,6 @@ def PEFile(baseaddr):
|
||||
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()
|
||||
@@ -85,7 +85,7 @@ def PEFile(baseaddr):
|
||||
|
||||
def remove_hook(self):
|
||||
if self.hook is None:
|
||||
return None
|
||||
return False
|
||||
self.hook.disable()
|
||||
self.hook = None
|
||||
return True
|
||||
@@ -241,4 +241,6 @@ def PEFile(baseaddr):
|
||||
# res.append((nb, func, name))
|
||||
# return res
|
||||
#
|
||||
return current_pe
|
||||
return current_pe
|
||||
|
||||
tst = PEFile.__code__.co_consts[13]
|
||||
@@ -18,4 +18,3 @@ def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttr
|
||||
if "dick" in lpFileName:
|
||||
return 0x4242
|
||||
return real_function()
|
||||
|
||||
+364
@@ -0,0 +1,364 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# PyWindows documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Apr 07 11:39:41 2015.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
|
||||
sys.path.append(r"C:\Users\hakril\Documents\Work\PythonForWindows")
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.autodoc',
|
||||
]
|
||||
|
||||
autodoc_default_flags = ['show-inheritance', 'inherited-members']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'PyWindows'
|
||||
copyright = u'2015, Clement Rouault'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Language to be used for generating the HTML full-text search index.
|
||||
# Sphinx supports the following languages:
|
||||
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
|
||||
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
|
||||
#html_search_language = 'en'
|
||||
|
||||
# A dictionary with options for the search language support, empty by default.
|
||||
# Now only 'ja' uses this config value
|
||||
#html_search_options = {'type': 'default'}
|
||||
|
||||
# The name of a javascript file (relative to the configuration directory) that
|
||||
# implements a search results scorer. If empty, the default will be used.
|
||||
#html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'PyWindowsdoc'
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'PyWindows.tex', u'PyWindows Documentation',
|
||||
u'Clement Rouault', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'pywindows', u'PyWindows Documentation',
|
||||
[u'Clement Rouault'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'PyWindows', u'PyWindows Documentation',
|
||||
u'Clement Rouault', 'PyWindows', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# -- Options for Epub output ----------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'PyWindows'
|
||||
epub_author = u'Clement Rouault'
|
||||
epub_publisher = u'Clement Rouault'
|
||||
epub_copyright = u'2015, Clement Rouault'
|
||||
|
||||
# The basename for the epub file. It defaults to the project name.
|
||||
#epub_basename = u'PyWindows'
|
||||
|
||||
# The HTML theme for the epub output. Since the default themes are not optimized
|
||||
# for small screen space, using the same theme for HTML and epub output is
|
||||
# usually not wise. This defaults to 'epub', a theme designed to save visual
|
||||
# space.
|
||||
#epub_theme = 'epub'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or 'en' if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
|
||||
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
|
||||
#epub_guide = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
# Choose between 'default' and 'includehidden'.
|
||||
#epub_tocscope = 'default'
|
||||
|
||||
# Fix unsupported image types using the PIL.
|
||||
#epub_fix_images = False
|
||||
|
||||
# Scale large images.
|
||||
#epub_max_image_width = 0
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#epub_show_urls = 'inline'
|
||||
|
||||
# If false, no index is generated.
|
||||
#epub_use_index = True
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'http://docs.python.org/': None}
|
||||
@@ -0,0 +1,19 @@
|
||||
GENERATED Documentation test
|
||||
****************************
|
||||
|
||||
Testing1
|
||||
********
|
||||
|
||||
.. automodule:: windows.generated_def.winstructs
|
||||
|
||||
|
||||
|
||||
Testing2
|
||||
********
|
||||
|
||||
.. autoclass:: _PEB_LDR_DATA
|
||||
.. autoclass:: _PEB
|
||||
.. autoclass:: _LIST_ENTRY
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
.. PyWindows documentation master file, created by
|
||||
sphinx-quickstart on Tue Apr 07 11:39:41 2015.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to PyWindows's documentation!
|
||||
=====================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
test.rst
|
||||
pe_parse.rst
|
||||
native_exec.rst
|
||||
rem_python.rst
|
||||
utils.rst
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
Native code execution
|
||||
***********************
|
||||
|
||||
.. automodule:: windows.native_exec
|
||||
:members: generate_callback_stub, create_function
|
||||
|
||||
|
||||
The native_function submodule
|
||||
"""""""""""""""""""""""""""""
|
||||
|
||||
.. automodule:: windows.native_exec.native_function
|
||||
:members: create_function
|
||||
|
||||
|
||||
Simple machine code generation
|
||||
""""""""""""""""""""""""""""""
|
||||
|
||||
These modules allow you to write some simple x86 / x64 shellcode. This is useful to use in adequation to :func:`create_function`.
|
||||
The instruction name are as explicit as possible with the following convention:
|
||||
|
||||
* This is `intel syntax` so `dest, src`
|
||||
* X specify a value passed as parameters::
|
||||
|
||||
Mov_EAX_X(0x42) # mov eax, 0x42
|
||||
|
||||
* D is for `dereference`::
|
||||
|
||||
Mov_EAX_DX(0x42424242) # mov EAX, [0x42424242]
|
||||
Mov_DEAX_EDI() # mov [EAX], EDI
|
||||
|
||||
All instructions follow this interface:
|
||||
|
||||
.. py:class:: Instruction
|
||||
|
||||
.. py:method:: get_code(self)
|
||||
|
||||
:returns: :class:`str`: The raw code of the instruction
|
||||
|
||||
.. py:method:: get_mnemo(self)
|
||||
|
||||
:returns: :class:`str`: The mnemonic of the instruction
|
||||
|
||||
Example::
|
||||
|
||||
import windows.native_exec.simple_x86 as x86
|
||||
|
||||
i = x86.Mov_EAX_X(0x42434445)
|
||||
i.get_code()
|
||||
# '\xb8EDCB'
|
||||
i.get_mnemo()
|
||||
# 'mov EAX, 0x42434445'
|
||||
|
||||
|
||||
You can also use a :class:`MultipleInstr` instance to merge instructions
|
||||
|
||||
Example::
|
||||
|
||||
import windows.native_exec.simple_x86 as x86
|
||||
|
||||
code = x86.MultipleInstr()
|
||||
code += x86.Mov_EAX_X(0x42434445)
|
||||
code += x86.Push_EAX()
|
||||
code += x86.Ret()
|
||||
code.get_code()
|
||||
# '\xb8EDCBP\xc3'
|
||||
print(code.get_mnemo())
|
||||
# mov EAX, 0x42434445
|
||||
# push EAX
|
||||
# ret
|
||||
|
||||
simple_x86 instructions
|
||||
-----------------------
|
||||
|
||||
.. automodule:: windows.native_exec.simple_x86
|
||||
|
||||
simple_x64 instructions
|
||||
-----------------------
|
||||
|
||||
.. automodule:: windows.native_exec.simple_x64
|
||||
@@ -0,0 +1,179 @@
|
||||
Loaded DLL Exploration and IAT hooks
|
||||
************************************
|
||||
|
||||
List of loaded modules
|
||||
""""""""""""""""""""""
|
||||
|
||||
Accessible using::
|
||||
|
||||
import windows
|
||||
windows.current_process.peb.modules[int].pe
|
||||
|
||||
..note::
|
||||
See: :class:`windows.winobject.PEB` and :class:`windows.winobject.LoadedModule`
|
||||
|
||||
|
||||
|
||||
DLL Import and IAT
|
||||
""""""""""""""""""
|
||||
|
||||
.. py:class:: PEFile
|
||||
|
||||
.. py:attribute:: imports
|
||||
|
||||
The imports of the PE
|
||||
|
||||
.. note::
|
||||
This is a :class:`dict` DLLName -> [:class:`IATEntry`]
|
||||
|
||||
Example::
|
||||
|
||||
import windows
|
||||
k32 = windows.current_process.peb.modules[2]
|
||||
# <LoadedModule "KERNEL32.DLL" at 0x2deca30>
|
||||
k32.pe.imports.keys()
|
||||
# ['kernelbase.dll', 'api-ms-win-core-profile-l1-1-0.dll', ...]
|
||||
k32.pe.imports['kernelbase.dll']
|
||||
# [<IATEntry "EnumLanguageGroupLocalesW" ordinal 58>, <IATEntry "GetNamedPipeAttribute" ordinal 93>, ...]
|
||||
[entry for entry in k32.pe.imports['kernelbase.dll'] if entry.name == "lstrcmpiW"][0]
|
||||
# <IATEntry "lstrcmpiW" ordinal 244>
|
||||
|
||||
|
||||
.. py:class:: IATEntry
|
||||
|
||||
| Reprensent An entry in the IAT of a module
|
||||
| Can be used to get resolved value and setup hook
|
||||
|
||||
.. py:attribute:: name
|
||||
|
||||
| :class:`int` : The name of the import
|
||||
|
||||
|
||||
.. py:attribute:: ord
|
||||
|
||||
| :class:`int` : The ordinal of the import
|
||||
|
||||
|
||||
.. py:attribute:: addr
|
||||
|
||||
| :class:`int` : The address of the IAT entry
|
||||
|
||||
.. py:attribute:: value
|
||||
|
||||
| :class:`int` : The destination of the IAT entry
|
||||
|
||||
.. warning::
|
||||
|
||||
`value` is a descriptor. Setting its value will actually CHANGE THE IAT ENTRY, resulting in a segfault if no VirtualProtect have been done.
|
||||
|
||||
.. note::
|
||||
|
||||
See: :class:`windows.utils.VirtualProtected`
|
||||
|
||||
|
||||
.. py:method:: set_hook(self, callback, types=None)
|
||||
|
||||
Setup a hook, `callback` should respect the :ref:`hook_protocol`. If `callback` have no :ref:`type_information`, `types` should provide them.
|
||||
|
||||
|
||||
IAT Hooking
|
||||
"""""""""""
|
||||
|
||||
.. _hook_protocol:
|
||||
|
||||
The hook protocol
|
||||
-----------------
|
||||
|
||||
Callback arguments
|
||||
''''''''''''''''''
|
||||
|
||||
A hook callback must have the same number of argument as the hooked API, PLUS a last argument `real_function`.
|
||||
|
||||
The `real_function` argument is a callable that represent the hooked API, it can be called in two ways:
|
||||
|
||||
* Without argument, the call will be done with the argument originaly passed to your callback. This allow simple redirection to the real API.
|
||||
|
||||
* With arguments it will simply call the API with these.
|
||||
|
||||
Example::
|
||||
|
||||
def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
|
||||
print("Trying to open {0}".format(lpFileName))
|
||||
if "secret" in lpFileName:
|
||||
return 0xffffffff
|
||||
# Perform the real call
|
||||
return real_function()
|
||||
|
||||
|
||||
.. _type_information:
|
||||
|
||||
Type information
|
||||
''''''''''''''''
|
||||
|
||||
In order make the magic behind Python Hook Callback, :mod:`ctypes` need to have type information about the API parameters.
|
||||
|
||||
There is (again) two ways to give those informations to your hook callback. Both techniques use a decorator to setup type information to the callback.
|
||||
|
||||
* Giving the type manualy using the decorator :class:`windows.hooks.Callback`::
|
||||
|
||||
from windows.hooks import *
|
||||
# First type is return type, others are parameters types
|
||||
@Callback(ctypes.c_void_p, ctypes.c_ulong)
|
||||
def exit_callback(x, real_function):
|
||||
print("Try to quit with {0} | {1}".format(x, type(x)))
|
||||
if x == 3:
|
||||
print("TRYING TO REAL EXIT")
|
||||
return real_function(1234)
|
||||
return 0x4242424243444546
|
||||
|
||||
* Using the `Callback` decorator generated from known functions::
|
||||
|
||||
from windows.hooks import *
|
||||
# Decorator name is always API_NAME + "CallBack"
|
||||
@CreateFileACallback
|
||||
def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
|
||||
print("Trying to open {0}".format(lpFileName))
|
||||
if "secret" in lpFileName:
|
||||
return 0xffffffff
|
||||
return real_function()
|
||||
|
||||
.. note::
|
||||
|
||||
See the list of known functions
|
||||
|
||||
|
||||
Put the hook
|
||||
------------
|
||||
|
||||
To setup your IAT hook you just need:
|
||||
|
||||
* A callback that respect the :ref:`hook_protocol`
|
||||
* The :class:`IATEntry` to hook
|
||||
|
||||
|
||||
You just need to use the function :func:`IATEntry.set_hook`
|
||||
|
||||
|
||||
Full Example::
|
||||
|
||||
import windows
|
||||
from windows.hooks import *
|
||||
|
||||
@CreateFileACallback
|
||||
def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
|
||||
print("Trying to open {0}".format(lpFileName))
|
||||
if "secret" in lpFileName:
|
||||
return 0xffffffff
|
||||
return real_function()
|
||||
|
||||
my_exe = windows.current_process.peb.modules[0]
|
||||
imp = my_exe.pe.imports
|
||||
|
||||
iat_create_file = [entry for entry in imp['kernel32.dll'] if entry.name == "CreateFileA"]
|
||||
iat_create_file.set_hook(createfile_callback)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
Remote Python Injection
|
||||
***********************
|
||||
|
||||
It's possible to inject the python interpreter into remote process. All you need to do is to use the method :func:`windows.winobject.WinProcess.execute_python`.
|
||||
|
||||
Calling this function will trigger the interpreter injection and the python code execution.
|
||||
|
||||
For simpler interaction interaction with the remote python, you can an RPC master linked to the remote interpreter.
|
||||
|
||||
RPython 101
|
||||
'''''''''''
|
||||
|
||||
RPython is a very simple Pythonic (I hope so) RPC slave-master. It's goal is to allow easy manipulation of a remote interpreter.
|
||||
|
||||
The only action up to the `slave` is the creation of it's `name_pool`: a namespace of object accessible by the `master`.
|
||||
After that the `slave` will just wait for request and return the desired object.
|
||||
|
||||
All slave object seen by the master are proxy that redirect operation to the slave.
|
||||
|
||||
RPython RPC to remote process
|
||||
'''''''''''''''''''''''''''''
|
||||
|
||||
For easy manipulation of a remote Python interpreter, you can use the RPCInjection module::
|
||||
|
||||
import windows
|
||||
import RPCInjection
|
||||
calc = [x for x in windows.system.processes if x.name == "calc.exe"][0]
|
||||
master = RPCInjection.launch_remote_slave(calc)
|
||||
# Master is a RPC-master to a python interpreter in calc.exe
|
||||
master['windows']
|
||||
# <RemoteObj |<module 'windows' from 'C:\Users\hakril\Documents\Work\PythonForWindows\windows\__init__.pyc'>|>
|
||||
|
||||
# This is a way to get our own (python.exe) pid
|
||||
windows.current_process.pid
|
||||
3624
|
||||
# This is a way to get the pid of calc.exe
|
||||
master['windows'].current_process
|
||||
# <RemoteObj |<windows.winobject.CurrentProcess object at 0x055E6250>|>
|
||||
master['windows'].current_process.pid
|
||||
5052
|
||||
# We can also play with the peb of the remote process
|
||||
master['windows'].current_process.peb
|
||||
# <RemoteObj |<windows.winobject.PEB object at 0x054A3DF0>|>
|
||||
master['windows'].current_process.peb.commandline
|
||||
# <RemoteObj |<WinUnicodeString ""C:\Windows\SysWOW64\calc.exe" " at 0x55e9850>|>
|
||||
|
||||
|
||||
# we can import new stuff
|
||||
|
||||
x['json']
|
||||
# ...
|
||||
# RPython.exchange.RemoteKeyError:
|
||||
# ....
|
||||
# KeyError: u'json'
|
||||
x.imp('json')
|
||||
# <RemoteObj |None|>
|
||||
x['json']
|
||||
# <RemoteObj |<module 'json' from 'C:\Python27\Lib\json\__init__.pyc'>|>
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
The slave `name_pool` in RPCInjection is filled with :mod:`windows`, :mod:`__import__`, :mod:`ctypes` and :mod:`self` (the RemotePythonSlave object)
|
||||
|
||||
The master.RemotePython
|
||||
'''''''''''''''''''''''
|
||||
|
||||
.. autoclass:: RPython.master.RemotePython
|
||||
|
||||
.. py:method:: __getitem__
|
||||
|
||||
Alias to :func:`ask_by_name`
|
||||
|
||||
Remote IAT Hooking
|
||||
''''''''''''''''''
|
||||
|
||||
See Examples directory
|
||||
@@ -0,0 +1,13 @@
|
||||
Overwiew of the `windows` objects
|
||||
**************************
|
||||
|
||||
object exported by `windows`
|
||||
""""""""""""""""""""""""""""
|
||||
|
||||
.. automodule:: windows
|
||||
|
||||
Principal classes for process exploration
|
||||
"""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. automodule:: windows.winobject
|
||||
:members:
|
||||
@@ -0,0 +1,4 @@
|
||||
Helpers
|
||||
*******
|
||||
|
||||
.. automodule:: windows.utils
|
||||
+24
-24
@@ -32,7 +32,7 @@ FF FF 1F 00 49 C7 C0 00 00 00 00 49 B9 40 40 40
|
||||
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
|
||||
5F 5E 5A 59 5B 58 58
|
||||
"""
|
||||
NtCreateThreadStub = Pretty_NtCreateThreadStub.replace(" ", "").replace("\n", "").decode('hex')
|
||||
|
||||
@@ -72,39 +72,39 @@ def NtCreateThreadEx_32_to_64(process, addr, param):
|
||||
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):
|
||||
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):
|
||||
|
||||
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):
|
||||
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 :(")
|
||||
@@ -113,7 +113,7 @@ def RemotePointer(struct):
|
||||
print("set proc via contents for {0}".format(s))
|
||||
return s
|
||||
return RemotePointerImp
|
||||
|
||||
|
||||
class RemoteStructure(Structure):
|
||||
def __init__(self, proc):
|
||||
self.proc = proc
|
||||
@@ -123,14 +123,14 @@ class RemoteStructure(Structure):
|
||||
if value in ["_fields_", "proc"]:
|
||||
return super(RemoteStructure, self).__getattribute__(value)
|
||||
d = dict(self._fields_)
|
||||
t = d.get(value, type(None))
|
||||
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_ = [
|
||||
@@ -138,13 +138,13 @@ class _LSA_UNICODE_STRING(RemoteStructure):
|
||||
("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)
|
||||
|
||||
|
||||
PLSA_UNICODE_STRING = POINTER(_LSA_UNICODE_STRING)
|
||||
|
||||
|
||||
class _LIST_ENTRY64(RemoteStructure): pass
|
||||
_LIST_ENTRY64._fields_ = [
|
||||
("Flink", Remote_LIST_ENTRY_PTR),
|
||||
@@ -170,14 +170,14 @@ class _LDR_DATA_TABLE_ENTRY64(RemoteStructure):
|
||||
]
|
||||
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),
|
||||
@@ -193,10 +193,10 @@ class _PEB64(RemoteStructure):
|
||||
("Reserved7", ULONG64 * 1),
|
||||
("SessionId", ULONG),
|
||||
]
|
||||
|
||||
|
||||
PEB64 = _PEB64
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ def swallow_ctypes_copy(ctypes_object):
|
||||
def get_func_addr(dll_name, func_name):
|
||||
dll = ctypes.WinDLL(dll_name)
|
||||
return kernel32proxy.GetProcAddress(dll._handle, func_name)
|
||||
|
||||
|
||||
# Used by system.processes
|
||||
def enumerate_processes():
|
||||
process_entry = winobject.WinProcess()
|
||||
process_entry.dwSize = ctypes.sizeof(process_entry)
|
||||
@@ -32,6 +33,7 @@ def enumerate_processes():
|
||||
res.append(swallow_ctypes_copy(process_entry))
|
||||
return res
|
||||
|
||||
# Used by system.threads
|
||||
def enumerate_threads():
|
||||
thread_entry = winobject.WinThread()
|
||||
thread_entry.dwSize = ctypes.sizeof(thread_entry)
|
||||
@@ -42,7 +44,7 @@ def enumerate_threads():
|
||||
while kernel32proxy.Thread32Next(snap, thread_entry):
|
||||
threads.append(copy.copy(thread_entry))
|
||||
return threads
|
||||
|
||||
|
||||
def is_wow_64(hProcess):
|
||||
try:
|
||||
fnIsWow64Process = get_func_addr("kernel32.dll", "IsWow64Process")
|
||||
@@ -54,41 +56,53 @@ def is_wow_64(hProcess):
|
||||
if res:
|
||||
return bool(Wow64Process)
|
||||
raise ctypes.WinError()
|
||||
|
||||
|
||||
def create_file_from_handle(handle, mode="r"):
|
||||
"""Return a Python :class:`file` arround a windows HANDLE"""
|
||||
fd = msvcrt.open_osfhandle(handle, os.O_TEXT)
|
||||
return os.fdopen(fd, mode, 0)
|
||||
|
||||
|
||||
def get_handle_from_file(f):
|
||||
"""Get the windows HANDLE of a python :class:`file`"""
|
||||
return msvcrt.get_osfhandle(f.fileno())
|
||||
|
||||
def create_console():
|
||||
|
||||
def create_console():
|
||||
"""| Create a new console displaying STDOUT
|
||||
| Useful in injection of GUI process
|
||||
"""
|
||||
kernel32proxy.AllocConsole()
|
||||
stdout_handle = kernel32proxy.GetStdHandle(windef.STD_OUTPUT_HANDLE)
|
||||
console_stdout = create_file_from_handle(stdout_handle, "w")
|
||||
sys.stdout = console_stdout
|
||||
|
||||
|
||||
stdin_handle = kernel32proxy.GetStdHandle(windef.STD_INPUT_HANDLE)
|
||||
console_stdin = create_file_from_handle(stdin_handle, "r+")
|
||||
sys.stdin = console_stdin
|
||||
|
||||
|
||||
stderr_handle = kernel32proxy.GetStdHandle(windef.STD_ERROR_HANDLE)
|
||||
console_stderr = create_file_from_handle(stderr_handle, "w")
|
||||
sys.stderr = console_stderr
|
||||
|
||||
|
||||
class VirtualProtected(object):
|
||||
"""A context manager usable like `VirtualProtect` that will restore the old protection at exit
|
||||
|
||||
Example::
|
||||
|
||||
with utils.VirtualProtected(IATentry.addr, ctypes.sizeof(PVOID), windef.PAGE_EXECUTE_READWRITE):
|
||||
IATentry.value = 0x42424242
|
||||
"""
|
||||
def __init__(self, addr, size, new_protect):
|
||||
if (addr % 0x1000):
|
||||
addr = addr - addr % 0x1000
|
||||
self.addr = addr
|
||||
self.size = size
|
||||
self.new_protect = new_protect
|
||||
|
||||
|
||||
def __enter__(self):
|
||||
self.old_protect = DWORD()
|
||||
kernel32proxy.VirtualProtect(self.addr, self.size, self.new_protect, ctypes.byref(self.old_protect))
|
||||
return self
|
||||
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
kernel32proxy.VirtualProtect(self.addr, self.size, self.old_protect.value, ctypes.byref(self.old_protect))
|
||||
return False
|
||||
@@ -0,0 +1,124 @@
|
||||
import windows
|
||||
|
||||
import ctypes
|
||||
import windows
|
||||
from windows.generated_def.winstructs import *
|
||||
import windows.generated_def.windef as windef
|
||||
import time
|
||||
|
||||
EXCEPTION_CONTINUE_SEARCH = (0x0)
|
||||
EXCEPTION_CONTINUE_EXECUTION = (0xffffffff)
|
||||
|
||||
|
||||
exception_type = [
|
||||
"EXCEPTION_ACCESS_VIOLATION",
|
||||
"EXCEPTION_DATATYPE_MISALIGNMENT",
|
||||
"EXCEPTION_BREAKPOINT",
|
||||
"EXCEPTION_SINGLE_STEP",
|
||||
"EXCEPTION_ARRAY_BOUNDS_EXCEEDED",
|
||||
"EXCEPTION_FLT_DENORMAL_OPERAND",
|
||||
"EXCEPTION_FLT_DIVIDE_BY_ZERO",
|
||||
"EXCEPTION_FLT_INEXACT_RESULT",
|
||||
"EXCEPTION_FLT_INVALID_OPERATION",
|
||||
"EXCEPTION_FLT_OVERFLOW",
|
||||
"EXCEPTION_FLT_STACK_CHECK",
|
||||
"EXCEPTION_FLT_UNDERFLOW",
|
||||
"EXCEPTION_INT_DIVIDE_BY_ZERO",
|
||||
"EXCEPTION_INT_OVERFLOW",
|
||||
"EXCEPTION_PRIV_INSTRUCTION",
|
||||
"EXCEPTION_IN_PAGE_ERROR",
|
||||
"EXCEPTION_ILLEGAL_INSTRUCTION",
|
||||
"EXCEPTION_NONCONTINUABLE_EXCEPTION",
|
||||
"EXCEPTION_STACK_OVERFLOW",
|
||||
"EXCEPTION_INVALID_DISPOSITION",
|
||||
"EXCEPTION_GUARD_PAGE",
|
||||
"EXCEPTION_INVALID_HANDLE",
|
||||
"EXCEPTION_POSSIBLE_DEADLOCK",
|
||||
]
|
||||
|
||||
# x -> x dict may seems strange but useful to get the Flags (with name) from the int
|
||||
# exception_name_by_value[0x80000001] -> EXCEPTION_GUARD_PAGE(0x80000001L)
|
||||
exception_name_by_value = dict([(x,x) for x in [getattr(windows.generated_def.windef, name) for name in exception_type]])
|
||||
|
||||
|
||||
class EnhancedEXCEPTION_RECORD(EXCEPTION_RECORD):
|
||||
@property
|
||||
def ExceptionCode(self):
|
||||
real_code = super(EnhancedEXCEPTION_RECORD, self).ExceptionCode
|
||||
return exception_name_by_value.get(real_code, 'UNKNOW_EXCEPTION({0})'.format(hex(real_code)))
|
||||
|
||||
class EnhancedCONTEXTBase(CONTEXT):
|
||||
default_dump = ()
|
||||
|
||||
def regs(self, to_dump=None):
|
||||
res = []
|
||||
if to_dump is None:
|
||||
to_dump = self.default_dump
|
||||
for name in to_dump:
|
||||
res.append((name, getattr(self, name)))
|
||||
return res
|
||||
|
||||
def dump(self, to_dump=None):
|
||||
regs = self.regs()
|
||||
for name, value in regs:
|
||||
print("{0} -> {1}".format(name, hex(value)))
|
||||
|
||||
class EnhancedCONTEXT32(EnhancedCONTEXTBase):
|
||||
default_dump = ('Eip', 'Esp', 'Eax', 'Ebx', 'Ecx', 'Ebp', 'Edi', 'Esi')
|
||||
|
||||
class EnhancedCONTEXT64(EnhancedCONTEXTBase):
|
||||
default_dump = ('Rip', 'Rsp', 'Rax', 'Rbx', 'Rcx', 'Rbp', 'Rdi', 'Rsi',
|
||||
'R9', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15')
|
||||
|
||||
if windows.current_process.bitness == 32:
|
||||
EnhancedCONTEXT = EnhancedCONTEXT32
|
||||
else:
|
||||
EnhancedCONTEXT = EnhancedCONTEXT64
|
||||
|
||||
class EnhancedEXCEPTION_POINTERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("ExceptionRecord", ctypes.POINTER(EnhancedEXCEPTION_RECORD)),
|
||||
("ContextRecord", ctypes.POINTER(EnhancedCONTEXT)),
|
||||
]
|
||||
|
||||
def dump(self):
|
||||
record = self.ExceptionRecord[0]
|
||||
print("Dumping Exception: ")
|
||||
print(" ExceptionCode = {0} at {1}".format(record.ExceptionCode, hex(record.ExceptionAddress)))
|
||||
regs = self.ContextRecord[0].regs()
|
||||
for name, value in regs:
|
||||
print(" {0} -> {1}".format(name, hex(value)))
|
||||
|
||||
|
||||
class VectoredException(object):
|
||||
func_type = ctypes.WINFUNCTYPE(ctypes.c_uint, ctypes.POINTER(EnhancedEXCEPTION_POINTERS))
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __call__(self, func):
|
||||
self.func = func
|
||||
return self.func_type(self.decorator)
|
||||
|
||||
def decorator(self, exception_pointers):
|
||||
print("IN DAT DECORATOR")
|
||||
try:
|
||||
x = self.func(exception_pointers)
|
||||
print("PROUT")
|
||||
return x
|
||||
except BaseException as e:
|
||||
print("Ignored Python Exception in Vectored Exception: {0}".format(e))
|
||||
return windef.EXCEPTION_CONTINUE_SEARCH
|
||||
|
||||
|
||||
class WithExceptionHandler(object):
|
||||
def __init__(self, handler):
|
||||
self.handler = handler
|
||||
|
||||
def __enter__(self):
|
||||
self.value = windows.k32testing.AddVectoredExceptionHandler(0, self.handler)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
windows.k32testing.RemoveVectoredExceptionHandler(self.value)
|
||||
return False
|
||||
+197
-54
@@ -12,11 +12,20 @@ import pe_parse
|
||||
|
||||
|
||||
class AutoHandle(object):
|
||||
"""An abstract class that allow easy handle creation/destruction"""
|
||||
def _get_handle(self):
|
||||
raise NotImplementedError('_get_handle')
|
||||
raise NotImplementedError("{0} is abstract".format(type(self).__name__))
|
||||
|
||||
@property
|
||||
def handle(self):
|
||||
"""A handle on the object
|
||||
|
||||
.. note::
|
||||
The handle is automaticaly closed when the object is destroyed
|
||||
|
||||
:type: int
|
||||
|
||||
"""
|
||||
if hasattr(self, "_handle"):
|
||||
return self._handle
|
||||
self._handle = self._get_handle()
|
||||
@@ -27,17 +36,32 @@ class AutoHandle(object):
|
||||
kernel32proxy.CloseHandle(self._handle)
|
||||
|
||||
class System(object):
|
||||
|
||||
"""Represent the current windows system python is running on"""
|
||||
@property
|
||||
def processes(self):
|
||||
"""The list of running processes
|
||||
|
||||
:type: [:class:`WinProcess`] -- A list of Process
|
||||
|
||||
"""
|
||||
return utils.enumerate_processes()
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
"""The list of running threads
|
||||
|
||||
:type: [:class:`WinThread`] -- A list of Thread
|
||||
|
||||
"""
|
||||
return utils.enumerate_threads()
|
||||
|
||||
@property
|
||||
def bitness(self):
|
||||
"""The bitness of the system
|
||||
|
||||
:type: int -- 32 or 64
|
||||
|
||||
"""
|
||||
if os.environ["PROCESSOR_ARCHITECTURE"].lower() != "x86":
|
||||
return 64
|
||||
if "PROCESSOR_ARCHITEW6432" in os.environ:
|
||||
@@ -48,12 +72,19 @@ class System(object):
|
||||
# May have a common class with WinProcess for is_wow_64 and stuff
|
||||
|
||||
class WinThread(THREADENTRY32, AutoHandle):
|
||||
"""Represent a thread """
|
||||
@property
|
||||
def tid(self):
|
||||
"""Thread ID"""
|
||||
return self.th32ThreadID
|
||||
|
||||
@property
|
||||
def owner(self):
|
||||
"""The Process owning the thread
|
||||
|
||||
:type: :class:`WinProcess`
|
||||
|
||||
"""
|
||||
if hasattr(self, "_owner"):
|
||||
return self._owner
|
||||
self._owner = [process for process in utils.enumerate_processes() if process.pid == self.th32OwnerProcessID][0]
|
||||
@@ -65,8 +96,71 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
def __repr__(self):
|
||||
return '<{0} {1} owner "{2}" at {3}>'.format(self.__class__.__name__, self.tid, self.owner.name, hex(id(self)))
|
||||
|
||||
class Process(AutoHandle):
|
||||
@property
|
||||
def is_wow_64(self):
|
||||
"""Is True if the process is a SysWow64 process
|
||||
|
||||
class CurrentProcess(object):
|
||||
This means a 32bits process on a 64bits system
|
||||
|
||||
:type: bool
|
||||
"""
|
||||
return utils.is_wow_64(self.handle)
|
||||
|
||||
@property
|
||||
def bitness(self):
|
||||
"""The bitness of the process
|
||||
|
||||
:returns: int -- 32 or 64"""
|
||||
if windows.system.bitness == 32:
|
||||
return 32
|
||||
if self.is_wow_64:
|
||||
return 32
|
||||
return 64
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
"""The threads of the process
|
||||
|
||||
:type: [:class:`WinThread`] -- A list of Thread
|
||||
|
||||
"""
|
||||
return [thread for thread in utils.enumerate_threads() if thread.th32OwnerProcessID == self.pid]
|
||||
|
||||
def virtual_alloc(self, size):
|
||||
raise NotImplementedError("virtual_alloc")
|
||||
|
||||
def execute(self, code):
|
||||
"""Execute some raw code in the context of the process"""
|
||||
x = self.virtual_alloc(len(code))
|
||||
self.write_memory(x, code)
|
||||
return self.create_thread(x, 0)
|
||||
|
||||
|
||||
class CurrentThread(AutoHandle):
|
||||
"""The current thread"""
|
||||
@property
|
||||
def tid(self):
|
||||
"""Thread ID"""
|
||||
return kernel32proxy.GetCurrentThreadId()
|
||||
|
||||
@property
|
||||
def owner(self):
|
||||
"""The current process
|
||||
|
||||
:type: :class:`CurrentProcess`
|
||||
"""
|
||||
return windows.current_process
|
||||
|
||||
def _get_handle(self):
|
||||
return kernel32proxy.GetCurrentThread()
|
||||
|
||||
def exit(self, code=0):
|
||||
"""Exit the thread"""
|
||||
return kernel32proxy.ExitThread(code)
|
||||
|
||||
class CurrentProcess(Process):
|
||||
"""The current process"""
|
||||
get_peb = None
|
||||
get_peb_32_code = '64a130000000c3'.decode('hex')
|
||||
|
||||
@@ -84,52 +178,101 @@ class CurrentProcess(object):
|
||||
self.get_peb = get_peb
|
||||
return get_peb
|
||||
|
||||
def _get_handle(self):
|
||||
return kernel32proxy.GetCurrentProcess()
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
"""Process ID
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return os.getpid()
|
||||
|
||||
# Is there a better way ?
|
||||
@property
|
||||
def ppid(self):
|
||||
"""Parent Process ID
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return [p for p in windows.system.processes if p.pid == self.pid][0].ppid
|
||||
|
||||
@property
|
||||
def peb(self):
|
||||
"""The Process Environment Block of the current process
|
||||
|
||||
:type: :class:`PEB`
|
||||
"""
|
||||
return PEB.from_address(self.get_peb_builtin()())
|
||||
|
||||
@property
|
||||
def bitness(self):
|
||||
"""Return 32 or 64"""
|
||||
"""The bitness of the process
|
||||
|
||||
:returns: int -- 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())
|
||||
|
||||
def virtual_alloc(self, size):
|
||||
"""Allocate memory in the current process
|
||||
|
||||
:returns: int
|
||||
"""
|
||||
return kernel32proxy.VirtualAlloc(dwSize=size)
|
||||
|
||||
def write_memory(self, addr, data):
|
||||
"""Write data at addr"""
|
||||
buffertype = (c_char * len(data)).from_address(addr)
|
||||
buffertype[:len(data)] = data
|
||||
return True
|
||||
|
||||
def read_memory(self, addr, size):
|
||||
"""Read size from adddr"""
|
||||
buffer = (c_char * size).from_address(addr)
|
||||
return buffer[:]
|
||||
|
||||
class WinProcess(PROCESSENTRY32, AutoHandle):
|
||||
def create_thread(self, lpStartAddress, lpParameter, dwCreationFlags=0):
|
||||
"""Create a new thread
|
||||
|
||||
.. note::
|
||||
CreateThread https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx
|
||||
"""
|
||||
return kernel32proxy.CreateThread(lpStartAddress=lpStartAddress, lpParameter=lpParameter, dwCreationFlags=dwCreationFlags)
|
||||
|
||||
def exit(self, code=0):
|
||||
"""Exit the process"""
|
||||
return kernel32proxy.ExitProcess(code)
|
||||
|
||||
class WinProcess(PROCESSENTRY32, Process):
|
||||
"""A Process on the system"""
|
||||
is_pythondll_injected = 0
|
||||
is_remote_slave_running = False
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Name of the process
|
||||
|
||||
:type: str
|
||||
"""
|
||||
return self.szExeFile[:]
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
"""Process ID
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.th32ProcessID
|
||||
|
||||
@property
|
||||
def ppid(self):
|
||||
return self.th32ParentProcessID
|
||||
"""Parent Process ID
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
return [thread for thread in utils.enumerate_threads() if thread.th32OwnerProcessID == self.pid]
|
||||
:type: int
|
||||
"""
|
||||
return self.th32ParentProcessID
|
||||
|
||||
def _get_handle(self):
|
||||
return kernel32proxy.OpenProcess(dwProcessId=self.pid)
|
||||
@@ -137,22 +280,15 @@ class WinProcess(PROCESSENTRY32, AutoHandle):
|
||||
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)
|
||||
|
||||
@property
|
||||
def bitness(self):
|
||||
if windows.system.bitness == 32:
|
||||
return 32
|
||||
if self.is_wow_64:
|
||||
return 32
|
||||
return 64
|
||||
|
||||
def virtual_alloc(self, size):
|
||||
"""Allocate memory in the process
|
||||
|
||||
:returns: int
|
||||
"""
|
||||
return kernel32proxy.VirtualAllocEx(self.handle, dwSize=size)
|
||||
|
||||
def write_memory(self, addr, data):
|
||||
"""Write `data` at `addr`"""
|
||||
return kernel32proxy.WriteProcessMemory(self.handle, addr, lpBuffer=data)
|
||||
|
||||
def low_read_memory(self, addr, buffer_addr, size):
|
||||
@@ -163,67 +299,58 @@ class WinProcess(PROCESSENTRY32, AutoHandle):
|
||||
return kernel32proxy.ReadProcessMemory(self.handle, addr, lpBuffer=buffer_addr, nSize=size)
|
||||
|
||||
def read_memory(self, addr, size):
|
||||
"""Read `size` from `addr`"""
|
||||
buffer = ctypes.create_string_buffer(size)
|
||||
self.low_read_memory(addr, ctypes.byref(buffer), size)
|
||||
return buffer[:]
|
||||
|
||||
def read_memory_into(self, addr, struct):
|
||||
"""Read a :mod:`ctypes` struct from `addr`"""
|
||||
self.low_read_memory(addr, ctypes.byref(struct), ctypes.sizeof(struct))
|
||||
return struct
|
||||
|
||||
def create_thread(self, addr, param):
|
||||
"""Create a remote thread"""
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
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):
|
||||
"""Load the library in remote process"""
|
||||
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):
|
||||
"""Execute Python code into the remote process"""
|
||||
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):
|
||||
"""An entry in the PEB Ldr list"""
|
||||
@property
|
||||
def baseaddr(self):
|
||||
"""base address of the module
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.DllBase
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Name of the module
|
||||
|
||||
:type: str
|
||||
"""
|
||||
return self.BaseDllName.Buffer
|
||||
|
||||
@property
|
||||
def fullname(self):
|
||||
"""Full name of the module (path)
|
||||
|
||||
:type: str
|
||||
"""
|
||||
return self.FullDllName.Buffer
|
||||
|
||||
def __repr__(self):
|
||||
@@ -231,9 +358,14 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
|
||||
@property
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
return pe_parse.PEFile(self.baseaddr)
|
||||
|
||||
class WinUnicodeString(LSA_UNICODE_STRING):
|
||||
"""LSA_UNICODE_STRING with a nice `__repr__`"""
|
||||
def __repr__(self):
|
||||
return """<{0} "{1}" at {2}>""".format(type(self).__name__, self.Buffer, hex(id(self)))
|
||||
|
||||
@@ -243,22 +375,33 @@ class LIST_ENTRY_PTR(PVOID):
|
||||
return LDR_DATA_TABLE_ENTRY.from_address(self.value - sizeof(PVOID) * 2)
|
||||
|
||||
|
||||
# May want to have all known fields..
|
||||
class PEB(PEB):
|
||||
|
||||
"""The PEB (Process Environment Block) of the current process"""
|
||||
@property
|
||||
def imagepath(self):
|
||||
"""The ImagePathName of the PEB
|
||||
|
||||
:type: :class:`WinUnicodeString`
|
||||
"""
|
||||
raw_imagepath = self.ProcessParameters.contents.ImagePathName
|
||||
return WinUnicodeString.from_address(ctypes.addressof(raw_imagepath))
|
||||
|
||||
@property
|
||||
def commandline(self):
|
||||
"""The CommandLine of the PEB
|
||||
|
||||
:type: :class:`WinUnicodeString`
|
||||
"""
|
||||
# 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):
|
||||
"""The loaded modules present in the PEB
|
||||
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules
|
||||
"""
|
||||
res = []
|
||||
list_entry_ptr = ctypes.cast(self.Ldr.contents.InMemoryOrderModuleList.Flink, LIST_ENTRY_PTR)
|
||||
current_dll = list_entry_ptr.TO_LDR_ENTRY()
|
||||
|
||||
Reference in New Issue
Block a user