From 2094ab4ad4c6a099048690ce57ab04377372a36b Mon Sep 17 00:00:00 2001 From: hakril Date: Sun, 15 Oct 2017 00:13:07 +0200 Subject: [PATCH] Fix some docstring + re-add windows.test.pop_proc_[32|64] + fix all samples + few doc adapt --- README.md | 9 ++++--- ctypes_generation/definitions/winstruct.txt | 14 ----------- ctypes_generation/generate.py | 6 ++--- docs/source/testing.rst | 21 ---------------- samples/crypto/certificate.py | 11 ++++---- samples/debug/attach.py | 2 +- samples/debug/debug_functionbp.py | 2 +- samples/debug/debugger_api.py | 2 +- samples/debug/debugger_membp_singlestep.py | 2 +- samples/debug/debugger_print_LdrLoaddll.py | 2 +- .../debug/local_debugger_remote_process.py | 2 +- samples/native_utils.py | 2 +- samples/process/remote_veh_segv.py | 2 +- samples/test_code.py | 4 +-- tests/test_network.py | 25 +++++++++++++++++++ windows/alpc.py | 2 +- windows/crypto/certificate.py | 2 +- windows/crypto/generation.py | 1 + windows/generated_def/winstructs.py | 19 -------------- windows/test.py | 25 +++++++++++++++++++ windows/utils/winutils.py | 1 - 21 files changed, 78 insertions(+), 78 deletions(-) delete mode 100644 docs/source/testing.rst create mode 100644 tests/test_network.py create mode 100644 windows/test.py diff --git a/README.md b/README.md index 8af7fed..6ebc329 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ You can find some examples of code in the [samples directory][SAMPLE_DIR] or [on Parts of PythonForWindows are used in the [LKD project][LKD_GITHUB]. +If you have any issue, question, suggestion do not hesitate to contact me. +I am always glad to have feedbacks from people using this project. + ## Overview ### Processes / Threads @@ -102,7 +105,7 @@ So the features is present (See [online documentation][ONLINE_IATHOOK] about IAT ### Winproxy A wrapper around some Windows functions. Arguments name and order are the same, -but some have default values and the functions raise exception on call error (I don't like 'if' around all my call). +but some have default values and the functions raise exception on call error (I don't like `if` around all my call). ```python >>> import windows @@ -150,8 +153,8 @@ windows.winproxy.Kernel32Error: VirtualAlloc: [Error 8] Not enough storage is av ### Native execution -To make the barrier between `native` and `Python` code, -PythonForWindows allows you to create native function callable from Python (thanks `ctypes`) and also embed +To make the barrier between `native` and `Python` code thinner, +PythonForWindows allows you to create native function callable from Python (thanks to `ctypes`) and also embed a simple x86/x64 assembler. ```python diff --git a/ctypes_generation/definitions/winstruct.txt b/ctypes_generation/definitions/winstruct.txt index ba79763..4242055 100644 --- a/ctypes_generation/definitions/winstruct.txt +++ b/ctypes_generation/definitions/winstruct.txt @@ -489,13 +489,6 @@ typedef enum _SID_NAME_USE { SidTypeLabel = 10 } SID_NAME_USE, *PSID_NAME_USE; -typedef enum NET_FW_PROFILE_TYPE2_ { - NET_FW_PROFILE2_DOMAIN = 0x1, - NET_FW_PROFILE2_PRIVATE = 0x2, - NET_FW_PROFILE2_PUBLIC = 0x4, - NET_FW_PROFILE2_ALL = 0x7fffffff -} NET_FW_PROFILE_TYPE2; - typedef enum NET_FW_ACTION_ { NET_FW_ACTION_BLOCK = 0, NET_FW_ACTION_ALLOW = 1, @@ -508,13 +501,6 @@ typedef enum NET_FW_MODIFY_STATE_ { NET_FW_MODIFY_STATE_INBOUND_BLOCKED = 2 } NET_FW_MODIFY_STATE; -typedef enum NET_FW_RULE_DIRECTION_ { - NET_FW_RULE_DIR_IN = 1, - NET_FW_RULE_DIR_OUT = 2 , - NET_FW_RULE_DIR_MAX = 3 -} NET_FW_RULE_DIRECTION; - - typedef enum tag_WBEMSTATUS { WBEM_NO_ERROR = 0, diff --git a/ctypes_generation/generate.py b/ctypes_generation/generate.py index 9ed4adf..0fef981 100644 --- a/ctypes_generation/generate.py +++ b/ctypes_generation/generate.py @@ -252,7 +252,7 @@ class InitialDefGenerator(CtypesGenerator): return ctypes_code def generate_doc(self, target_file): - all_lines = [".. currentmodule:: windows.generated_def\n" + all_lines = [".. currentmodule:: windows.generated_def\n\n" "Windef\n" "------\n"] all_lines += [".. autodata:: {windef.name}\n".format(windef=windef) for windef in self.parse()] @@ -356,7 +356,7 @@ class StructGenerator(CtypesGenerator): self.check_dependances() def generate_doc(self, target_file): - all_lines = [".. currentmodule:: windows.generated_def\n" + all_lines = [".. currentmodule:: windows.generated_def\n\n" "Winstructs\n" "----------\n"] struct_separator = "'" @@ -494,7 +494,7 @@ class NtStatusGenerator(CtypesGenerator): return ctypes_code def generate_doc(self, target_file): - all_lines = [".. currentmodule:: windows.generated_def\n" + all_lines = [".. currentmodule:: windows.generated_def\n\n" "Ntstatus\n" "--------\n"] all_lines += [".. autodata:: {nstatus_name}\n".format(nstatus_name=nstatus[1]) for nstatus in self.parse()] diff --git a/docs/source/testing.rst b/docs/source/testing.rst deleted file mode 100644 index 16eb04d..0000000 --- a/docs/source/testing.rst +++ /dev/null @@ -1,21 +0,0 @@ -LOOL -**** - -.. module:: windows.generated_def - -.. class:: windows.generated_def.IMAGE_FILE_HEADER - - public name of :class:`windows.generated_def.winstructs._IMAGE_FILE_HEADER` - - -.. autoclass:: windows.generated_def.winstructs._PEB - -.. autoclass:: windows.generated_def.winstructs._PEB_LDR_DATA - - -yolo :class:`windows.generated_def.ERROR_RXACT_STATE_CREATED` - -:class:`windows.generated_def._ALPC_PORT_INFORMATION_CLASS` - - -:class:`windows.generated_def._ALPC_PORT_INFORMATION_CLASS.AlpcServerInformation` \ No newline at end of file diff --git a/samples/crypto/certificate.py b/samples/crypto/certificate.py index 6aba8b1..de72c5f 100644 --- a/samples/crypto/certificate.py +++ b/samples/crypto/certificate.py @@ -67,6 +67,7 @@ else: print("Not found :(") ## Extract certificates of a PE file +## This code is not a fixed API and the current state of my tests print ("") print ("== PE Analysis ==") @@ -74,15 +75,15 @@ TARGET_FILE = r"C:\windows\system32\ntdll.dll" print("Target sha1 = <{0}>".format(hashlib.sha1(open(TARGET_FILE, "rb").read()).hexdigest())) cryptobj = windows.crypto.CryptObject(TARGET_FILE) print("Analysing {0}".format(cryptobj)) -print("File has {0} signer(s):".format(cryptobj.nb_signer)) -for i, signer in ((i, cryptobj.get_signer_data(i)) for i in range(cryptobj.nb_signer)): +print("File has {0} signer(s):".format(cryptobj.crypt_msg.nb_signer)) +for i, signer in enumerate(cryptobj.crypt_msg.signers): print("Signer {0}:".format(i)) print(" * Issuer: {0!r}".format(windows.crypto.ECRYPT_DATA_BLOB(signer.Issuer.cbData, signer.Issuer.pbData).data)) print(" * HashAlgorithme: {0}".format(signer.HashAlgorithm.pszObjId)) - cert = cryptobj.get_signer_certificate(i) + cert = cryptobj.cert_store.find(signer.Issuer, signer.SerialNumber) print(" * Certificate: {0}".format(cert)) print("") -print("File embdeds {0} certificate(s):".format(cryptobj.nb_cert)) -for i, certificate in ((i, cryptobj.get_cert(i)) for i in range(cryptobj.nb_cert)): +print("File embdeds {0} certificate(s):".format(cryptobj.crypt_msg.nb_cert)) +for i, certificate in enumerate(cryptobj.crypt_msg.certs): print(" * {0}) {1}".format(i, certificate)) \ No newline at end of file diff --git a/samples/debug/attach.py b/samples/debug/attach.py index d46d206..7d96877 100644 --- a/samples/debug/attach.py +++ b/samples/debug/attach.py @@ -25,6 +25,6 @@ def follow_create_file(pid): if __name__ == "__main__": # Create a non-debugged process safe to debug - calc = windows.test.pop_calc_32(dwCreationFlags=0) + calc = windows.test.pop_proc_32(dwCreationFlags=0) # Give ovnly the PID to follow_create_file follow_create_file(calc.pid) diff --git a/samples/debug/debug_functionbp.py b/samples/debug/debug_functionbp.py index 6f53c53..bda9b84 100644 --- a/samples/debug/debug_functionbp.py +++ b/samples/debug/debug_functionbp.py @@ -42,7 +42,7 @@ class FollowNtCreateFile(windows.debug.FunctionBP): self.COUNTER -= 1 if __name__ == "__main__": - calc = windows.test.pop_calc_32(dwCreationFlags=DEBUG_PROCESS) + calc = windows.test.pop_proc_32(dwCreationFlags=DEBUG_PROCESS) d = windows.debug.Debugger(calc) d.add_bp(FollowNtCreateFile()) d.loop() \ No newline at end of file diff --git a/samples/debug/debugger_api.py b/samples/debug/debugger_api.py index 57ebaef..c85d9e6 100644 --- a/samples/debug/debugger_api.py +++ b/samples/debug/debugger_api.py @@ -71,6 +71,6 @@ class MyDebugger(windows.debug.Debugger): pass -calc = windows.test.pop_calc_32(dwCreationFlags=DEBUG_PROCESS) +calc = windows.test.pop_proc_32(dwCreationFlags=DEBUG_PROCESS) d = MyDebugger(calc) d.loop() diff --git a/samples/debug/debugger_membp_singlestep.py b/samples/debug/debugger_membp_singlestep.py index 7bf80b6..4dac3a6 100644 --- a/samples/debug/debugger_membp_singlestep.py +++ b/samples/debug/debugger_membp_singlestep.py @@ -43,7 +43,7 @@ class SingleStepOnWrite(windows.debug.MemoryBreakpoint): return dbg.single_step() -calc = windows.test.pop_calc_32(dwCreationFlags=DEBUG_PROCESS) +calc = windows.test.pop_proc_32(dwCreationFlags=DEBUG_PROCESS) d = MyDebugger(calc) code = calc.virtual_alloc(0x1000) diff --git a/samples/debug/debugger_print_LdrLoaddll.py b/samples/debug/debugger_print_LdrLoaddll.py index 623c7d5..70bb28a 100644 --- a/samples/debug/debugger_print_LdrLoaddll.py +++ b/samples/debug/debugger_print_LdrLoaddll.py @@ -39,7 +39,7 @@ class PrintUnicodeString(windows.debug.Breakpoint): dbg.current_process.exit() -calc = windows.test.pop_calc_32(dwCreationFlags=DEBUG_PROCESS) +calc = windows.test.pop_proc_32(dwCreationFlags=DEBUG_PROCESS) d = MyDebugger(calc) d.add_bp(PrintUnicodeString("ntdll!LdrLoadDll", argument_position=2)) d.loop() diff --git a/samples/debug/local_debugger_remote_process.py b/samples/debug/local_debugger_remote_process.py index 42c5432..0091608 100644 --- a/samples/debug/local_debugger_remote_process.py +++ b/samples/debug/local_debugger_remote_process.py @@ -35,7 +35,7 @@ d.add_bp(YOLOHXBP(ldr)) """ -c = windows.test.pop_calc_32(dwCreationFlags=CREATE_SUSPENDED) +c = windows.test.pop_proc_32(dwCreationFlags=CREATE_SUSPENDED) c.execute_python(remote_code) c.threads[0].resume() diff --git a/samples/native_utils.py b/samples/native_utils.py index 32b8624..493d23f 100644 --- a/samples/native_utils.py +++ b/samples/native_utils.py @@ -36,7 +36,7 @@ c += x64.Ret() RemoteManualLoadLibray += GetProcAddress64 -calc= windows.test.pop_calc_64(dwCreationFlags=CREATE_SUSPENDED) +calc= windows.test.pop_proc_64(dwCreationFlags=CREATE_SUSPENDED) addr = calc.virtual_alloc(0x1000) addr2 = addr + len(dll) diff --git a/samples/process/remote_veh_segv.py b/samples/process/remote_veh_segv.py index 600399e..a220a24 100644 --- a/samples/process/remote_veh_segv.py +++ b/samples/process/remote_veh_segv.py @@ -53,7 +53,7 @@ print("Protected page is at {0}".format(hex(target_page))) windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_READWRITE) """ -c = windows.test.pop_calc_64(dwCreationFlags=CREATE_SUSPENDED) +c = windows.test.pop_proc_64(dwCreationFlags=CREATE_SUSPENDED) x = c.execute_python(python_code) c.threads[0].resume() diff --git a/samples/test_code.py b/samples/test_code.py index d3bc91b..be4ad1b 100644 --- a/samples/test_code.py +++ b/samples/test_code.py @@ -116,7 +116,7 @@ class CodeTesteur(dbg.Debugger): def test_code_x86(code, regs=None, raw=False, **kwargs): print("Testing x86 code") - process = windows.test.pop_calc_32(dwCreationFlags=DEBUG_PROCESS) + process = windows.test.pop_proc_32(dwCreationFlags=DEBUG_PROCESS) if raw: code = code.replace(" ", "").decode('hex') else: @@ -140,7 +140,7 @@ def test_code_x64(code, regs=None, raw=False, **kwargs): print("Testing x64 code") if windows.current_process.bitness == 32: raise ValueError("Cannot debug a 64b process from 32b python") - process = windows.test.pop_calc_64(dwCreationFlags=DEBUG_PROCESS) + process = windows.test.pop_proc_64(dwCreationFlags=DEBUG_PROCESS) if raw: code = code.replace(" ", "").decode('hex') else: diff --git a/tests/test_network.py b/tests/test_network.py new file mode 100644 index 0000000..98dc48e --- /dev/null +++ b/tests/test_network.py @@ -0,0 +1,25 @@ +import windows +import windows.generated_def as gdef + +def test_ipv4_connection(): + windows.system.network.ipv4 # Better idea ? + +def test_ipv6_connection(): + windows.system.network.ipv6 # Better idea ? + +def test_firewall(): + firewall = windows.system.network.firewall + assert firewall.enabled # Its a dict that should not be empty + assert firewall.rules # Its a list that should not be empty + # Just check that fields exists and do not crash for now + rule = firewall.rules[0] + rule.name + rule.description + rule.protocol + rule.remote_port + rule.local_port + rule.local_address + rule.remote_address + rule.application_name + rule.direction + rule.enabled diff --git a/windows/alpc.py b/windows/alpc.py index be95623..6a4dc9f 100644 --- a/windows/alpc.py +++ b/windows/alpc.py @@ -61,7 +61,7 @@ class AlpcMessage(object): @property def security_attribute(self): """The :data:`~windows.generated_def.ALPC_MESSAGE_SECURITY_ATTRIBUTE` of the message - : + :type: :class:`ALPC_SECURITY_ATTR` """ return self.attributes.get_attribute(gdef.ALPC_MESSAGE_SECURITY_ATTRIBUTE) diff --git a/windows/crypto/certificate.py b/windows/crypto/certificate.py index 484d71c..be75a40 100644 --- a/windows/crypto/certificate.py +++ b/windows/crypto/certificate.py @@ -430,7 +430,7 @@ class CryptContext(gdef.HCRYPTPROV): except WindowsError as e: if not self.retrycreate: raise - return winproxy.CryptAcquireContextW(self, self.pszContainer, self.pszProvider, self.dwProvType, self.dwFlags | CRYPT_NEWKEYSET) + return winproxy.CryptAcquireContextW(self, self.pszContainer, self.pszProvider, self.dwProvType, self.dwFlags | gdef.CRYPT_NEWKEYSET) def release(self): return winproxy.CryptReleaseContext(self, False) \ No newline at end of file diff --git a/windows/crypto/generation.py b/windows/crypto/generation.py index a351423..c796f23 100644 --- a/windows/crypto/generation.py +++ b/windows/crypto/generation.py @@ -1,3 +1,4 @@ +import windows from windows import winproxy from windows.generated_def import * diff --git a/windows/generated_def/winstructs.py b/windows/generated_def/winstructs.py index 540bef5..efd66b7 100644 --- a/windows/generated_def/winstructs.py +++ b/windows/generated_def/winstructs.py @@ -587,16 +587,6 @@ SID_NAME_USE = _SID_NAME_USE PSID_NAME_USE = POINTER(_SID_NAME_USE) -NET_FW_PROFILE2_DOMAIN = EnumValue("NET_FW_PROFILE_TYPE2_", "NET_FW_PROFILE2_DOMAIN", 0x1) -NET_FW_PROFILE2_PRIVATE = EnumValue("NET_FW_PROFILE_TYPE2_", "NET_FW_PROFILE2_PRIVATE", 0x2) -NET_FW_PROFILE2_PUBLIC = EnumValue("NET_FW_PROFILE_TYPE2_", "NET_FW_PROFILE2_PUBLIC", 0x4) -NET_FW_PROFILE2_ALL = EnumValue("NET_FW_PROFILE_TYPE2_", "NET_FW_PROFILE2_ALL", 0x7fffffff) -class NET_FW_PROFILE_TYPE2_(EnumType): - values = [NET_FW_PROFILE2_DOMAIN, NET_FW_PROFILE2_PRIVATE, NET_FW_PROFILE2_PUBLIC, NET_FW_PROFILE2_ALL] - mapper = {x:x for x in values} -NET_FW_PROFILE_TYPE2 = NET_FW_PROFILE_TYPE2_ - - NET_FW_ACTION_BLOCK = EnumValue("NET_FW_ACTION_", "NET_FW_ACTION_BLOCK", 0x0) NET_FW_ACTION_ALLOW = EnumValue("NET_FW_ACTION_", "NET_FW_ACTION_ALLOW", 0x1) NET_FW_ACTION_MAX = EnumValue("NET_FW_ACTION_", "NET_FW_ACTION_MAX", 0x2) @@ -615,15 +605,6 @@ class NET_FW_MODIFY_STATE_(EnumType): NET_FW_MODIFY_STATE = NET_FW_MODIFY_STATE_ -NET_FW_RULE_DIR_IN = EnumValue("NET_FW_RULE_DIRECTION_", "NET_FW_RULE_DIR_IN", 0x1) -NET_FW_RULE_DIR_OUT = EnumValue("NET_FW_RULE_DIRECTION_", "NET_FW_RULE_DIR_OUT", 0x2) -NET_FW_RULE_DIR_MAX = EnumValue("NET_FW_RULE_DIRECTION_", "NET_FW_RULE_DIR_MAX", 0x3) -class NET_FW_RULE_DIRECTION_(EnumType): - values = [NET_FW_RULE_DIR_IN, NET_FW_RULE_DIR_OUT, NET_FW_RULE_DIR_MAX] - mapper = {x:x for x in values} -NET_FW_RULE_DIRECTION = NET_FW_RULE_DIRECTION_ - - WBEM_NO_ERROR = EnumValue("tag_WBEMSTATUS", "WBEM_NO_ERROR", 0x0) WBEM_S_NO_ERROR = EnumValue("tag_WBEMSTATUS", "WBEM_S_NO_ERROR", 0x0) WBEM_S_SAME = EnumValue("tag_WBEMSTATUS", "WBEM_S_SAME", 0x0) diff --git a/windows/test.py b/windows/test.py new file mode 100644 index 0000000..f3ad100 --- /dev/null +++ b/windows/test.py @@ -0,0 +1,25 @@ +import windows +import windows.generated_def as gdef +from windows.utils import create_process, DisableWow64FsRedirection + + +test_binary_name = "notepad.exe" +DEFAULT_CREATION_FLAGS = gdef.CREATE_NEW_CONSOLE + +if windows.system.bitness == 32: + def pop_proc_32(dwCreationFlags=DEFAULT_CREATION_FLAGS): + return create_process(r"C:\Windows\system32\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True) + + def pop_proc_64(dwCreationFlags=DEFAULT_CREATION_FLAGS): + raise WindowsError("Cannot create calc64 in 32bits system") +else: + def pop_proc_32(dwCreationFlags=DEFAULT_CREATION_FLAGS): + return create_process(r"C:\Windows\syswow64\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True) + + if windows.current_process.bitness == 32: + def pop_proc_64(dwCreationFlags=DEFAULT_CREATION_FLAGS): + with DisableWow64FsRedirection(): + return create_process(r"C:\Windows\system32\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True) + else: + def pop_proc_64(dwCreationFlags=DEFAULT_CREATION_FLAGS): + return create_process(r"C:\Windows\system32\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True) \ No newline at end of file diff --git a/windows/utils/winutils.py b/windows/utils/winutils.py index 6f9d7e4..a152b09 100644 --- a/windows/utils/winutils.py +++ b/windows/utils/winutils.py @@ -192,7 +192,6 @@ def pop_shell(locs=None): create_console() FixedInteractiveConsole(locs).interact() - def get_kernel_modules(): if windows.current_process.is_wow_64: return get_kernel_modules_syswow64()