stealth: m0.5 borrow system app store session#1
Merged
Conversation
add the empty shells for system-session borrowing:
* SystemSessionImporter protocol + SystemSessionError enum
* CompositeImporter chain (first success wins, all-fail aggregates)
* Account / HTTPCookieBox domain models with redacting debugDescription
* Util/Unimplemented placeholder for the importer impls landing next
no business logic here; project.yml extended so xcodegen picks up
EvilStore/{Core,Domain,Util}.
path B reads /var/mobile/Library/com.apple.itunesstored/ off-disk: * BinaryCookiesParser: pure-byte v0x100 reader (apple format) * FileSystemImporter: accountInfo plist + accountTokens (best effort) + Cookies/com.apple.itunesstored.binarycookies via the parser * multi-key fallback for accountInfo schema drift across ios versions * storefront head extraction "143441-19,29" -> "143441" matching the authenticator response shape needs no entitlements beyond the m0 minimal set. unit test exercises the parser against a hand-built 236-byte fixture with two cookies. tests run on real device under m0.5 task 6 — simulator path is intentionally not trusted (see 2-doc §8).
path A walks ACAccountStore for both com.apple.account.AppleAccount and com.apple.account.iTunesStore. private property names (DSID, AltDSID, storefront, oauthToken) are reached via valueForKey: with @Try blocks because the keys drift across ios majors. on success the importer maps to Account; on failure the objc bridge stashes a human-readable reason that AccountsdImporter classifies into notLoggedIn vs entitlementDenied. bridging header lands at EvilStore/EvilStore-Bridging-Header.h and is wired through SWIFT_OBJC_BRIDGING_HEADER in project.yml. entitlements gain com.apple.accounts.appleaccount.fullaccess and com.apple.private.accounts.bundleidspoofing for the PoC. these will be trimmed to a verified-minimum once the m0.5 diagnostics matrix shows which ones are actually needed per ios version.
path C: SecItemCopyMatching against access group com.apple.itunesstored for DSID, passwordToken, Storefront, GUID. multi-key fallback handles the same property-name drift seen on paths A and B. isAvailable() probes with kSecMatchLimitOne so it cheaply distinguishes "no entitlement" (errSecMissingEntitlement -34018, common on ios 16+) from "entitlement granted, just empty". entitlements gain: * keychain-access-groups = ["*"] * com.apple.private.keychain.allowed-application-groups = [com.apple.itunesstored] * com.apple.private.keychain.unrestricted if real-device m0.5 testing shows path C is denied across the board, docs/4 §3.5 says we may drop the entitlements again rather than carry ones we can't use.
debug-only Settings entry runs all SystemSessionImporter strategies in order, renders a redacted markdown report with tail-4 secret masking, and hands the markdown to UIActivityViewController for AirDrop. * SettingsView placeholder takes over the 4th tab * StealthDiagnosticsView under #if DEBUG; release builds drop it entirely * Util/Logger.swift adds redactTail + Log.info field-scrubbing helpers (single source of truth — Account.debugDescription now uses Util's redactTail) verified Debug + Release archive both pass and the final tipa carries every m0.5 entitlement (path A + path C ents) plus the m0 baseline. next step: airdrop the .tipa to ios 14/15/16/17 devices, run the diagnostics, write the redacted reports into docs/m05_diagnostics/.
three CI failures observed: 1. swiftformat 0.55+ rejects `--lint EvilStore EvilStoreTests` because --lint is now a pure boolean flag. moved the flag after the paths. 2. xcodegen 2.45 emits objectVersion=77 (xcode 17 format). the runners were pinned to Xcode_15.4.app which can't open it. switch both workflows to macos-15 + default xcode (ships 17.x). 3. swiftformat picked up real issues across the m0.5 sources (hoistTry, spaceAroundOperators, trailingCommas, etc). applied auto-format to bring 17 files to spec. also added `--ifdef no-indent` to .swiftformat so `#if DEBUG` blocks at file scope stay un-indented and greppable. verified locally: lint ok, debug+release archive both green.
design and planning docs (architecture, build layout, ui wireframes, m0.5 stealth poc plan, m0 getting-started) live only on the maintainer's machine. they leak too much intent — full private entitlement table, ios-version session-borrowing tactics, risk-control analysis — and have no operational value to a downstream user. * gitignore now hides docs/ * git rm --cached drops the 5 markdown files; local copies stay on disk * README rewritten as a public-only quickstart (no doc cross-links) * code comments referencing docs/N §X stripped to keep the public source self-explanatory what stays public: source, build scripts, ci, project.yml, xcconfig, LICENSE, README, entitlements (declarative, not secret).
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.
what
stealth path proof-of-concept (m0.5). adds 4 system-session importer
strategies and a debug-only diagnostics view that runs all of them and
exports a redacted markdown report.
why
so the user does not have to log in a second time inside EvilStore. the
real apple-id session is borrowed off-device, removing the new-device
risk-control path that asspp users hit.
changes
ACAccountStorevia objc kvc bridge)/var/mobile/Library/com.apple.itunesstored/com.apple.itunesstored#if DEBUG; release tipa drops itdiagnostics matrix shows what is actually reachable per ios version)
test
local: xcodebuild archive Debug + Release both green; final tipa carries
all 10 entitlements; lint clean.
real-device verification (m0.5 task 6) lands as follow-up commits adding
docs/m05_diagnostics/_.md reports.