Skip to main content

A Python library for memory manipulation, code injection and function hooking

Project description

PyJectify logo

PyJectify

A Python library for memory manipulation, code injection and function hooking.

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

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 (Python 3.10 - 3.11 supported)

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 Inject module to use direct syscalls
  • ApiSetSchema: parse Windows ApiSet

Example

Memory manipulation

import pyjectify

# Open notepad process (only the first found if multiple instances of notepad are running)
notepad = pyjectify.byName('Notepad.exe')[0]

# Search for the secret in notepad's memory
# We 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)
addrs = notepad.memscan.scan(pattern)
for addr in addrs:
    secret = notepad.process.read(addr, 50)
    secret = secret.split(b'\x00\x00')[0].replace(b'\x00', b'')
    print('[+] Found secret:', str(secret))
    notepad.process.write(addr, b'*\x00'*len(secret)) # let's hide the secret!

# Reset memscan to perform a new search regardless of the previous scan
notepad.memscan.reset()

Python code injection

import pyjectify

# Open notepad process
notepad = pyjectify.byName('Notepad.exe')[0]

# Inject Python DLL
notepad.pythonlib.python_mod = notepad.inject.load_library("C:\\path\\to\\python-embed\\python311.dll")
notepad.pythonlib.python_mod.parse_exports()

# 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.byName('Notepad.exe')[0]
notepad.pythonlib.python_mod = notepad.inject.load_library("C:\\path\\to\\python-embed\\python311.dll")
notepad.pythonlib.python_mod.parse_exports()

# 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')
user32.parse_exports()
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.byName('proc1.exe')[0]
proc2 = pyjectify.byName('proc2.exe')[0]

# Extract a library from proc1's memory
module = proc1.process.get_module('module.dll')[0]

# Extract common syscalls from ntdll.dll and wrap them in 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, without copying PE headers
proc2.inject.memory_loader(module, copy_headers=False)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyjectify-0.2.tar.gz (21.8 kB view details)

Uploaded Source

Built Distribution

pyjectify-0.2-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

File details

Details for the file pyjectify-0.2.tar.gz.

File metadata

  • Download URL: pyjectify-0.2.tar.gz
  • Upload date:
  • Size: 21.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.6

File hashes

Hashes for pyjectify-0.2.tar.gz
Algorithm Hash digest
SHA256 bcd20c82cb70b053343399be6786d62c7f4c6f1d9725026dc369c2357d245a03
MD5 8ffedf05f950b7d61a26d438560447a4
BLAKE2b-256 475a4a70e61728926cf2a9a380535df930a0c0220305e3465dc7991f391a3873

See more details on using hashes here.

File details

Details for the file pyjectify-0.2-py3-none-any.whl.

File metadata

  • Download URL: pyjectify-0.2-py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.6

File hashes

Hashes for pyjectify-0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 16ec3e19d869e315fb514033e32556842e3e46ac27f64d27626e7a2053bf63b9
MD5 038841bb60519fdacb93b0c407d22488
BLAKE2b-256 2c45bbbfa2170f1c83164272d27349dfd119218836e1dcd2b8afab93016515dc

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page