Universal injection mechanism: any process where AVFoundation is
loaded (Camera.app, continuitycaptured, third-party apps, system
daemons — anything dyld pulls AVF into) automatically gets libcamfix
via TweakLoader. No per-bundle plist filter, no allowlist entries.
scripts/tweakloader/TweakLoader.m
New Filter.Frameworks key. A tweak's plist may list framework
names; TweakLoader matches the path containing
"/<name>.framework/". Already-loaded frameworks trigger an immediate
dlopen; not-yet-loaded frameworks register a
_dyld_register_func_for_add_image callback that fires when the
named framework appears.
Two-tier engagement:
- Framework-filtered tweaks scan + schedule in EVERY process,
self-limiting at runtime. Cost in non-AVF processes is one
dir scan + a few plist parses + one callback registration.
- Non-framework tweaks (Bundles/Executables or no filter) keep
the existing .app/+kVPhoneAllowedDaemonPaths gate so we don't
drop arbitrary tweaks into launch-critical daemons.
CRITICAL safety: dyld invokes add-image callbacks SYNCHRONOUSLY
inside its loader lock. dlopen from within that callback recurses
and can deadlock or crash early daemons. The actual dlopen is
handed off to a background queue (dispatch_async) so it runs after
dyld is idle.
Defensive: each per-tweak block is @try/@catch wrapped so a
malformed plist or Foundation quirk in an early-boot daemon can't
crash the process and trigger a launchd respawn loop.
scripts/camfix/libcamfix.m
Constructor no longer eagerly installs hooks. Instead registers a
_dyld_register_func_for_add_image callback and installs hooks the
first time AVFCapture's mach header is observed (idempotent via
dispatch_once). Whether libcamfix loads before or after AVFCapture,
hooks land exactly once.
cfx_capturePhoto_hook now drives the MODERN
-[<AVCapturePhotoCaptureDelegate> captureOutput:
didFinishProcessingPhoto:error:] path in addition to the deprecated
CMSampleBuffer one. The synthesized AVCapturePhoto uses nil
captureRequest (there's no CAMCaptureEngine outside Camera.app —
msgSend to nil during init returns 0 safely). Photos tagged with
associated JPEG/CGImage so fileDataRepresentation /
CGImageRepresentation return our bytes regardless of which delegate
protocol the client implements.
scripts/camfix/libcamfix.plist
Filter.Frameworks = ["AVFoundation"]. Replaces the previous
Bundles=["com.apple.camera"] filter.
scripts/cfw_install_exp.sh
build_libcamfix install_name reverted to /var/jb/Library/
MobileSubstrate/DynamicLibraries/libcamfix.dylib (TweakLoader
location). [JB-4.2] deploys dylib + plist together.
Verified on fresh `make setup_machine` install of 26.5:
- 373+ distinct AVF-using processes auto-load libcamfix at boot,
including watchdogd / amfid / backboardd / SpringBoard /
cameracaptured / continuitycaptured.
- Camera.app: preview live, photos save, shutter works past
many consecutive captures.
- continuitycaptured: a vanilla AVCapturePhotoCaptureDelegate
using the documented capturePhotoWithSettings:delegate: API gets
a real 1280x720 JFIF JPEG via the modern delegate path.
- Full reboot cycle stable.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
libvcamcaptured.dylib is loaded into /usr/libexec/cameracaptured via
TweakLoader and registers a synthetic FigCaptureSource backed by the
vphone shm region. From AVF's point of view there is now a normal
"vphone:vcam:0" camera device that streams BGRA frames at the
session's requested width/height.
scripts/vcamcaptured/ .gitignore (drop built .dylib),
Makefile, libvcamcaptured.m,
libvcamcaptured.plist (filter:
Executables=["cameracaptured"]).
scripts/tweakloader/TweakLoader.m add /usr/libexec/cameracaptured
to kVPhoneAllowedDaemonPaths so
TweakLoader engages in a daemon
(not just .app/) processes.
scripts/cfw_install_exp.sh build_libvcamcaptured() helper
(clang + CoreMedia/CoreVideo/
Foundation, ldid-signed) and
new [JB-4.1] section that
scp's the dylib + plist into
procursus/Library/MobileSubstrate/
DynamicLibraries.
Pairs with the host vphone-cli camera server + vphoned vcam vsock
listener already in this branch.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Convert README header to ATX style and add spacing/blank lines for improved Markdown readability in scripts/tweakloader/README.md. Also adjust spacing in a table row in research/0_binary_patch_comparison.md to correct alignment/formatting.