PyJectify
Quick start
PyJectify is available on PyPI.
Alternatively, you can download releases from GitHub or clone the project.
Documentation is available at https://petitoto.github.io/pyjectify/
Features
Windows (x86 & x86_64)
Core
- Allocate / Free / Read / Write memory
- Create threads
- List loaded modules
- PE parser
- Use kernel32 or ntdll functions
Modules
- MemScan: scan memory using regex patterns
- Inject: load library, from disk (remote LoadLibrary) or from memory (fully map the DLL into the remote process)
- Hook: set up inline hooks in the target process
- PythonLib: embed python into a remote process
Utils
- Syscall: parse syscall codes from ntdll.dll (from the loaded library or from the disk), and produce a ntdll-like object which can be used by the core to use direct syscalls
- ApiSetSchema: parse Windows ApiSet
Examples
Memory search & basic operations
import pyjectify
# Open notepad process (only the first found if multiple instances of notepad are running)
notepad = pyjectify.open('notepad.exe')[0]
# Use the pattern "secret( is)?: (.){10}", but encoded in utf-16-le because Notepad uses wchar_t
words = ['secret', ' is', ': ', '.']
pattern = b'%b(%b)?%b(%b){10}' % tuple(e.encode('utf-16-le') for e in words)
# Search for the secret in notepad's memory
addrs = notepad.memscan.scan(pattern)
# Process found addresses
for addr in addrs:
secret = notepad.process.read(addr, 50).decode('utf-16-le')
print('[+] Found secret:', secret)
notepad.process.write(addr, ('*'*len(secret)).encode('utf-16-le')) # let's hide the secret!
# Reset memscan to discard found addresses and perform a new search
notepad.memscan.reset()
Python code injection
import pyjectify
# Open notepad process
notepad = pyjectify.open('notepad.exe')[0]
# Inject Python DLL
notepad.pythonlib.python_mod = notepad.inject.load_library("C:\\path\\to\\python-embed\\python311.dll")
# Run some Python code from notepad
notepad.pythonlib.initialize()
notepad.pythonlib.exec('import os; os.system("calc.exe")')
# Undo all initializations
notepad.pythonlib.finalize()
Setup an inline hook written in Python
import pyjectify
# Open notepad process & inject Python DLL
notepad = pyjectify.open('notepad.exe')[0]
notepad.pythonlib.python_mod = notepad.inject.load_library("C:\\path\\to\\python-embed\\python311.dll")
notepad.pythonlib.initialize()
# Let's hook GetClipboardData!
# Step 1: define our new function
pycode = """
import ctypes
def GetClipboardData(uFormat:ctypes.c_uint) -> ctypes.c_void_p:
ctypes.windll.user32.MessageBoxW(0, "I hooked you :D", "MyNewGetClipboardData", 0)
return o_GetClipboardData(uFormat)
"""
notepad.pythonlib.exec(pycode)
# Step 2: get original function address and setup a trampoline (of 15 bytes size)
user32 = notepad.process.get_module('user32.dll')
oaddr = user32.exports['GetClipboardData'] + user32.base_addr
trampoline_addr = notepad.hook.trampoline(oaddr, 15)
# Step 3: prepare Python function hooking, ie create o_GetClipboardData and get ou Python GetClipboardData address
hook_addr = notepad.pythonlib.prepare_hook('GetClipboardData', trampoline_addr)
# Step 4: inline hook
notepad.hook.inline(oaddr, hook_addr)
Advanced DLL injection
import pyjectify
# Open processes
proc1 = pyjectify.open('proc1.exe')[0]
proc2 = pyjectify.open('proc2.exe')[0]
# Extract a library from proc1's memory
module = proc1.process.get_module('module.dll')
# Extract common syscalls from ntdll.dll and wrap them into a ntdll-like object
syscall = pyjectify.windows.Syscall()
syscall.get_common(from_disk=True)
# Use direct syscalls to operate on proc2 (memory read / write / protect, thread creation...)
proc2.process.ntdll = syscall
# Inject the module directly from memory into proc2, at a random location, without PE headers, and do not call DLL entry point
injected_mod = proc2.inject.memory_loader(module, prefer_base_addr=False, copy_headers=False, call_entry_point=False)
# Run a function from the injected module
proc2.process.start_thread(injected_mod.base_addr + injected_mod.exports['SomeExportedFunction'])
Metadata
Release files for pyjectify 1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyjectify-1.0.tar.gz | 24.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyjectify-1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.5 kB
Release files / pyjectify-1.0.tar.gz
| Download URL | pyjectify-1.0.tar.gz |
|---|---|
| Size | 24.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a21a0416b48061bdf375e58f0bb6191cac4ea0c5140decf589bc50861faedb5f
|
|
BLAKE2b-256 checksum How to use checksums |
aa9df332f8ec5724460c1b6de8ae7064ff2d95b7234d48dc56ce0fbfbaef8141
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 27, 2025.
Transparency logRelease files / pyjectify-1.0-py3-none-any.whl
| Download URL | pyjectify-1.0-py3-none-any.whl |
|---|---|
| Size | 27.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7ff38c2284b8740e5af8bf45408ef3ddfeff0b953b811785fd4f7630119475a2
|
|
BLAKE2b-256 checksum How to use checksums |
4fb9e921bb9f5d2f3bdf5c9e80c9b864272ab33c269715f2e3c3fdd0c6cb8da7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 27, 2025.
Transparency log