Skip to content

Add loaderlock-settle config option and generic If: conditional action - #147

Open
enzok wants to merge 21 commits into
kevoreilly:capemonfrom
enzok:sleep-test
Open

enzok wants to merge 21 commits into
kevoreilly:capemonfrom
enzok:sleep-test

Conversation

@enzok

@enzok enzok commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

loaderlock-settle: opt-in Sleep(1) yield in LdrGetProcedureAddressForCaller to fix timing race in trojanized sideload DLLs (AxolotlLoader/dui70.dll) where a DllMain bootstrap re-clobbers a dispatch-table slot to -1 mid-resolver.

If::[:]:: generic conditional prefix for ActionDispatcher that tests any operand (Src/Dst/register/[mem]/immediate) against unary (ptr/z/nz) or binary (eq/ne/gt/lt/ge/le) predicates before running any wrapped action.

loaderlock-settle: opt-in Sleep(1) yield in LdrGetProcedureAddressForCaller
to fix timing race in trojanized sideload DLLs (AxolotlLoader/dui70.dll)
where a DllMain bootstrap re-clobbers a dispatch-table slot to -1 mid-resolver.

If:<lhs>:<op>[:<rhs>]:<action>: generic conditional prefix for ActionDispatcher
that tests any operand (Src/Dst/register/[mem]/immediate) against unary (ptr/z/nz)
or binary (eq/ne/gt/lt/ge/le) predicates before running any wrapped action.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

enzok added 20 commits August 11, 2026 13:05
Extend the interactive debugger protocol used by CAPEsolo:

- RD reads one pointer from each address in a comma-separated list in a
  single round trip. Naming indirect calls by their import slot cost one
  MD per slot (~110ms each), too slow to resolve a window's worth of
  calls on every break. Unreadable addresses are omitted from the reply,
  so the caller learns which failed by their absence.
- CS walks the call stack from the break context, reporting per frame the
  return address, frame pointer and the bytes preceding the return
  address, so the frontend can decode the originating CALL without a
  round trip per frame. x64 unwinds via RtlLookupFunctionEntry/
  RtlVirtualUnwind and falls back to popping a return address off the
  stack for frames with no unwind data; x86 follows the EBP chain.
- TI snapshots another thread's registers, stack window and call stack
  from a single suspension, so all three views describe the same instant.
- Tag requests as "<id>:<purpose>|" on IP, MD and RD payloads and echo the
  tag back, so responses are correlated by tag rather than by reply
  length, which cannot tell a 4-byte pointer read from a 4-byte dump.
- SB accepts optional type and size fields for write and read/write data
  watchpoints; LB decodes R/W and LEN out of DR7 to report each
  breakpoint's type and width, and now requires a DR7 enable bit as well
  as a non-zero address so cleared slots and stale addresses are not
  reported as phantom breakpoints.

Also fix InteractiveDebuggerPipe clearing DebuggerCommand before
formatting its output: callers pass pointers into that buffer as varargs
(the request tag, echoed payloads), so every tagged reply came back with
an empty tag and CAPEsolo discarded it as unsolicited. The buffer is now
cleared after formatting, immediately before the pipe call.
HandlePageMap sent the whole map in one reply, silently truncating a
fragmented process's tail - which CAPEsolo cannot distinguish from freed
regions when diffing maps. Serve 1024 regions per request with a MORE/END
terminator, and drop the now-dead MBIEntryArray helpers.

Dr6 is sticky, so leaving it set on the resume paths made the lowest bit
ever set win the breakpoint scan for the thread's life. Zero it wherever
we continue execution.
…int handling; refactor memory map handling in Solo.c for better stability and performance
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.

1 participant