obscene-injector - Native PS5 Process Injector
A freestanding ELF payload that consumes session kernel R/W to hijack
a target process, map obSCEne segments, and execute the
conformance probe natively.
1. Why the Injector Exists
As recorded in D276, standard payload execution
(make payload loaded via elfldr) runs in the
PS4 backward-compatibility sandbox
(payload/ps4-bc). In that environment:
- Current-generation GPU APIs (
libSceAgc) cannot be mapped or linked. - Dynamic introspection (
sceKernelGetModuleInfo,sceKernelDlsym) is refused with0x80020016/0x80020003. - The runtime linker debug table (
DT_DEBUG) is absent.
To measure real, native Prospero platform behavior
(payload/ps5-native), obSCEne must run inside
a native-category process (such as a launched retail title or system
helper). obscene-injector bridges this gap.
2. Decoupled Architecture
The probe and injector are strictly decoupled:
- The probe never links the injector.
src/probe/sections/andsrc/probe/runtime.cremain clean conformance probe code. - The injector never links the probe checks. The
injector is self-contained in
src/probe/injector_entry.c. - Shared freestanding layer. Built into
src/probe/injector_entry.cwith zero external dependencies. obscene/ src/probe/injector_entry.c ← Consolidated injector payload link/injector.ld ← ET_DYN payload linker script (16 KiB page aligned) docs/INJECTOR.md ← This specification
---
## 3. Kernel R/W Interface (`krw.h` / `krw.c`)
The injector receives `payload_args_t` from the session exploit chain (`kstuff-lite` / `elfldr`):
typedef struct payload_args {
int (*sys_dynlib_dlsym)(int, const char *, void *);
int *rwpipe;
int *rwpair;
long kpipe_addr;
long kdata_base_addr;
int *payloadout;
} payload_args_t;
Primitive Mechanics
- Kernel Write: Sets IPv6 socket packet options
(
setsockopt(IPV6_PKTINFO)) onrwpairto construct arbitrary kernel writes viakpipe_addr. - Kernel Read / Copyout: Uses the modified pipe
buffer flags to read kernel memory through
sys_read(rwpipe[0]). - Credential Escalation:
krw_elevate_current_process()setsauthid = 0x4800000000010003and enables full capability bits (caps[16] = 0xff), granting unrestrictedptraceaccess and unblocking protected syscalls.
4. Execution & Injection Flow: What Happens Under the Hood
When ./bin/obscene inject is executed, the entire
process is automated in a single round-trip:
sequenceDiagram
participant CLI as ./bin/obscene inject
participant Tool as obscene-tool (Prosperous)
participant Loader as elfldr (:9021 on PS5)
participant Injector as obscene-injector.elf
participant Title as Native PS5 Title (Foreground)
CLI->>CLI: 1. Builds obscene-payload.elf
CLI->>CLI: 2. Embeds payload into obscene-injector.elf
CLI->>Tool: 3. Invoke hw send + hw logs in parallel
Tool->>Loader: 4. Transmit injector via prosperous (TCP :9021)
Loader->>Injector: 5. Execute injector with session kernel R/W
Injector->>Injector: 6. Elevate ucred (authid = 0x4800000000010003)
Injector->>Title: 7. ptrace attach to foreground title
Injector->>Title: 8. Map embedded probe segments & apply relocations
Injector->>Title: 9. Set RIP = obscene_start and ptrace detach
Title->>CLI: 10. obSCEne runs in ps5_mode and streams report (socket + klog)
Detailed Pipeline Breakdown:
Self-Contained Bundle Build:
make payloadproducesbuild/obscene-payload.elf(the full conformance probe).make injectorlinkssrc/injector/blob.Sto embed the probe ELF directly into the.rodatasection ofbuild/obscene-injector.elf(with runtime disk fallback to/data/if needed).
Network Delivery via Prosperous:
- Relays to
obscene-tool hw send build/obscene-injector.elf. - The tooling calls Prosperous
(
pros_link) to stream the self-contained injector over TCP port 9021 toelfldron the PS5. scripts/payload-run.shconcurrently initiates background log capture (obscene-tool hw logs).
- Relays to
Kernel Privilege Elevation:
elfldrexecutesobscene-injector.elfwith the active session'spayload_args_t.krw_init()initializes the IPv6 socket-pair and pipe buffer primitives.krw_elevate_current_process()patches the injector processucred: setsauthid = 0x4800000000010003and enables all capability bits, allowing unrestrictedptracesystem calls.
Target Attachment & ELF Loading:
target_resolve()traverses the kernelallprocchain to locate the PID of the foreground native title (e.g.eboot.bin).procctl_attach(target_pid)halts the title.loader_load_into_proc()allocates virtual memory via remotemmap, copiesPT_LOADsegments, appliesR_X86_64_RELATIVErelocations, and enforces segment page permissions (PROT_READ,PROT_WRITE,PROT_EXEC) with 16 KiB page alignment.
Thread Hijacking & Native Execution (
payload/ps5-native):- The injector pushes the original
RIPonto the target stack as a return address, setsRIPtoobscene_start, and passes remotepayload_args_tviaRDI. - The injector restores its own credentials, detaches via
ptrace, and allows the native title to resume. - The probe runs natively inside the retail/native game process with full Prospero subsystem access.
- The injector pushes the original
Dual-Channel Capture:
scripts/payload-run.shcollects the emitted records from both the incoming TCP return socket ($into) and the system log ($klog), outputting a unified report summary to the terminal.
5. Building the Injector
# Build the injector payload
make injector HARDWARE=1
# Build both payload and injector
make payload injector HARDWARE=1Outputs:
build/obscene-payload.elf(the conformance probe)build/obscene-injector.elf(the process injector)
6. How to
Use: Getting into Native PS5 Mode (ps5_mode)
To evaluate native Prospero platform behavior (such as
libSceAgc, native graphics drivers, and unrestricted
introspection APIs), follow this runbook:
Step 1: Pre-flight Checklist
- Jailbroken Console: A PS5 running compatible
firmware (1.00 - 13.00) with kernel exploit and
kstuff-liteactive. - Payload Server: Payload receiver listening on port
9021 (standard
elfldr/pldmgrsetup). - Network Configuration: Host machine connected to
the target over LAN, with the target registered by name. Registrations
live in
hardware.txtunder the tool's own data root -obscene-tool hwresolves--namethrough it (tool/src/hardware.rs). There is nodata/hardware/console.toml; nothing reads one.
Step 2: Launch a Native PS5 Title
- On the console dashboard, launch any native PS5 game or native application (disc or digital title).
- Keep the title running in the foreground (it will provide the native Prospero process context).
Step 3: Run the
Injection via ./bin/obscene
From your development workstation, run:
# Build both artifacts, inject into the running title, and capture the report
./bin/obscene injectUseful Flags:
--seconds N: Duration of log capture window (default90seconds).--into FILE: Where to store the captured records (defaultreports/hardware/injector-klog.txt).--build-only: Compile artifacts without sending over the network.--name NAME: Target a specific console if multiple are registered.
Alternatively, if sending payloads manually:
# 1. Build artifacts
make payload injector HARDWARE=1
# 2. Stage probe ELF on console (if not embedded)
# Stored at /data/obscene.elf or /data/payload.elf via FTP/shsrv
# 3. Send injector to elfldr (port 9021)
obscene-tool hw send build/obscene-injector.elf --seconds 90Step 4: What the Injector Does
- Initializes Kernel R/W: Consumes the session's socket-pair and pipe buffer primitive.
- Elevates Privileges: Grants full root capabilities
and
authid = 0x4800000000010003to allow unrestrictedptracecontrol. - Discovers Foreground Title: Walks the kernel
allproctable to find the running native game's PID. - Maps Probe Segments: Attaches to the title,
allocates virtual address space via remote
mmap, copiesPT_LOADsegments, and applies relocations. - Hijacks Thread & Executes: Updates target
registers (
rip-> entry point,rdi-> runtime args) and detaches.
Step 5: Verifying Native PS5 Execution
Inspect the resulting report header:
OBS|build|payload|...
OBS|context|payload/ps5-native
payload/ps4-bc: Indicates standard un-injected payload running in the PS4 compatibility sandbox.payload/ps5-native: Confirms successful injection and execution within a native Prospero process!
In payload/ps5-native mode:
libSceAgc/libSceAgcDriverAPIs load withoutABIVERSION mismatch.- Introspection functions and native system libraries execute with native category permissions.