docs(evolution): proposal 0007 — inject into iOS Simulator processes - #105
Closed
Mx-Iris wants to merge 1 commit into
Closed
docs(evolution): proposal 0007 — inject into iOS Simulator processes#105Mx-Iris wants to merge 1 commit into
Mx-Iris wants to merge 1 commit into
Conversation
Injecting into a simulator process currently crashes the target. The injector resolves `pthread_create_from_mach_thread`, `dlopen` and `sandbox_extension_consume` against its own address space via `dlsym(RTLD_DEFAULT, ...)`, then hands those absolute addresses to the target. That holds only while injector and target share a dyld shared cache. A simulator process runs its own cache — mapped at the same 0x180000000 base but laid out differently — so the address lands on unrelated code. Three SpringBoard crashes pin this down at register level: `lr` sits exactly 4 bytes past the host's `pthread_create_from_mach_thread`, and `x0`/`x1`/`x2` match what `loader_arm64.s` sets up for that call. The `task_for_pid` failure the user saw is a second-order effect — the target was already dead. Feasibility is verified: an `iphonesimulator` payload dlopen'd into `gamecontrollerd` loads, starts its Swift runtime, advertises over Bonjour and gets a connection back from the host. Bonjour needs no changes — the payload already takes that branch at compile time on non-macOS platforms. One blocker surfaced during verification: the iOS Bonjour identity is device-level (service name and identifier both derive from the device), a leftover from "one app per device". With multiple injected processes the host skips every endpoint after the first as a duplicate, so only one ever connects. Resolved by giving devices a Section and processes the entries under it, reusing the grouping `rebuildSections()` already performs for Mac. Status: Accepted.
Member
Author
|
Superseded by #106: the proposal number collided (0007 is already taken on two unmerged branches) and the branch is renamed to |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds evolution proposal 0007. Documentation only — no code changes.
Why
Injecting into a simulator process crashes the target.
MIMachInjector.mresolves
pthread_create_from_mach_thread,dlopenandsandbox_extension_consumethroughdlsym(RTLD_DEFAULT, ...)— that is, againstthe injector's address space — and then hands those absolute addresses to the
target. The assumption holds only while both processes share a dyld shared
cache. A simulator process runs its own, mapped at the same
0x180000000basebut laid out differently, so the address resolves to unrelated code.
Register-level evidence from three SpringBoard crash reports:
lris exactlyhost pthread_create_from_mach_thread + 4in all three, andx0 = sp+8,x1 = 0,x2 = page-aligned + 0x50match whatloader_arm64.ssets up for thatcall. The
task_for_pid(...): (os/kern) failureseen in the UI is second-order —by then the target was already dead.
What was verified
An
iphonesimulatorpayloaddlopen'd intogamecontrollerd(a daemon, notSpringBoard):
dlerror()is NULL, four segments mappedfrom both sides)
Bonjour needs no new transport: the payload picks that branch at compile time on
non-macOS platforms, and that path already treats simulators as a first-class
case (
rv-simTXT key).Blocker found during verification
The iOS Bonjour identity is device-level — both the service name and the
identifier derive from the device, a leftover from "one app per device". The
host's
connectToBonjourEndpointde-duplicates on the service name, so withseveral injected processes only the first ever connects; the rest sit in
pendingReconnectEndpoints(also keyed by name, so they overwrite each other).Measured:
gamecontrollerdESTABLISHED,nanoappregistrydstuck at LISTEN.Resolved by giving devices a Section and processes the entries beneath it,
reusing the grouping
rebuildSections()already does for Mac. No new displaystructure.
Status
Accepted. Step 1 (feasibility) is done; the proposal records what remains,starting with the identity rework, which is confined to this repo and can be
verified on its own.