Skip to content

Follow every thread: catch exploits that fire from worker threads#2

Merged
grloper merged 1 commit into
mainfrom
claude/repo-improvements-80226a
Jul 12, 2026
Merged

Follow every thread: catch exploits that fire from worker threads#2
grloper merged 1 commit into
mainfrom
claude/repo-improvements-80226a

Conversation

@grloper

@grloper grloper commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Wraith previously traced only the main thread — it waited on a single pid
and never set PTRACE_O_TRACECLONE — so any syscall issued from a thread the
target spawned was invisible. For a sensor aimed at network daemons, request
handlers, and fuzz harnesses (almost always multithreaded), that was the
biggest real blind spot and the stated next milestone.

The tracer now follows every clone/fork/vfork and reaps the whole tree with
waitpid(-1). Each thread keeps its own syscall entry/exit phase, while threads
that share an address space (same thread-group id) share one cached memory map
and one exploitation-chain accumulator — so a payload staged on one thread and
fired from another is still correlated into a single verdict, and distinct
processes keep distinct state. New tracees are registered lazily on their first
stop, which sidesteps the parent/child wait-ordering race.

  • detect.rs: chain state is now per-process (keyed by tgid) instead of a single
    accumulator, so cross-thread staging correlates and separate processes don't
    bleed evidence together.
  • tracer.rs: PTRACE_O_TRACECLONE/FORK/VFORK, waitpid(-1) reap loop, per-thread
    state, per-address-space map cache with cross-thread dirtying.
  • New targets: benign-threads (multithreaded false-positive control) and
    mt-shellcode-sim (payload detonated from a worker thread).
  • Two end-to-end tests cover both; the e2e suite serializes through a lock
    since two ptrace engines can't share one process.
  • README, demo.sh, and roadmap updated to reflect thread-following.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01WS9djsh9BpTKXGgYBJET5u

Wraith previously traced only the main thread — it waited on a single pid
and never set PTRACE_O_TRACECLONE — so any syscall issued from a thread the
target spawned was invisible. For a sensor aimed at network daemons, request
handlers, and fuzz harnesses (almost always multithreaded), that was the
biggest real blind spot and the stated next milestone.

The tracer now follows every clone/fork/vfork and reaps the whole tree with
waitpid(-1). Each thread keeps its own syscall entry/exit phase, while threads
that share an address space (same thread-group id) share one cached memory map
and one exploitation-chain accumulator — so a payload staged on one thread and
fired from another is still correlated into a single verdict, and distinct
processes keep distinct state. New tracees are registered lazily on their first
stop, which sidesteps the parent/child wait-ordering race.

- detect.rs: chain state is now per-process (keyed by tgid) instead of a single
  accumulator, so cross-thread staging correlates and separate processes don't
  bleed evidence together.
- tracer.rs: PTRACE_O_TRACECLONE/FORK/VFORK, waitpid(-1) reap loop, per-thread
  state, per-address-space map cache with cross-thread dirtying.
- New targets: benign-threads (multithreaded false-positive control) and
  mt-shellcode-sim (payload detonated from a worker thread).
- Two end-to-end tests cover both; the e2e suite serializes through a lock
  since two ptrace engines can't share one process.
- README, demo.sh, and roadmap updated to reflect thread-following.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WS9djsh9BpTKXGgYBJET5u
@grloper
grloper merged commit b2311d5 into main Jul 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants