Cross-platform Dynamic Library Injection Toolkit
injx is a cross-platform toolkit for injecting dynamic libraries into running processes. It supports Windows DLLs, macOS dylibs, and Linux shared objects (.so files).
Available as:
- 🖥️ CLI Tool - Command-line interface for quick injection
- 📦 Library - Rust and Go APIs for integration into your projects
- 🦀 Rust Implementation - Safe, fast, zero-dependency core
- 🐹 Go Implementation - Pure Go with Windows support
- 🖥️ Cross-Platform - Windows, macOS, and Linux support
- 📦 Dual Interface - CLI tool and library API
- 🔍 Process Discovery - Find processes by name or PID
- 💉 Inject/Eject - Load and unload libraries at runtime
- ✅ Status Check - Verify if a library is already injected
| Platform | Architecture | Rust | Go | Technique |
|---|---|---|---|---|
| Windows | x86 | ✅ | ✅ | CreateRemoteThread + LoadLibrary |
| Windows | x64 | ✅ | ✅ | CreateRemoteThread + LoadLibrary |
| macOS | ARM64 | ✅ | 🚧 | task_for_pid + thread_create_running |
| macOS | x64 | ✅ | 🚧 | task_for_pid + thread_create_running |
| Linux | x64 | ✅ | 🚧 | ptrace + dlopen |
| Linux | ARM64 | ✅ | 🚧 | ptrace + dlopen |
Legend: ✅ Full support | 🚧 In development
# Clone the repository
git clone https://github.com/user/injx.git
cd injx
# Build everything
make build
# Or build individually
make build-rust # Rust CLI and library
make build-go # Go CLI (Windows)# Install CLI
cargo install --path rust
# Or add as dependency
# Cargo.toml:
# [dependencies]
# injx = { git = "https://github.com/user/injx" }go get go.zoe.im/injx# Basic injection
injx <PROCESS_NAME|PID> <LIBRARY>...
# Windows - Inject DLL into Notepad
injx notepad.exe payload.dll
# macOS - Inject dylib (requires root)
sudo injx Safari payload.dylib
# Linux - Inject .so (requires CAP_SYS_PTRACE or root)
sudo injx firefox payload.so
# Inject multiple libraries
injx 1234 lib1.dll lib2.dll lib3.dll
# Inject by PID
injx 12345 ./myhook.dlluse injx::{Process, Injector};
fn main() -> injx::Result<()> {
// Find process by name
let process = Process::find_by_name("target.exe")
.ok_or("Process not found")?;
println!("Found: {} (PID: {})", process.name(), process.pid());
// Check if already injected
if process.is_injected("payload.dll")? {
println!("Already injected!");
return Ok(());
}
// Inject library
process.inject("./payload.dll")?;
println!("Injection successful!");
// Eject library (Windows only currently)
process.eject("payload.dll")?;
Ok(())
}package main
import (
"fmt"
"log"
"go.zoe.im/injgo"
)
func main() {
// Find process by name
proc, err := injgo.FindProcessByName("target.exe")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found: %s (PID: %d)\n", proc.Name, proc.PID)
// Check if already injected
injected, _ := proc.IsInjected("payload.dll")
if injected {
fmt.Println("Already injected!")
return
}
// Inject library
err = proc.Inject("./payload.dll")
if err != nil {
log.Fatal(err)
}
fmt.Println("Injection successful!")
}// Find process by name (returns first match)
Process::find_by_name(name: &str) -> Option<Process>
// Find all processes matching name
Process::find_all_by_name(name: &str) -> Vec<Process>
// Open process by PID
Process::from_pid(pid: u32) -> Option<Process>
// Get process info
process.pid() -> u32
process.name() -> &str// Check if library is loaded
process.is_injected(lib: &str) -> Result<bool>
// Inject library
process.inject(lib: &str) -> Result<()>
// Eject library
process.eject(lib: &str) -> Result<()>// Find process by name
injgo.FindProcessByName(name string) (*Process, error)
// Find process by PID
injgo.FindProcessByPID(pid int) (*Process, error)
// Process methods
proc.IsInjected(lib string) (bool, error)
proc.Inject(lib string) error
proc.Eject(lib string) error
// Convenience functions
injgo.InjectByPID(pid int, lib string, replace bool) error
injgo.InjectByProcessName(name, lib string, replace bool) errorThe examples/ directory contains ready-to-use payload examples:
| Example | Platform | Description |
|---|---|---|
messagebox.rs |
Windows | Shows a MessageBox when injected |
procinfo.rs |
Windows | Collects and saves process info |
keylogger_demo.rs |
Windows | Keyboard hook demo (educational) |
hello_dylib.rs |
macOS | Simple dylib with constructor |
hook_demo.rs |
macOS | Function hooking example |
hello_so.rs |
Linux | Simple .so with constructor |
# Windows MessageBox DLL
cargo build --example messagebox --target x86_64-pc-windows-msvc --release
# macOS dylib
cargo build --example hello_dylib --release
# Linux .so
cargo build --example hello_so --releaseSee examples/payloads/ for C templates:
template_dll.c- Windows DLLtemplate_dylib.c- macOS dylibtemplate_so.c- Linux .so
- Open target process with
PROCESS_ALL_ACCESS - Allocate memory in target for DLL path (
VirtualAllocEx) - Write DLL path to allocated memory (
WriteProcessMemory) - Get
LoadLibraryWaddress from kernel32.dll - Create remote thread calling
LoadLibraryW(CreateRemoteThread) - Wait for thread completion
- Get task port via
task_for_pid(requires root) - Allocate memory in target (
mach_vm_allocate) - Write dylib path and set up registers
- Create thread via
thread_create_runningcallingdlopen
- Attach to target via
PTRACE_ATTACH - Save original registers
- Find
dlopenaddress in target's libc - Write library path to process memory
- Set up registers for dlopen call
- Continue execution, restore registers
- Detach from process
- Rust: 1.70+ with platform-specific targets
- Go: 1.21+
| Platform | Requirements |
|---|---|
| Windows | Same architecture as target (x86→x86, x64→x64) |
| macOS | Root privileges or taskgated entitlement |
| Linux | CAP_SYS_PTRACE capability or root |
# Format code
make fmt
# Run lints
make lint
# Run tests
make test
# Clean build artifacts
make clean- Only use on processes you own or have explicit permission to test
- Be aware of legal implications in your jurisdiction
- Some antivirus software may flag injection tools
injx/
├── rust/ # Rust implementation
│ ├── src/
│ │ ├── lib.rs # Library entry point
│ │ ├── main.rs # CLI entry point
│ │ ├── error.rs # Error types
│ │ ├── inject.rs # Injector trait
│ │ ├── process_*.rs # Platform process handling
│ │ └── inject_*.rs # Platform injection logic
│ └── Cargo.toml
├── go/ # Go implementation
│ ├── inject.go # Core types and interface
│ ├── inject_windows.go # Windows implementation
│ ├── inject_darwin.go # macOS implementation
│ ├── inject_linux.go # Linux implementation
│ └── cmd/injgo/ # CLI entry point
├── examples/ # Example payloads
│ ├── windows/
│ ├── macos/
│ ├── linux/
│ └── payloads/ # C templates
├── Makefile
└── README.md