PythonForWindows


NamePythonForWindows JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/hakril/PythonForWindows
SummaryA codebase aimed to make interaction with Windows and native execution easier
upload_time2024-06-14 16:55:31
maintainerNone
docs_urlNone
authorHakril
requires_pythonNone
licenseBSD
keywords windows python
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PythonForWindows

[![Pytest](https://github.com/hakril/PythonForWindows/actions/workflows/mypytest.yml/badge.svg?branch=master)](https://github.com/hakril/PythonForWindows/actions/workflows/mypytest.yml)

PythonForWindows (PFW) is a base of code aimed to make interaction with `Windows` (on X86/X64) easier (for both 32 and 64 bits Python).
Its goal is to offer abstractions around some of the OS features in a (I hope) pythonic way.
It also tries to make the barrier between python and native execution thinner in both ways.
There is no external dependencies but it relies heavily on the `ctypes` module.

Let's say that the codebase evolves with my needs, my researches and my curiosity.

Complete online documentation is available [here][ONLINE_DOC]
You can find some examples of code in the [samples directory][SAMPLE_DIR] or [online][ONLINE_SAMPLE].

PythonForWindows is principally known for:

- its ALPC-RPC Client (see [samples](https://hakril.github.io/PythonForWindows/build/html/sample.html#windows-rpc))
- its generated [ctypes definitions](https://github.com/hakril/PythonForWindows/tree/master/windows/generated_def).



If you have any issue, question or suggestion do not hesitate to create an issue or reach me out.
I am always glad to have feedbacks from people using this project.

## Installation


PythonForWindows is available on [Pypi](https://pypi.org/project/PythonForWindows/) an this can be installed with

``
python -m pip install PythonForWindows
``

You can also install PythonForWindows by cloning it and using the ``setup.py`` script:

``
python setup.py install
``

## Encoding & unicode

PythonForWindows support `python2.7` & `python3` and is currently tested for `Python2.7`, `3.6` & `3.11` via [Github Workflow](https://github.com/hakril/PythonForWindows/actions/workflows/mypytest.yml)

Since 1.0.0, the code uses "wide APIs" whenever possible and accept/returns python3 `str` (py2.7 `unicode` type) almost everywhere. Any functions/APIs not accepting unicode string can be  considered a bug if its not stated explicitly in the documentation.

### Python2

PythonForWindows continues to support python2.7 as its the only way to have it running on `Windows XP` & `Windows Server 2003` which are sadly still seen in production.
Encoding errors at print time might be awkward for unicode string on python2, see the [PythonForWindows encoding guide](https://hakril.github.io/PythonForWindows/build/html/encoding.html) in the documentation.


## Overview

### Processes / Threads

PythonForWindows offers objects around processes and allows you to:

- Retrieve basic process informations (pid, name, ppid, bitness, ...)
- Perform basic interprocess operation (allocation, create thread, read/write memory)
- Explore the PEB (Process Environment Block)
- Execute `native` and `Python` code in the context of a process.

I try my best to make those features available for every cross-bitness processes (`32 <-> 64` in both ways).
This involves relying on non-documented `Windows` functions/behaviours and also injecting code in the 64bits world of a `Syswow64` process.
All those operations are also available for the `current_process`.

You can also make some operation on threads (suspend/resume/wait/get(or set) context/ kill)

```python
>>> import windows
>>> windows.current_process.bitness
32
>>> windows.current_process.token.integrity
SECURITY_MANDATORY_MEDIUM_RID(0x2000)
>>> proc = [p for p in windows.system.processes if p.name == "notepad.exe"][0]
>>> proc
<WinProcess "notepad.exe" pid 16520 at 0x544e410>
>>> proc.bitness
64
>>> proc.peb.modules[:3]
[<RemoteLoadedModule64 "notepad.exe" at 0x3671e90>, <RemoteLoadedModule64 "ntdll.dll" at 0x3671030>, <RemoteLoadedModule64 "kernel32.dll" at 0x3671080>]
>>> k32 = proc.peb.modules[2]
>>> hex(k32.pe.exports["CreateFileW"])
'0x7ffee6761550L'
>>> proc.threads[0]
<WinThread 17688 owner "notepad.exe" at 0x53b47f0>
>>> hex(proc.threads[0].context.Rip)
'0x7ffee68b54b0L'
>>> proc.execute_python("import os")
True
>>> proc.execute_python("exit(os.getpid() + 1)")
# execute_python raise if process died
Traceback (most recent call last):
...
WindowsError: <WinProcess "notepad.exe" pid 16520 (DEAD) at 0x579f610> died during execution of python command
>>> calc
<WinProcess "notepad.exe" pid 16520 (DEAD) at 0x579f610>
>>> calc.exit_code
16521L
```

### System information

Information about the Windows computer running the script are available through the `windows.system` object.

```python
>>> windows.system
<windows.winobject.system.System object at 0x03FEED10>
>>> windows.system.bitness
64
>>> windows.system.computer_name
'DESKTOP-VKUGISR'
>>> windows.system.product_type
VER_NT_WORKSTATION(0x1)
>>> windows.system.version
(10, 0)
>>> windows.system.version_name
'Windows 10'
>>> windows.system.build_number
'10.0.15063.608'

# windows.system also contains dynamic lists about processes / threads / handles / ...
>>> windows.system.handles[-2:]
[<Handle value=<0x5cc> in process pid=14360>, <Handle value=<0x28e4> in process pid=14360>]
>>> windows.system.processes[:2]
[<WinProcess "[System Process]" pid 0 at 0x433f7d0>, <WinProcess "System" pid 4 at 0x433fd30>]
>>> windows.system.logicaldrives[0]
<LogicalDrive "C:\" (DRIVE_FIXED)>
>>> windows.system.services[23]
<ServiceA "Appinfo" SERVICE_RUNNING(0x4)>

```

### IAT Hook

This codebase is born from my need to have IAT hooks implemented in Python.
So the features is present (See [online documentation][ONLINE_IATHOOK] about IAT hooks).


### 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).

```python
>>> import windows
>>> help(windows.winproxy.VirtualAlloc)
# Help on function VirtualAlloc in module windows.winproxy:
# VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT(0x1000L), flProtect=PAGE_EXECUTE_READWRITE(0x40L))
#     Errcheck:
#     raise WinproxyError if result is 0

# Positional arguments
>>> windows.winproxy.VirtualAlloc(0, 0x1000)
34537472

# Keyword arguments
>>> windows.winproxy.VirtualAlloc(dwSize=0x1000)
34603008

# NeededParameter must be provided
>>> windows.winproxy.VirtualAlloc()
"""
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "windows\winproxy.py", line 264, in VirtualAlloc
    return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
File "windows\winproxy.py", line 130, in perform_call
    raise TypeError("{0}: Missing Mandatory parameter <{1}>".format(self.func_name, param_name))
TypeError: VirtualAlloc: Missing Mandatory parameter <dwSize>
"""

# Error raises exception
>>> windows.winproxy.VirtualAlloc(dwSize=0xffffffff)
"""
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "windows\winproxy.py", line 264, in VirtualAlloc
    return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
File "windows\winproxy.py", line 133, in perform_call
    return self._cprototyped(*args)
File "windows\winproxy.py", line 59, in kernel32_error_check
    raise WinproxyError(func_name)
windows.winproxy.error.WinproxyError: VirtualAlloc: [Error 87] The parameter is incorrect.
"""
```


### Native execution

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
>>> import windows.native_exec.simple_x86 as x86
>>> code = x86.MultipleInstr()
>>> code += x86.Mov("EAX", 41)
>>> code += x86.Inc("EAX")
>>> code += x86.Ret()
>>> code.get_code()
'\xc7\xc0)\x00\x00\x00@\xc3'
# Create a function that takes no parameters and return an uint
>>> f = windows.native_exec.create_function(code.get_code(), [ctypes.c_uint])
>>> f()
42L
# Assemblers can also be used in a more standard way
>>> x86.assemble("cmp edi, 0; jnz :end; mov eax, 1; label :end; ret")
'\x81\xff\x00\x00\x00\x00u\x06\xc7\xc0\x01\x00\x00\x00\xc3'
```

### Token / Security Descriptor

Objects easing access to some information about ``Token`` and ``SecurityDescriptor`` are also available.

```python
>>> import windows.security
>>> import windows.generated_def as gdef
>>> tok = windows.current_process.token
>>> tok
<Token TokenId=0x6a2b4550 Type=TokenPrimary(0x1)>
>>> tok.username
u'hakril'
>>> tok.type
tagTOKEN_TYPE.TokenPrimary(0x1)
>>> tok.integrity
SECURITY_MANDATORY_MEDIUM_RID(0x2000)
>>> tok.duplicate(type=gdef.TokenImpersonation, impersonation_level=gdef.SecurityIdentification)
<Token TokenId=0x6a3532ce Type=TokenImpersonation(0x2) ImpersonationLevel=SecurityIdentification(0x1)>

# Security Descriptor
>>> sd = windows.security.SecurityDescriptor.from_filename("c:\windows\system32\kernel32.dll")
>>> sd
<SecurityDescriptor object at 0x054E3DF0>
>>> windows.utils.lookup_sid(sd.owner)
(u'NT SERVICE', u'TrustedInstaller')
>>> sd.dacl
<Acl count=6>
>>> list(sd.dacl)
[<AccessAllowedACE mask=2032127>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>]
>>> sd.dacl[1].sid
<PSID "S-1-5-32-544">
```

### Wintrust

To easily script some signature check script, PythonForWindows implements some wrapper functions around ``wintrust.dll``

```python
>>> import windows.wintrust
>>> windows.wintrust.is_signed(r"C:\Windows\system32\ntdll.dll")
True
>>> windows.wintrust.is_signed(r"C:\Windows\system32\python27.dll")
False
>>> windows.wintrust.full_signature_information(r"C:\Windows\system32\ntdll.dll")
SignatureData(signed=True,
    catalog=u'C:\\Windows\\system32\\CatRoot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\\Package_35_for_KB3128650~31bf3856ad364e35~amd64~~6.3.1.2.cat',
    catalogsigned=True, additionalinfo=0L)
>>> windows.wintrust.full_signature_information(r"C:\Windows\system32\python27.dll")
SignatureData(signed=False, catalog=None, catalogsigned=False, additionalinfo=TRUST_E_NOSIGNATURE(0x800b0100))
```

### WMI

To extract/play with even more information about the system, PythonForWindows is able to perform WMI request.

```python
>>> import windows
>>> windows.system.wmi.select
<bound method WmiNamespace.select of <WmiNamespace "root\cimv2">>
>>> windows.system.wmi.select("Win32_Process")[:3]
[<WmiObject instance of "Win32_Process">, <WmiObject instance of "Win32_Process">, <WmiObject instance of "Win32_Process">]# Get WMI data for current process
>>> windows.system.wmi.select("Win32_Process")[42]["Name"]
u'svchost.exe'
>>> wmi_cp = [p for p in windows.system.wmi.select("Win32_Process") if int(p["Handle"]) == windows.current_process.pid][0]
>>> wmi_cp["CommandLine"], wmi_cp["HandleCount"]
(u'"C:\\Python27\\python.exe"', 227)
```

### Registry

The project also contains some wrapping classes around `_winreg` for simpler use.

```python
>>> import windows
>>> from windows.generated_def import KEY_WRITE, KEY_READ, REG_QWORD
>>> registry = windows.system.registry
>>> cuuser_software = registry(r'HKEY_CURRENT_USER\Software')
>>> cuuser_software
<PyHKey "HKEY_CURRENT_USER\Software">
>>> cuuser_software.sam
KEY_READ(0x20019)
# Explore subkeys
>>> cuuser_software.subkeys[:3]
[<PyHKey "HKEY_CURRENT_USER\Software\7-Zip">, <PyHKey "HKEY_CURRENT_USER\Software\AppDataLow">, <PyHKey "HKEY_CURRENT_USER\Software\Audacity">]
>>> tstkey = registry('HKEY_CURRENT_USER\TestKey',  KEY_WRITE | KEY_READ)
# Get / Set individual value
>>> tstkey["VALUE"] = 'a_value_for_my_key'
>>> tstkey["VALUE"]
KeyValue(name='VALUE', value=u'a_value_for_my_key', type=1)
>>> tstkey["MYQWORD"] = (123456789987654321, REG_QWORD)  # Default is REG_DWORD for int/long
>>> tstkey["MYQWORD"]
KeyValue(name='MYQWORD', value=123456789987654321L, type=11)
# Explore Values
>>> tstkey.values
[KeyValue(name='MYQWORD', value=123456789987654321L, type=11), KeyValue(name='VALUE', value=u'a_value_for_my_key', type=1)]
```

### Object manager

PythonForWindows uses the native Windows NT API to display some information about the object in the Object Manager's name space.
Just like the well-known tools ``winobj.exe``

```python
>>> windows.system.object_manager.root
<KernelObject "\" (type="Directory")>
# The objects of type "Directory" can be acceded just like a dict
>>> list(windows.system.object_manager.root)[:3]
[u'PendingRenameMutex', u'ObjectTypes', u'storqosfltport']
# Find an object by its path
>>> windows.system.object_manager["KnownDLLs\\kernel32.dll"]
<KernelObject "\KnownDLLs\kernel32.dll" (type="Section")>
>>> k32 = windows.system.object_manager["KnownDLLs\\kernel32.dll"]
>>> k32.name, k32.fullname, k32.type
('kernel32.dll', '\\KnownDLLs\\kernel32.dll', u'Section')
# Follow SymbolicLink object
>>> windows.system.object_manager["\\KnownDLLs\\KnownDLLPath"]
<KernelObject "\KnownDLLs\KnownDLLPath" (type="SymbolicLink")>
>>> windows.system.object_manager["\\KnownDLLs\\KnownDLLPath"].target
u'C:\\WINDOWS\\System32'
```

### Scheduled Task

The ``windows.system.task_scheduler`` object allows to query and create scheduled task.

**This part is still in developpement and the API may evolve**

```python
>>> windows.system.task_scheduler
<TaskService at 0x4774670>
>>> windows.system.task_scheduler.root
<TaskFolder "\" at 0x4774710>
>>> task = windows.system.task_scheduler.root.tasks[2]
>>> task
<Task "DemoTask" at 0x47748f0>
>>> task.name
u'DemoTask'
# Explore task actions
>>> task.definition.actions[1]
<ExecAction at 0x4774800>
>>> task.definition.actions[1].path
u'c:\\windows\\python\\python.exe'
>>> task.definition.actions[1].arguments
u'yolo.py --test'
```

### Event logs

The ``windows.system.event_log`` object allows to query event logs.

**This part is still in developpement and the API may evolve**

```python
>>> windows.system.event_log
<windows.winobject.event_log.EvtlogManager object at 0x04A78270>
# Find a channel by its name
>>> chan = windows.system.event_log["Microsoft-Windows-Windows Firewall With Advanced Security/Firewall"]
>>> chan
<EvtChannel "Microsoft-Windows-Windows Firewall With Advanced Security/Firewall">
# Open .evtx files
>>> windows.system.event_log["test.evtx"]
<EvtFile "test.evtx">
# Query a channel for all events
>>> chan.query().all()[:2]
[<EvtEvent id="2004" time="2018-07-12 07:44:08.081504">, <EvtEvent id="2006" time="2018-07-12 07:57:59.806938">]
# Query a channel for some ids
>>> chan.query(ids=2004).all()[:2]
[<EvtEvent id="2004" time="2018-07-12 07:44:08.081504">, <EvtEvent id="2004" time="2018-07-12 07:57:59.815156">]
# Query a channel via XPATH
>>> evt = chan.query("Event/EventData[Data='Netflix']").all()[0]
# Explore event information
>>> evt
<EvtEvent id="2006" time="2018-07-17 10:32:39.160423">
>>> evt.data
{u'ModifyingUser': 69828304, u'RuleName': u'Netflix', u'ModifyingApplication': ...}
```

### ALPC-RPC

#### ALPC

Classes around **A**dvanced **L**ocal **P**rocedure **C**all (**ALPC**) syscalls allows to simply
write client and server able to send **ALPC** messages.

```python
>>> import windows.alpc
# Test server juste reply to each message with "REQUEST '{msg_data}' RECEIVED"
>>> client = windows.alpc.AlpcClient(r"\RPC Control\PythonForWindowsTESTPORT")
>>> response = client.send_receive("Hello world !")
>>> response
<windows.alpc.AlpcMessage object at 0x04C0D5D0>
>>> response.data
"REQUEST 'Hello world !' RECEIVED"
```

Full client/server code for this example is available is the [ALPC samples][ONLINE_SAMPLE_ALPC] along with a more complex example.


#### RPC

An RPC-Client based using **ALPC** communication is also integred

```python
# Server (port ALPC '\RPC Control\HelloRpc') offers:
# Interface '41414141-4242-4343-4444-45464748494a' version 1.0
#   Method 1 -> int Add(int a, int b) -> return a + b
# This Test server is a real RPC Server using rpcrt4.dll and compiled with VS2015.

>>> import windows.rpc
>>> from windows.rpc import ndr
>>> client = windows.rpc.RPCClient(r"\RPC Control\HelloRpc")
>>> client
<windows.rpc.client.RPCClient object at 0x0411E130>
>>> iid = client.bind("41414141-4242-4343-4444-45464748494a")
>>> ndr_params = ndr.make_parameters([ndr.NdrLong] * 2)
# NDR pack + Make RPC call to method 1.
>>> resp = client.call(iid, 1, ndr_params.pack([41414141, 1010101]))
# Unpack the NDR response
>>> result = ndr.NdrLong.unpack(ndr.NdrStream(resp))
>>> result
42424242
```

A sample with the **U**ser **A**ccount **C**ontrol (**UAC**) and one with `lsasrv.dll` are available in the [RPC samples][ONLINE_SAMPLE_RPC].


### Debugger

PythonForWindows provides a standard debugger to debug other processes.

```python
import windows
import windows.debug
import windows.test
import windows.native_exec.simple_x86 as x86
import windows.generated_def as gdef

from windows.test import pop_proc_32

class MyDebugger(windows.debug.Debugger):
    def on_exception(self, exception):
        code = exception.ExceptionRecord.ExceptionCode
        addr = exception.ExceptionRecord.ExceptionAddress
        print("Got exception {0} at 0x{1:x}".format(code, addr))
        if code == gdef.EXCEPTION_ACCESS_VIOLATION:
            print("Access Violation: kill target process")
            self.current_process.exit()

calc = windows.test.pop_proc_32(dwCreationFlags=gdef.DEBUG_PROCESS)
d = MyDebugger(calc)
calc.execute(x86.assemble("int3; mov [0x42424242], EAX; ret"))
d.loop()

## Ouput ##
Got exception EXCEPTION_BREAKPOINT(0x80000003) at 0x77e13c7d
Got exception EXCEPTION_BREAKPOINT(0x80000003) at 0x230000
Got exception EXCEPTION_ACCESS_VIOLATION(0xc0000005) at 0x230001
Access Violation: kill target process
```

The debugger handles

* Standard breakpoint ``int3``
* Hardware Execution breakpoint ``DrX``
* Memory breakpoint ``virtual protect``


#### LocalDebugger

You can also debug your own process (or debug a process by injection) via the LocalDebugger.

The LocalDebugger is an abstraction around Vectored Exception Handler (VEH)

```python
import windows
from windows.generated_def.winstructs import *
import windows.native_exec.simple_x86 as x86

class SingleSteppingDebugger(windows.debug.LocalDebugger):
    SINGLE_STEP_COUNT = 4
    def on_exception(self, exc):
        code = self.get_exception_code()
        context = self.get_exception_context()
        print("EXCEPTION !!!! Got a {0} at 0x{1:x}".format(code, context.pc))
        self.SINGLE_STEP_COUNT -= 1
        if self.SINGLE_STEP_COUNT:
            return self.single_step()
        return EXCEPTION_CONTINUE_EXECUTION

class RewriteBreakpoint(windows.debug.HXBreakpoint):
    def trigger(self, dbg, exc):
        context = dbg.get_exception_context()
        print("GOT AN HXBP at 0x{0:x}".format(context.pc))
        # Rewrite the infinite loop with 2 nop
        windows.current_process.write_memory(self.addr, "\x90\x90")
        # Ask for a single stepping
        return dbg.single_step()


d = SingleSteppingDebugger()
# Infinite loop + nop + ret
code = x86.assemble("label :begin; jmp :begin; nop; ret")
func = windows.native_exec.create_function(code, [PVOID])
print("Code addr = 0x{0:x}".format(func.code_addr))
# Create a thread that will infinite loop
t = windows.current_process.create_thread(func.code_addr, 0)
# Add a breakpoint on the infinite loop
d.add_bp(RewriteBreakpoint(func.code_addr))
t.wait()
print("Done!")

## Output ##

Code addr = 0x6a0002
GOT AN HXBP at 0x6a0002
EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x6a0003
EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x6a0004
EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x6a0005
EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x770c7c04
Done!

```

The local debugger handles

* Standard breakpoint ``int3``
* Hardware Execution breakpoint ``DrX``

### Symbols

Classes around the Symbols APIs of `dbghelp.dll` are also implemented and can be used independently of the Debugger.
The path of `dbghelp.dll` can also be given via the `PFW_DBGHELP_PATH` environment variable.


```python
# Python3

>>> from windows.debug import symbols
>>> # symbols.set_dbghelp_path(MY_DBGHELP_PATH)
>>> symbols.engine.options = 0 # Disable defered load
>>> sh = symbols.VirtualSymbolHandler()
>>> ntmod = sh.load_file(r"c:\windows\system32\ntdll.dll", addr=0x420000)
>>> ntmod
<SymbolModule name="ntdll" type=SymPdb pdb="ntdll.pdb" addr=0x420000>
>>> ntmod.name
'ntdll'
>>> ntmod.path
'c:\\windows\\system32\\ntdll.dll'
>>> ntmod.pdb
'c:\\Symbols\\ntdll.pdb\\8D5D5ED5D5B8AA609A82600C14E3004D1\\ntdll.pdb'
>>> sym = sh["ntdll!LdrLoadDll"]
>>> sym
<SymbolInfoW name="LdrLoadDll" start=0x44a160 tag=SymTagFunction>
>>> sym.fullname
'ntdll!LdrLoadDll'
>>> hex(sym.addr)
'0x44a160'
>>> sh.search("ntdll!*CreateFile")
[<SymbolInfoW name="EtwpCreateFile" start=0x47d9ec tag=SymTagFunction>, <SymbolInfoW name="EtwpCreateFile" start=0x47d9ec tag=SymTagPublicSymbol>, <SymbolInfoW name="NtCreateFile" start=0x4c03e0 tag=SymTagPublicSymbol>, <SymbolInfoW name="ZwCreateFile" start=0x4c03e0 tag=SymTagPublicSymbol>, <SymbolInfoW name="__imp_NtCreateFile" start=0x55cb70 tag=SymTagPublicSymbol>]
# Some types exploration
>>> peb = sh.get_type("ntdll!_PEB")
>>> peb
<SymbolType name="_PEB" tag=_SymTagEnum.SymTagUDT(0xb)>
>>> peb.size
2000
>>> peb.children[:3]
[<SymbolType name="InheritedAddressSpace" tag=_SymTagEnum.SymTagData(0x7)>, <SymbolType name="ReadImageFileExecOptions" tag=_SymTagEnum.SymTagData(0x7)>, <SymbolType name="BeingDebugged" tag=_SymTagEnum.SymTagData(0x7)>]
>>> peb.children[2].offset
2
```

### Other stuff (see doc / samples)

- Network
- COM

## Acknowledgments

* clmntb for his initial work on ``windows.security``


[LKD_GITHUB]: https://github.com/sogeti-esec-lab/LKD/
[SAMPLE_DIR]: https://github.com/hakril/PythonForWindows/tree/master/samples
[ONLINE_DOC]: https://hakril.github.io/PythonForWindows/
[ONLINE_SAMPLE]: https://hakril.github.io/PythonForWindows/build/html/sample.html
[ONLINE_SAMPLE_ALPC]: https://hakril.github.io/PythonForWindows/build/html/sample.html#windows-alpc
[ONLINE_SAMPLE_RPC]: https://hakril.github.io/PythonForWindows/build/html/sample.html#windows-rpc
[ONLINE_IATHOOK]: https://hakril.github.io/PythonForWindows/build/html/iat_hook.html

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/hakril/PythonForWindows",
    "name": "PythonForWindows",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "windows python",
    "author": "Hakril",
    "author_email": "pfw@hakril.net",
    "download_url": "https://files.pythonhosted.org/packages/4c/7a/df1f9508453c32596f2bf462a42f6422e508aad296e9bb240769281d8fa5/PythonForWindows-1.0.0.tar.gz",
    "platform": null,
    "description": "# PythonForWindows\r\n\r\n[![Pytest](https://github.com/hakril/PythonForWindows/actions/workflows/mypytest.yml/badge.svg?branch=master)](https://github.com/hakril/PythonForWindows/actions/workflows/mypytest.yml)\r\n\r\nPythonForWindows (PFW) is a base of code aimed to make interaction with `Windows` (on X86/X64) easier (for both 32 and 64 bits Python).\r\nIts goal is to offer abstractions around some of the OS features in a (I hope) pythonic way.\r\nIt also tries to make the barrier between python and native execution thinner in both ways.\r\nThere is no external dependencies but it relies heavily on the `ctypes` module.\r\n\r\nLet's say that the codebase evolves with my needs, my researches and my curiosity.\r\n\r\nComplete online documentation is available [here][ONLINE_DOC]\r\nYou can find some examples of code in the [samples directory][SAMPLE_DIR] or [online][ONLINE_SAMPLE].\r\n\r\nPythonForWindows is principally known for:\r\n\r\n- its ALPC-RPC Client (see [samples](https://hakril.github.io/PythonForWindows/build/html/sample.html#windows-rpc))\r\n- its generated [ctypes definitions](https://github.com/hakril/PythonForWindows/tree/master/windows/generated_def).\r\n\r\n\r\n\r\nIf you have any issue, question or suggestion do not hesitate to create an issue or reach me out.\r\nI am always glad to have feedbacks from people using this project.\r\n\r\n## Installation\r\n\r\n\r\nPythonForWindows is available on [Pypi](https://pypi.org/project/PythonForWindows/) an this can be installed with\r\n\r\n``\r\npython -m pip install PythonForWindows\r\n``\r\n\r\nYou can also install PythonForWindows by cloning it and using the ``setup.py`` script:\r\n\r\n``\r\npython setup.py install\r\n``\r\n\r\n## Encoding & unicode\r\n\r\nPythonForWindows support `python2.7` & `python3` and is currently tested for `Python2.7`, `3.6` & `3.11` via [Github Workflow](https://github.com/hakril/PythonForWindows/actions/workflows/mypytest.yml)\r\n\r\nSince 1.0.0, the code uses \"wide APIs\" whenever possible and accept/returns python3 `str` (py2.7 `unicode` type) almost everywhere. Any functions/APIs not accepting unicode string can be  considered a bug if its not stated explicitly in the documentation.\r\n\r\n### Python2\r\n\r\nPythonForWindows continues to support python2.7 as its the only way to have it running on `Windows XP` & `Windows Server 2003` which are sadly still seen in production.\r\nEncoding errors at print time might be awkward for unicode string on python2, see the [PythonForWindows encoding guide](https://hakril.github.io/PythonForWindows/build/html/encoding.html) in the documentation.\r\n\r\n\r\n## Overview\r\n\r\n### Processes / Threads\r\n\r\nPythonForWindows offers objects around processes and allows you to:\r\n\r\n- Retrieve basic process informations (pid, name, ppid, bitness, ...)\r\n- Perform basic interprocess operation (allocation, create thread, read/write memory)\r\n- Explore the PEB (Process Environment Block)\r\n- Execute `native` and `Python` code in the context of a process.\r\n\r\nI try my best to make those features available for every cross-bitness processes (`32 <-> 64` in both ways).\r\nThis involves relying on non-documented `Windows` functions/behaviours and also injecting code in the 64bits world of a `Syswow64` process.\r\nAll those operations are also available for the `current_process`.\r\n\r\nYou can also make some operation on threads (suspend/resume/wait/get(or set) context/ kill)\r\n\r\n```python\r\n>>> import windows\r\n>>> windows.current_process.bitness\r\n32\r\n>>> windows.current_process.token.integrity\r\nSECURITY_MANDATORY_MEDIUM_RID(0x2000)\r\n>>> proc = [p for p in windows.system.processes if p.name == \"notepad.exe\"][0]\r\n>>> proc\r\n<WinProcess \"notepad.exe\" pid 16520 at 0x544e410>\r\n>>> proc.bitness\r\n64\r\n>>> proc.peb.modules[:3]\r\n[<RemoteLoadedModule64 \"notepad.exe\" at 0x3671e90>, <RemoteLoadedModule64 \"ntdll.dll\" at 0x3671030>, <RemoteLoadedModule64 \"kernel32.dll\" at 0x3671080>]\r\n>>> k32 = proc.peb.modules[2]\r\n>>> hex(k32.pe.exports[\"CreateFileW\"])\r\n'0x7ffee6761550L'\r\n>>> proc.threads[0]\r\n<WinThread 17688 owner \"notepad.exe\" at 0x53b47f0>\r\n>>> hex(proc.threads[0].context.Rip)\r\n'0x7ffee68b54b0L'\r\n>>> proc.execute_python(\"import os\")\r\nTrue\r\n>>> proc.execute_python(\"exit(os.getpid() + 1)\")\r\n# execute_python raise if process died\r\nTraceback (most recent call last):\r\n...\r\nWindowsError: <WinProcess \"notepad.exe\" pid 16520 (DEAD) at 0x579f610> died during execution of python command\r\n>>> calc\r\n<WinProcess \"notepad.exe\" pid 16520 (DEAD) at 0x579f610>\r\n>>> calc.exit_code\r\n16521L\r\n```\r\n\r\n### System information\r\n\r\nInformation about the Windows computer running the script are available through the `windows.system` object.\r\n\r\n```python\r\n>>> windows.system\r\n<windows.winobject.system.System object at 0x03FEED10>\r\n>>> windows.system.bitness\r\n64\r\n>>> windows.system.computer_name\r\n'DESKTOP-VKUGISR'\r\n>>> windows.system.product_type\r\nVER_NT_WORKSTATION(0x1)\r\n>>> windows.system.version\r\n(10, 0)\r\n>>> windows.system.version_name\r\n'Windows 10'\r\n>>> windows.system.build_number\r\n'10.0.15063.608'\r\n\r\n# windows.system also contains dynamic lists about processes / threads / handles / ...\r\n>>> windows.system.handles[-2:]\r\n[<Handle value=<0x5cc> in process pid=14360>, <Handle value=<0x28e4> in process pid=14360>]\r\n>>> windows.system.processes[:2]\r\n[<WinProcess \"[System Process]\" pid 0 at 0x433f7d0>, <WinProcess \"System\" pid 4 at 0x433fd30>]\r\n>>> windows.system.logicaldrives[0]\r\n<LogicalDrive \"C:\\\" (DRIVE_FIXED)>\r\n>>> windows.system.services[23]\r\n<ServiceA \"Appinfo\" SERVICE_RUNNING(0x4)>\r\n\r\n```\r\n\r\n### IAT Hook\r\n\r\nThis codebase is born from my need to have IAT hooks implemented in Python.\r\nSo the features is present (See [online documentation][ONLINE_IATHOOK] about IAT hooks).\r\n\r\n\r\n### Winproxy\r\n\r\nA wrapper around some Windows functions. Arguments name and order are the same,\r\nbut some have default values and the functions raise exception on call error (I don't like `if` around all my call).\r\n\r\n```python\r\n>>> import windows\r\n>>> help(windows.winproxy.VirtualAlloc)\r\n# Help on function VirtualAlloc in module windows.winproxy:\r\n# VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT(0x1000L), flProtect=PAGE_EXECUTE_READWRITE(0x40L))\r\n#     Errcheck:\r\n#     raise WinproxyError if result is 0\r\n\r\n# Positional arguments\r\n>>> windows.winproxy.VirtualAlloc(0, 0x1000)\r\n34537472\r\n\r\n# Keyword arguments\r\n>>> windows.winproxy.VirtualAlloc(dwSize=0x1000)\r\n34603008\r\n\r\n# NeededParameter must be provided\r\n>>> windows.winproxy.VirtualAlloc()\r\n\"\"\"\r\nTraceback (most recent call last):\r\nFile \"<stdin>\", line 1, in <module>\r\nFile \"windows\\winproxy.py\", line 264, in VirtualAlloc\r\n    return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)\r\nFile \"windows\\winproxy.py\", line 130, in perform_call\r\n    raise TypeError(\"{0}: Missing Mandatory parameter <{1}>\".format(self.func_name, param_name))\r\nTypeError: VirtualAlloc: Missing Mandatory parameter <dwSize>\r\n\"\"\"\r\n\r\n# Error raises exception\r\n>>> windows.winproxy.VirtualAlloc(dwSize=0xffffffff)\r\n\"\"\"\r\nTraceback (most recent call last):\r\nFile \"<stdin>\", line 1, in <module>\r\nFile \"windows\\winproxy.py\", line 264, in VirtualAlloc\r\n    return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)\r\nFile \"windows\\winproxy.py\", line 133, in perform_call\r\n    return self._cprototyped(*args)\r\nFile \"windows\\winproxy.py\", line 59, in kernel32_error_check\r\n    raise WinproxyError(func_name)\r\nwindows.winproxy.error.WinproxyError: VirtualAlloc: [Error 87] The parameter is incorrect.\r\n\"\"\"\r\n```\r\n\r\n\r\n### Native execution\r\n\r\nTo make the barrier between `native` and `Python` code thinner,\r\nPythonForWindows allows you to create native function callable from Python (thanks to `ctypes`) and also embed\r\na simple x86/x64 assembler.\r\n\r\n```python\r\n>>> import windows.native_exec.simple_x86 as x86\r\n>>> code = x86.MultipleInstr()\r\n>>> code += x86.Mov(\"EAX\", 41)\r\n>>> code += x86.Inc(\"EAX\")\r\n>>> code += x86.Ret()\r\n>>> code.get_code()\r\n'\\xc7\\xc0)\\x00\\x00\\x00@\\xc3'\r\n# Create a function that takes no parameters and return an uint\r\n>>> f = windows.native_exec.create_function(code.get_code(), [ctypes.c_uint])\r\n>>> f()\r\n42L\r\n# Assemblers can also be used in a more standard way\r\n>>> x86.assemble(\"cmp edi, 0; jnz :end; mov eax, 1; label :end; ret\")\r\n'\\x81\\xff\\x00\\x00\\x00\\x00u\\x06\\xc7\\xc0\\x01\\x00\\x00\\x00\\xc3'\r\n```\r\n\r\n### Token / Security Descriptor\r\n\r\nObjects easing access to some information about ``Token`` and ``SecurityDescriptor`` are also available.\r\n\r\n```python\r\n>>> import windows.security\r\n>>> import windows.generated_def as gdef\r\n>>> tok = windows.current_process.token\r\n>>> tok\r\n<Token TokenId=0x6a2b4550 Type=TokenPrimary(0x1)>\r\n>>> tok.username\r\nu'hakril'\r\n>>> tok.type\r\ntagTOKEN_TYPE.TokenPrimary(0x1)\r\n>>> tok.integrity\r\nSECURITY_MANDATORY_MEDIUM_RID(0x2000)\r\n>>> tok.duplicate(type=gdef.TokenImpersonation, impersonation_level=gdef.SecurityIdentification)\r\n<Token TokenId=0x6a3532ce Type=TokenImpersonation(0x2) ImpersonationLevel=SecurityIdentification(0x1)>\r\n\r\n# Security Descriptor\r\n>>> sd = windows.security.SecurityDescriptor.from_filename(\"c:\\windows\\system32\\kernel32.dll\")\r\n>>> sd\r\n<SecurityDescriptor object at 0x054E3DF0>\r\n>>> windows.utils.lookup_sid(sd.owner)\r\n(u'NT SERVICE', u'TrustedInstaller')\r\n>>> sd.dacl\r\n<Acl count=6>\r\n>>> list(sd.dacl)\r\n[<AccessAllowedACE mask=2032127>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>, <AccessAllowedACE mask=1179817>]\r\n>>> sd.dacl[1].sid\r\n<PSID \"S-1-5-32-544\">\r\n```\r\n\r\n### Wintrust\r\n\r\nTo easily script some signature check script, PythonForWindows implements some wrapper functions around ``wintrust.dll``\r\n\r\n```python\r\n>>> import windows.wintrust\r\n>>> windows.wintrust.is_signed(r\"C:\\Windows\\system32\\ntdll.dll\")\r\nTrue\r\n>>> windows.wintrust.is_signed(r\"C:\\Windows\\system32\\python27.dll\")\r\nFalse\r\n>>> windows.wintrust.full_signature_information(r\"C:\\Windows\\system32\\ntdll.dll\")\r\nSignatureData(signed=True,\r\n    catalog=u'C:\\\\Windows\\\\system32\\\\CatRoot\\\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\\\\Package_35_for_KB3128650~31bf3856ad364e35~amd64~~6.3.1.2.cat',\r\n    catalogsigned=True, additionalinfo=0L)\r\n>>> windows.wintrust.full_signature_information(r\"C:\\Windows\\system32\\python27.dll\")\r\nSignatureData(signed=False, catalog=None, catalogsigned=False, additionalinfo=TRUST_E_NOSIGNATURE(0x800b0100))\r\n```\r\n\r\n### WMI\r\n\r\nTo extract/play with even more information about the system, PythonForWindows is able to perform WMI request.\r\n\r\n```python\r\n>>> import windows\r\n>>> windows.system.wmi.select\r\n<bound method WmiNamespace.select of <WmiNamespace \"root\\cimv2\">>\r\n>>> windows.system.wmi.select(\"Win32_Process\")[:3]\r\n[<WmiObject instance of \"Win32_Process\">, <WmiObject instance of \"Win32_Process\">, <WmiObject instance of \"Win32_Process\">]# Get WMI data for current process\r\n>>> windows.system.wmi.select(\"Win32_Process\")[42][\"Name\"]\r\nu'svchost.exe'\r\n>>> wmi_cp = [p for p in windows.system.wmi.select(\"Win32_Process\") if int(p[\"Handle\"]) == windows.current_process.pid][0]\r\n>>> wmi_cp[\"CommandLine\"], wmi_cp[\"HandleCount\"]\r\n(u'\"C:\\\\Python27\\\\python.exe\"', 227)\r\n```\r\n\r\n### Registry\r\n\r\nThe project also contains some wrapping classes around `_winreg` for simpler use.\r\n\r\n```python\r\n>>> import windows\r\n>>> from windows.generated_def import KEY_WRITE, KEY_READ, REG_QWORD\r\n>>> registry = windows.system.registry\r\n>>> cuuser_software = registry(r'HKEY_CURRENT_USER\\Software')\r\n>>> cuuser_software\r\n<PyHKey \"HKEY_CURRENT_USER\\Software\">\r\n>>> cuuser_software.sam\r\nKEY_READ(0x20019)\r\n# Explore subkeys\r\n>>> cuuser_software.subkeys[:3]\r\n[<PyHKey \"HKEY_CURRENT_USER\\Software\\7-Zip\">, <PyHKey \"HKEY_CURRENT_USER\\Software\\AppDataLow\">, <PyHKey \"HKEY_CURRENT_USER\\Software\\Audacity\">]\r\n>>> tstkey = registry('HKEY_CURRENT_USER\\TestKey',  KEY_WRITE | KEY_READ)\r\n# Get / Set individual value\r\n>>> tstkey[\"VALUE\"] = 'a_value_for_my_key'\r\n>>> tstkey[\"VALUE\"]\r\nKeyValue(name='VALUE', value=u'a_value_for_my_key', type=1)\r\n>>> tstkey[\"MYQWORD\"] = (123456789987654321, REG_QWORD)  # Default is REG_DWORD for int/long\r\n>>> tstkey[\"MYQWORD\"]\r\nKeyValue(name='MYQWORD', value=123456789987654321L, type=11)\r\n# Explore Values\r\n>>> tstkey.values\r\n[KeyValue(name='MYQWORD', value=123456789987654321L, type=11), KeyValue(name='VALUE', value=u'a_value_for_my_key', type=1)]\r\n```\r\n\r\n### Object manager\r\n\r\nPythonForWindows uses the native Windows NT API to display some information about the object in the Object Manager's name space.\r\nJust like the well-known tools ``winobj.exe``\r\n\r\n```python\r\n>>> windows.system.object_manager.root\r\n<KernelObject \"\\\" (type=\"Directory\")>\r\n# The objects of type \"Directory\" can be acceded just like a dict\r\n>>> list(windows.system.object_manager.root)[:3]\r\n[u'PendingRenameMutex', u'ObjectTypes', u'storqosfltport']\r\n# Find an object by its path\r\n>>> windows.system.object_manager[\"KnownDLLs\\\\kernel32.dll\"]\r\n<KernelObject \"\\KnownDLLs\\kernel32.dll\" (type=\"Section\")>\r\n>>> k32 = windows.system.object_manager[\"KnownDLLs\\\\kernel32.dll\"]\r\n>>> k32.name, k32.fullname, k32.type\r\n('kernel32.dll', '\\\\KnownDLLs\\\\kernel32.dll', u'Section')\r\n# Follow SymbolicLink object\r\n>>> windows.system.object_manager[\"\\\\KnownDLLs\\\\KnownDLLPath\"]\r\n<KernelObject \"\\KnownDLLs\\KnownDLLPath\" (type=\"SymbolicLink\")>\r\n>>> windows.system.object_manager[\"\\\\KnownDLLs\\\\KnownDLLPath\"].target\r\nu'C:\\\\WINDOWS\\\\System32'\r\n```\r\n\r\n### Scheduled Task\r\n\r\nThe ``windows.system.task_scheduler`` object allows to query and create scheduled task.\r\n\r\n**This part is still in developpement and the API may evolve**\r\n\r\n```python\r\n>>> windows.system.task_scheduler\r\n<TaskService at 0x4774670>\r\n>>> windows.system.task_scheduler.root\r\n<TaskFolder \"\\\" at 0x4774710>\r\n>>> task = windows.system.task_scheduler.root.tasks[2]\r\n>>> task\r\n<Task \"DemoTask\" at 0x47748f0>\r\n>>> task.name\r\nu'DemoTask'\r\n# Explore task actions\r\n>>> task.definition.actions[1]\r\n<ExecAction at 0x4774800>\r\n>>> task.definition.actions[1].path\r\nu'c:\\\\windows\\\\python\\\\python.exe'\r\n>>> task.definition.actions[1].arguments\r\nu'yolo.py --test'\r\n```\r\n\r\n### Event logs\r\n\r\nThe ``windows.system.event_log`` object allows to query event logs.\r\n\r\n**This part is still in developpement and the API may evolve**\r\n\r\n```python\r\n>>> windows.system.event_log\r\n<windows.winobject.event_log.EvtlogManager object at 0x04A78270>\r\n# Find a channel by its name\r\n>>> chan = windows.system.event_log[\"Microsoft-Windows-Windows Firewall With Advanced Security/Firewall\"]\r\n>>> chan\r\n<EvtChannel \"Microsoft-Windows-Windows Firewall With Advanced Security/Firewall\">\r\n# Open .evtx files\r\n>>> windows.system.event_log[\"test.evtx\"]\r\n<EvtFile \"test.evtx\">\r\n# Query a channel for all events\r\n>>> chan.query().all()[:2]\r\n[<EvtEvent id=\"2004\" time=\"2018-07-12 07:44:08.081504\">, <EvtEvent id=\"2006\" time=\"2018-07-12 07:57:59.806938\">]\r\n# Query a channel for some ids\r\n>>> chan.query(ids=2004).all()[:2]\r\n[<EvtEvent id=\"2004\" time=\"2018-07-12 07:44:08.081504\">, <EvtEvent id=\"2004\" time=\"2018-07-12 07:57:59.815156\">]\r\n# Query a channel via XPATH\r\n>>> evt = chan.query(\"Event/EventData[Data='Netflix']\").all()[0]\r\n# Explore event information\r\n>>> evt\r\n<EvtEvent id=\"2006\" time=\"2018-07-17 10:32:39.160423\">\r\n>>> evt.data\r\n{u'ModifyingUser': 69828304, u'RuleName': u'Netflix', u'ModifyingApplication': ...}\r\n```\r\n\r\n### ALPC-RPC\r\n\r\n#### ALPC\r\n\r\nClasses around **A**dvanced **L**ocal **P**rocedure **C**all (**ALPC**) syscalls allows to simply\r\nwrite client and server able to send **ALPC** messages.\r\n\r\n```python\r\n>>> import windows.alpc\r\n# Test server juste reply to each message with \"REQUEST '{msg_data}' RECEIVED\"\r\n>>> client = windows.alpc.AlpcClient(r\"\\RPC Control\\PythonForWindowsTESTPORT\")\r\n>>> response = client.send_receive(\"Hello world !\")\r\n>>> response\r\n<windows.alpc.AlpcMessage object at 0x04C0D5D0>\r\n>>> response.data\r\n\"REQUEST 'Hello world !' RECEIVED\"\r\n```\r\n\r\nFull client/server code for this example is available is the [ALPC samples][ONLINE_SAMPLE_ALPC] along with a more complex example.\r\n\r\n\r\n#### RPC\r\n\r\nAn RPC-Client based using **ALPC** communication is also integred\r\n\r\n```python\r\n# Server (port ALPC '\\RPC Control\\HelloRpc') offers:\r\n# Interface '41414141-4242-4343-4444-45464748494a' version 1.0\r\n#   Method 1 -> int Add(int a, int b) -> return a + b\r\n# This Test server is a real RPC Server using rpcrt4.dll and compiled with VS2015.\r\n\r\n>>> import windows.rpc\r\n>>> from windows.rpc import ndr\r\n>>> client = windows.rpc.RPCClient(r\"\\RPC Control\\HelloRpc\")\r\n>>> client\r\n<windows.rpc.client.RPCClient object at 0x0411E130>\r\n>>> iid = client.bind(\"41414141-4242-4343-4444-45464748494a\")\r\n>>> ndr_params = ndr.make_parameters([ndr.NdrLong] * 2)\r\n# NDR pack + Make RPC call to method 1.\r\n>>> resp = client.call(iid, 1, ndr_params.pack([41414141, 1010101]))\r\n# Unpack the NDR response\r\n>>> result = ndr.NdrLong.unpack(ndr.NdrStream(resp))\r\n>>> result\r\n42424242\r\n```\r\n\r\nA sample with the **U**ser **A**ccount **C**ontrol (**UAC**) and one with `lsasrv.dll` are available in the [RPC samples][ONLINE_SAMPLE_RPC].\r\n\r\n\r\n### Debugger\r\n\r\nPythonForWindows provides a standard debugger to debug other processes.\r\n\r\n```python\r\nimport windows\r\nimport windows.debug\r\nimport windows.test\r\nimport windows.native_exec.simple_x86 as x86\r\nimport windows.generated_def as gdef\r\n\r\nfrom windows.test import pop_proc_32\r\n\r\nclass MyDebugger(windows.debug.Debugger):\r\n    def on_exception(self, exception):\r\n        code = exception.ExceptionRecord.ExceptionCode\r\n        addr = exception.ExceptionRecord.ExceptionAddress\r\n        print(\"Got exception {0} at 0x{1:x}\".format(code, addr))\r\n        if code == gdef.EXCEPTION_ACCESS_VIOLATION:\r\n            print(\"Access Violation: kill target process\")\r\n            self.current_process.exit()\r\n\r\ncalc = windows.test.pop_proc_32(dwCreationFlags=gdef.DEBUG_PROCESS)\r\nd = MyDebugger(calc)\r\ncalc.execute(x86.assemble(\"int3; mov [0x42424242], EAX; ret\"))\r\nd.loop()\r\n\r\n## Ouput ##\r\nGot exception EXCEPTION_BREAKPOINT(0x80000003) at 0x77e13c7d\r\nGot exception EXCEPTION_BREAKPOINT(0x80000003) at 0x230000\r\nGot exception EXCEPTION_ACCESS_VIOLATION(0xc0000005) at 0x230001\r\nAccess Violation: kill target process\r\n```\r\n\r\nThe debugger handles\r\n\r\n* Standard breakpoint ``int3``\r\n* Hardware Execution breakpoint ``DrX``\r\n* Memory breakpoint ``virtual protect``\r\n\r\n\r\n#### LocalDebugger\r\n\r\nYou can also debug your own process (or debug a process by injection) via the LocalDebugger.\r\n\r\nThe LocalDebugger is an abstraction around Vectored Exception Handler (VEH)\r\n\r\n```python\r\nimport windows\r\nfrom windows.generated_def.winstructs import *\r\nimport windows.native_exec.simple_x86 as x86\r\n\r\nclass SingleSteppingDebugger(windows.debug.LocalDebugger):\r\n    SINGLE_STEP_COUNT = 4\r\n    def on_exception(self, exc):\r\n        code = self.get_exception_code()\r\n        context = self.get_exception_context()\r\n        print(\"EXCEPTION !!!! Got a {0} at 0x{1:x}\".format(code, context.pc))\r\n        self.SINGLE_STEP_COUNT -= 1\r\n        if self.SINGLE_STEP_COUNT:\r\n            return self.single_step()\r\n        return EXCEPTION_CONTINUE_EXECUTION\r\n\r\nclass RewriteBreakpoint(windows.debug.HXBreakpoint):\r\n    def trigger(self, dbg, exc):\r\n        context = dbg.get_exception_context()\r\n        print(\"GOT AN HXBP at 0x{0:x}\".format(context.pc))\r\n        # Rewrite the infinite loop with 2 nop\r\n        windows.current_process.write_memory(self.addr, \"\\x90\\x90\")\r\n        # Ask for a single stepping\r\n        return dbg.single_step()\r\n\r\n\r\nd = SingleSteppingDebugger()\r\n# Infinite loop + nop + ret\r\ncode = x86.assemble(\"label :begin; jmp :begin; nop; ret\")\r\nfunc = windows.native_exec.create_function(code, [PVOID])\r\nprint(\"Code addr = 0x{0:x}\".format(func.code_addr))\r\n# Create a thread that will infinite loop\r\nt = windows.current_process.create_thread(func.code_addr, 0)\r\n# Add a breakpoint on the infinite loop\r\nd.add_bp(RewriteBreakpoint(func.code_addr))\r\nt.wait()\r\nprint(\"Done!\")\r\n\r\n## Output ##\r\n\r\nCode addr = 0x6a0002\r\nGOT AN HXBP at 0x6a0002\r\nEXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x6a0003\r\nEXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x6a0004\r\nEXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x6a0005\r\nEXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004) at 0x770c7c04\r\nDone!\r\n\r\n```\r\n\r\nThe local debugger handles\r\n\r\n* Standard breakpoint ``int3``\r\n* Hardware Execution breakpoint ``DrX``\r\n\r\n### Symbols\r\n\r\nClasses around the Symbols APIs of `dbghelp.dll` are also implemented and can be used independently of the Debugger.\r\nThe path of `dbghelp.dll` can also be given via the `PFW_DBGHELP_PATH` environment variable.\r\n\r\n\r\n```python\r\n# Python3\r\n\r\n>>> from windows.debug import symbols\r\n>>> # symbols.set_dbghelp_path(MY_DBGHELP_PATH)\r\n>>> symbols.engine.options = 0 # Disable defered load\r\n>>> sh = symbols.VirtualSymbolHandler()\r\n>>> ntmod = sh.load_file(r\"c:\\windows\\system32\\ntdll.dll\", addr=0x420000)\r\n>>> ntmod\r\n<SymbolModule name=\"ntdll\" type=SymPdb pdb=\"ntdll.pdb\" addr=0x420000>\r\n>>> ntmod.name\r\n'ntdll'\r\n>>> ntmod.path\r\n'c:\\\\windows\\\\system32\\\\ntdll.dll'\r\n>>> ntmod.pdb\r\n'c:\\\\Symbols\\\\ntdll.pdb\\\\8D5D5ED5D5B8AA609A82600C14E3004D1\\\\ntdll.pdb'\r\n>>> sym = sh[\"ntdll!LdrLoadDll\"]\r\n>>> sym\r\n<SymbolInfoW name=\"LdrLoadDll\" start=0x44a160 tag=SymTagFunction>\r\n>>> sym.fullname\r\n'ntdll!LdrLoadDll'\r\n>>> hex(sym.addr)\r\n'0x44a160'\r\n>>> sh.search(\"ntdll!*CreateFile\")\r\n[<SymbolInfoW name=\"EtwpCreateFile\" start=0x47d9ec tag=SymTagFunction>, <SymbolInfoW name=\"EtwpCreateFile\" start=0x47d9ec tag=SymTagPublicSymbol>, <SymbolInfoW name=\"NtCreateFile\" start=0x4c03e0 tag=SymTagPublicSymbol>, <SymbolInfoW name=\"ZwCreateFile\" start=0x4c03e0 tag=SymTagPublicSymbol>, <SymbolInfoW name=\"__imp_NtCreateFile\" start=0x55cb70 tag=SymTagPublicSymbol>]\r\n# Some types exploration\r\n>>> peb = sh.get_type(\"ntdll!_PEB\")\r\n>>> peb\r\n<SymbolType name=\"_PEB\" tag=_SymTagEnum.SymTagUDT(0xb)>\r\n>>> peb.size\r\n2000\r\n>>> peb.children[:3]\r\n[<SymbolType name=\"InheritedAddressSpace\" tag=_SymTagEnum.SymTagData(0x7)>, <SymbolType name=\"ReadImageFileExecOptions\" tag=_SymTagEnum.SymTagData(0x7)>, <SymbolType name=\"BeingDebugged\" tag=_SymTagEnum.SymTagData(0x7)>]\r\n>>> peb.children[2].offset\r\n2\r\n```\r\n\r\n### Other stuff (see doc / samples)\r\n\r\n- Network\r\n- COM\r\n\r\n## Acknowledgments\r\n\r\n* clmntb for his initial work on ``windows.security``\r\n\r\n\r\n[LKD_GITHUB]: https://github.com/sogeti-esec-lab/LKD/\r\n[SAMPLE_DIR]: https://github.com/hakril/PythonForWindows/tree/master/samples\r\n[ONLINE_DOC]: https://hakril.github.io/PythonForWindows/\r\n[ONLINE_SAMPLE]: https://hakril.github.io/PythonForWindows/build/html/sample.html\r\n[ONLINE_SAMPLE_ALPC]: https://hakril.github.io/PythonForWindows/build/html/sample.html#windows-alpc\r\n[ONLINE_SAMPLE_RPC]: https://hakril.github.io/PythonForWindows/build/html/sample.html#windows-rpc\r\n[ONLINE_IATHOOK]: https://hakril.github.io/PythonForWindows/build/html/iat_hook.html\r\n",
    "bugtrack_url": null,
    "license": "BSD",
    "summary": "A codebase aimed to make interaction with Windows and native execution easier",
    "version": "1.0.0",
    "project_urls": {
        "Homepage": "https://github.com/hakril/PythonForWindows"
    },
    "split_keywords": [
        "windows",
        "python"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4c7adf1f9508453c32596f2bf462a42f6422e508aad296e9bb240769281d8fa5",
                "md5": "57554b92966f6b64d83bc6aa9de2f1e0",
                "sha256": "06463030d92111426a9f5cae130ff61da40eeaa8a8277b344c6c3e8e6cbeff81"
            },
            "downloads": -1,
            "filename": "PythonForWindows-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "57554b92966f6b64d83bc6aa9de2f1e0",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 679219,
            "upload_time": "2024-06-14T16:55:31",
            "upload_time_iso_8601": "2024-06-14T16:55:31.010206Z",
            "url": "https://files.pythonhosted.org/packages/4c/7a/df1f9508453c32596f2bf462a42f6422e508aad296e9bb240769281d8fa5/PythonForWindows-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-06-14 16:55:31",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "hakril",
    "github_project": "PythonForWindows",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pythonforwindows"
}
        
Elapsed time: 0.26911s