Skip to content

Inject pass fails on PAC devices: INJECT_SENTINEL_LR is not a canonical pointer #40

Description

@troublediosuser

AI usage disclosure

Opus 5 found this issue while making a personal wrapper around this tool, so it's only been tested on the apps I want to decrypt, and only on my jailbroken device. Also, I tested both decrypted Instagram apps in Livecontainer and I couldn't find a difference between them since both functioned the same. Maybe it's different if they're sideloaded or installed another way, can't test myself, and I can't test if this will cause any regression issues, but I have tested a couple apps that decrypted fine without this change and decrypting them with this new build saw no changes.

Summary

On PAC devices (A12 and newer) the inject pass never loads anything, so any
framework that is not already resident in the target is left encrypted and
verify fails. The cause is one constant. Proposed fix, in helper/inject.c:

-#define INJECT_SENTINEL_LR 0x4141414141414141ULL
+#define INJECT_SENTINEL_LR 0x0000000041414141ULL

Why

When the helper injects a call into the target process, it sets a fake return
address on the hijacked thread. When the called function returns, it jumps to
that fake address, which is unmapped, so the process traps and the helper knows
the call has finished. That fake address is INJECT_SENTINEL_LR.

On PAC hardware (A12 and newer) the current value does not work. Arm's pointer
authentication treats 0x4141414141414141 as a non canonical pointer, because
bits 55 through 47 are neither all zeroes nor all ones. When such a value is
signed, the CPU deliberately flips a bit in the signature so that any later
authentication of it fails on purpose. If anything in the call path signs and
then authenticates the return address, which is what a normal pacibsp and
autibsp function epilogue does, the authentication fails and the thread takes
an EXC_BAD_ACCESS with EXC_ARM_PAC_FAIL instead of reaching the sentinel.

target_call sees an exception that is not the sentinel trap and returns -1, so
the caller reports dlopen failed ... rc=-1 handle=0x0 and the image is never
loaded or decrypted.

The new value 0x0000000041414141 is a canonical pointer, so signing and
authenticating it round trips normally. It is still inside __PAGEZERO, so it
is still unmapped and still traps when the call returns, which is the behaviour
the sentinel relies on. Nothing else changes.

This is a device class problem, not an app specific one. Stock libdyld's
dlopen does not sign a return address, so the bug only appears when something
in the call path does. In the case below that was a jailbreak tweak hooking
dlopen, but any signed frame in front of the called function produces the same
failure. The inject pass is only reached when a framework is not already loaded
in the target, which is rare, so this can go unnoticed for a long time.

Before

Environment: iPhone 13 Pro Max (iPhone14,3), iOS 15.4, arm64e, Dopamine.
Target: Pokemon GO 0.423.1. Built from main at 567de708 (v0.7.4), unmodified.

Frameworks/SwiftProtobuf.framework/SwiftProtobuf is linked only by
PlugIns/homewidget.appex, so it is never loaded in the main app process and is
the only image that needs the inject pass.

  ✓ found installed com.nianticlabs.pokemongo v0.423.1
    · threadpool ready: 34 fresh pthreads to hijack
    · dlopen failed name=Frameworks/SwiftProtobuf.framework/SwiftProtobuf rc=-1 handle=0x0
    · inject pass 0 loaded 0
    · inject failed for Frameworks/SwiftProtobuf.framework/SwiftProtobuf (dlopen returned NULL or hung)
    · bundle done: 29 framework(s) decrypted
  ✓ decrypted 32 image(s): 3 main, 29 framework
  ✗ verify failed: 1 still encrypted
Full log
  ✓ ipadecrypt dev · mobile@… iOS 15.4 arm64e iPhone14,3 (Dopamine)
  ✓ found installed com.nianticlabs.pokemongo v0.423.1
  ✓ helper ready
    · CS enforcement lax (csflags=0x32007001); debugger attach not needed
    · event=target.csflags pid="51913" csflags="0x32007001" platform="0" cdhash="7d764f839d4c7940b2a51e6511f5cc7f794a05fd"
    · spawned com.nianticlabs.pokemongo via SBS (pid=51913)
    · decrypted main PokmonGO (16.0 KB)
    · event=patch.applied addr="0x1cbab2c58" tag="abort_with_payload"
    · event=patch.applied tag="__abort_with_payload" addr="0x1cbab0320"
    · event=patch.applied tag="abort" addr="0x19f0a4474"
    · event=patch.dyld_base_diff dyld="0x10264c000" libdyld="0x193c6b000"
    · event=patch.applied tag="diag_error" addr="0x1026912e4"
    · event=patch.applied addr="0x102691310" tag="diag_error"
    · symtab patches: 2 (Diagnostics::error ret)
    · event=dyld.settled
    · decrypted Frameworks/Sentry.framework/Sentry (1.7 MB)
    · decrypted Frameworks/UnityFramework.framework/UnityFramework (155.1 MB)
    · decrypted Frameworks/FBAEMKit.framework/FBAEMKit (224.0 KB)
    · decrypted Frameworks/FBSDKCoreKit.framework/FBSDKCoreKit (1.4 MB)
    · decrypted Frameworks/FBSDKCoreKit_Basics.framework/FBSDKCoreKit_Basics (48.0 KB)
    · decrypted Frameworks/FBSDKGamingServicesKit.framework/FBSDKGamingServicesKit (320.0 KB)
    · decrypted Frameworks/FBSDKLoginKit.framework/FBSDKLoginKit (320.0 KB)
    · decrypted Frameworks/FBSDKShareKit.framework/FBSDKShareKit (256.0 KB)
    · decrypted Frameworks/NiaAdvsyncPermissions.framework/NiaAdvsyncPermissions (128.0 KB)
    · decrypted Frameworks/NianticPhoneAuth.framework/NianticPhoneAuth (16.0 KB)
    · decrypted Frameworks/HelpshiftX.framework/HelpshiftX (448.0 KB)
    · decrypted Frameworks/NianticPlatformAddressBookImport.framework/NianticPlatformAddressBookImport (64.0 KB)
    · decrypted Frameworks/NianticPlatformIdentityWebview.framework/NianticPlatformIdentityWebview (16.0 KB)
    · decrypted Frameworks/LightshipARDK.framework/LightshipARDK (14.5 MB)
    · decrypted Frameworks/NiaAdvsyncFitness.framework/NiaAdvsyncFitness (160.0 KB)
    · decrypted Frameworks/NianticClientSecretsManager.framework/NianticClientSecretsManager (48.0 KB)
    · decrypted Frameworks/NianticLabsPlugin.framework/NianticLabsPlugin (5.5 MB)
    · decrypted Frameworks/UnityiOSPlugin.framework/UnityiOSPlugin (16.0 KB)
    · decrypted Frameworks/NianticPlatformIap.framework/NianticPlatformIap (224.0 KB)
    · decrypted Frameworks/NiaAdvsyncCore.framework/NiaAdvsyncCore (160.0 KB)
    · decrypted Frameworks/NiaAdvsyncReporter.framework/NiaAdvsyncReporter (1.5 MB)
    · decrypted Frameworks/NianticPlatformAuthGoogleSignIn.framework/NianticPlatformAuthGoogleSignIn (416.0 KB)
    · decrypted Frameworks/NianticPlatformSharedLogin.framework/NianticPlatformSharedLogin (64.0 KB)
    · decrypted Frameworks/NiaAuthFacebookSignIn.framework/NiaAuthFacebookSignIn (16.0 KB)
    · decrypted Frameworks/UsabillaCS.framework/UsabillaCS (1.5 MB)
    · decrypted Frameworks/NianticPlatformSocialWebview.framework/NianticPlatformSocialWebview (48.0 KB)
    · decrypted Frameworks/NiaAdvsyncLocation.framework/NiaAdvsyncLocation (176.0 KB)
    · decrypted Frameworks/NianticPlatformNativeUtil.framework/NianticPlatformNativeUtil (64.0 KB)
    · decrypted Frameworks/geouploader.framework/geouploader (464.0 KB)
    · event=patch.api_lock_scan prims="0" callers="0" dyld_base="0x10264c000" scanned="8388608" found="0"
    · threadpool: spawned 34/34 fresh pthreads
    · threadpool ready: 34 fresh pthreads to hijack
    · dlopen failed name=Frameworks/SwiftProtobuf.framework/SwiftProtobuf rc=-1 handle=0x0
    · inject pass 0 loaded 0
    · inject failed for Frameworks/SwiftProtobuf.framework/SwiftProtobuf (dlopen returned NULL or hung)
    · bundle done: 29 framework(s) decrypted
    · spawned /var/containers/Bundle/Application/0D25767E-71C1-4501-89F3-6256EEE3AA57/PokmonGO.app/PlugIns/notification.appex/notification via ptrace (pid=52455)
    · decrypted main notification (624.0 KB)
    · spawned /var/containers/Bundle/Application/0D25767E-71C1-4501-89F3-6256EEE3AA57/PokmonGO.app/PlugIns/homewidget.appex/homewidget via ptrace (pid=52456)
    · decrypted main homewidget (224.0 KB)
    · packaged -> stdout
  ✓ decrypted 32 image(s): 3 main, 29 framework (153.7 MB → /tmp/pogo-c.ipa)
  ✗ verify failed: 1 still encrypted

Note rc=-1. target_call returns 0 when the hijacked thread traps at the
sentinel, so a genuine dlopen returning NULL would log rc=0 handle=0x0. A
-1 means the call never returned at all.

otool -l on that binary in the produced IPA:

cmd LC_ENCRYPTION_INFO_64
cryptoff 16384
cryptsize 983040
cryptid 1

Entropy of the 983040 byte crypt region: 8.000, which is the maximum, so the
region is still ciphertext. First bytes: 62 19 a1 e1.

Result: 32 of 33 encrypted binaries decrypted.

After

Same environment, same target, same 567de708, with only that one line
changed:

  ✓ found installed com.nianticlabs.pokemongo v0.423.1
    · threadpool ready: 34 fresh pthreads to hijack
    · inject pass 0 loaded 1
    · inject pass 1 loaded 0
    · bundle done: 30 framework(s) decrypted
  ✓ decrypted 33 image(s): 3 main, 30 framework
  ✓ 33 Mach-O(s) verified
Full log
  ✓ ipadecrypt dev · mobile@… iOS 15.4 arm64e iPhone14,3 (Dopamine)
  ✓ found installed com.nianticlabs.pokemongo v0.423.1
  ✓ helper ready
    · CS enforcement lax (csflags=0x32007001); debugger attach not needed
    · event=target.csflags pid="52477" csflags="0x32007001" platform="0" cdhash="7d764f839d4c7940b2a51e6511f5cc7f794a05fd"
    · spawned com.nianticlabs.pokemongo via SBS (pid=52477)
    · decrypted main PokmonGO (16.0 KB)
    · event=patch.dyld_base_diff dyld="0x102d00000" libdyld="0x0"
    · event=patch.applied tag="diag_error" addr="0x102d452e4"
    · event=patch.applied addr="0x102d45310" tag="diag_error"
    · symtab patches: 2 (Diagnostics::error ret)
    · event=dyld.settled
    · decrypted Frameworks/Sentry.framework/Sentry (1.7 MB)
    · decrypted Frameworks/UnityFramework.framework/UnityFramework (155.1 MB)
    · decrypted Frameworks/FBAEMKit.framework/FBAEMKit (224.0 KB)
    · decrypted Frameworks/FBSDKCoreKit.framework/FBSDKCoreKit (1.4 MB)
    · decrypted Frameworks/FBSDKCoreKit_Basics.framework/FBSDKCoreKit_Basics (48.0 KB)
    · decrypted Frameworks/FBSDKGamingServicesKit.framework/FBSDKGamingServicesKit (320.0 KB)
    · decrypted Frameworks/FBSDKLoginKit.framework/FBSDKLoginKit (320.0 KB)
    · decrypted Frameworks/FBSDKShareKit.framework/FBSDKShareKit (256.0 KB)
    · decrypted Frameworks/NiaAdvsyncPermissions.framework/NiaAdvsyncPermissions (128.0 KB)
    · decrypted Frameworks/NianticPhoneAuth.framework/NianticPhoneAuth (16.0 KB)
    · decrypted Frameworks/HelpshiftX.framework/HelpshiftX (448.0 KB)
    · decrypted Frameworks/NianticPlatformAddressBookImport.framework/NianticPlatformAddressBookImport (64.0 KB)
    · decrypted Frameworks/NianticPlatformIdentityWebview.framework/NianticPlatformIdentityWebview (16.0 KB)
    · decrypted Frameworks/LightshipARDK.framework/LightshipARDK (14.5 MB)
    · decrypted Frameworks/NiaAdvsyncFitness.framework/NiaAdvsyncFitness (160.0 KB)
    · decrypted Frameworks/NianticClientSecretsManager.framework/NianticClientSecretsManager (48.0 KB)
    · decrypted Frameworks/NianticLabsPlugin.framework/NianticLabsPlugin (5.5 MB)
    · decrypted Frameworks/UnityiOSPlugin.framework/UnityiOSPlugin (16.0 KB)
    · decrypted Frameworks/NianticPlatformIap.framework/NianticPlatformIap (224.0 KB)
    · decrypted Frameworks/NiaAdvsyncCore.framework/NiaAdvsyncCore (160.0 KB)
    · decrypted Frameworks/NiaAdvsyncReporter.framework/NiaAdvsyncReporter (1.5 MB)
    · decrypted Frameworks/NianticPlatformAuthGoogleSignIn.framework/NianticPlatformAuthGoogleSignIn (416.0 KB)
    · decrypted Frameworks/NianticPlatformSharedLogin.framework/NianticPlatformSharedLogin (64.0 KB)
    · decrypted Frameworks/NiaAuthFacebookSignIn.framework/NiaAuthFacebookSignIn (16.0 KB)
    · decrypted Frameworks/UsabillaCS.framework/UsabillaCS (1.5 MB)
    · decrypted Frameworks/NianticPlatformSocialWebview.framework/NianticPlatformSocialWebview (48.0 KB)
    · decrypted Frameworks/NiaAdvsyncLocation.framework/NiaAdvsyncLocation (176.0 KB)
    · decrypted Frameworks/NianticPlatformNativeUtil.framework/NianticPlatformNativeUtil (64.0 KB)
    · decrypted Frameworks/geouploader.framework/geouploader (464.0 KB)
    · event=patch.api_lock_scan callers="0" dyld_base="0x102d00000" scanned="8388608" found="0" prims="0"
    · threadpool: spawned 34/34 fresh pthreads
    · threadpool ready: 34 fresh pthreads to hijack
    · decrypted Frameworks/SwiftProtobuf.framework/SwiftProtobuf (960.0 KB)
    · inject pass 0 loaded 1
    · inject pass 1 loaded 0
    · bundle done: 30 framework(s) decrypted
    · spawned /var/containers/Bundle/Application/0D25767E-71C1-4501-89F3-6256EEE3AA57/PokmonGO.app/PlugIns/notification.appex/notification via ptrace (pid=52481)
    · decrypted main notification (624.0 KB)
    · spawned /var/containers/Bundle/Application/0D25767E-71C1-4501-89F3-6256EEE3AA57/PokmonGO.app/PlugIns/homewidget.appex/homewidget via ptrace (pid=52482)
    · decrypted main homewidget (224.0 KB)
    · packaged -> stdout
  ✓ decrypted 33 image(s): 3 main, 30 framework (153.2 MB → /tmp/pogo-f.ipa)
  ✓ 33 Mach-O(s) verified

No dlopen failed, no inject failed, and the verify step passes.

otool -l on the same binary:

cmd LC_ENCRYPTION_INFO_64
cryptoff 16384
cryptsize 983040
cryptid 0

Entropy of the same region: 6.494, which is ordinary compiled code. First
bytes: ff 03 01 d1, which is sub sp, sp, #0x40, a normal ARM64 function
prologue. cryptoff and cryptsize are unchanged, so the load command geometry
is untouched.

Result: 33 of 33 encrypted binaries decrypted.

Second case: Instagram 442.0.0

Same device. Instagram 442.0.0 was already installed, so both runs used
--use-installed --no-uninstall, which downloads and installs nothing. The only
difference between the two runs is the one line above.

Exactly one image in that bundle needs the inject pass:
Frameworks/libmobile_first_frame_pipeline.framework/libmobile_first_frame_pipeline.
The other five frameworks are already resident and are read out of the live
process.

Unpatched:

  ✓ ipadecrypt dev · mobile@… iOS 15.4 arm64e iPhone14,3 (Dopamine)
  ✓ found installed com.burbn.instagram v442.0.0
  ✓ helper ready
    · CS enforcement lax (csflags=0x32007001); debugger attach not needed
    · event=target.csflags pid="52549" csflags="0x32007001" platform="0" cdhash="1931c0971d150bc7e63a5e958843303e2e8a8d6a"
    · spawned com.burbn.instagram via SBS (pid=52549)
    · decrypted main Instagram (235.5 MB)
    · event=patch.dyld_base_diff dyld="0x11792c000" libdyld="0x0"
    · event=patch.applied tag="diag_error" addr="0x1179712e4"
    · event=patch.applied tag="diag_error" addr="0x117971310"
    · symtab patches: 2 (Diagnostics::error ret)
    · target trapped: EXC_BAD_ACCESS (skips=0 pac_strips=0)
    · decrypted Frameworks/FBSharedFramework.framework/FBSharedFramework (37.5 MB)
    · decrypted Frameworks/SpotifyiOS.framework/SpotifyiOS (176.0 KB)
    · decrypted Frameworks/libavcodec.framework/libavcodec (512.0 KB)
    · decrypted Frameworks/libavutil.framework/libavutil (80.0 KB)
    · decrypted Frameworks/GoogleCast.framework/GoogleCast (2.2 MB)
    · event=patch.api_lock_scan found="0" prims="0" callers="0" dyld_base="0x11792c000" scanned="8388608"
    · threadpool: spawned 34/34 fresh pthreads
    · threadpool ready: 34 fresh pthreads to hijack
    · dlopen failed name=Frameworks/libmobile_first_frame_pipeline.framework/libmobile_first_frame_pipeline rc=-1 handle=0x0
    · inject pass 0 loaded 0
    · inject failed for Frameworks/libmobile_first_frame_pipeline.framework/libmobile_first_frame_pipeline (dlopen returned NULL or hung)
    · bundle done: 5 framework(s) decrypted
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramNotificationExtension.appex/InstagramNotificationExtension via ptrace (pid=52550)
    · decrypted main InstagramNotificationExtension (9.5 MB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramWidgetExtensionLockScreenCameraControl.appex/InstagramWidgetExtensionLockScreenCameraControl via ptrace (pid=52551)
    · decrypted main InstagramWidgetExtensionLockScreenCameraControl (10.3 MB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramShareExtension.appex/InstagramShareExtension via ptrace (pid=52552)
    · decrypted main InstagramShareExtension (160.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramWidgetExtension.appex/InstagramWidgetExtension via ptrace (pid=52553)
    · decrypted main InstagramWidgetExtension (10.5 MB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramNotificationContentExtension.appex/InstagramNotificationContentExtension via ptrace (pid=52554)
    · decrypted main InstagramNotificationContentExtension (144.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramWidgetExtensionLiveActivities.appex/InstagramWidgetExtensionLiveActivities via ptrace (pid=52555)
    · decrypted main InstagramWidgetExtensionLiveActivities (128.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramBroadcastSampleHandlerExtension.appex/InstagramBroadcastSampleHandlerExtension via ptrace (pid=52556)
    · decrypted main InstagramBroadcastSampleHandlerExtension (64.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/Extensions/InstagramExtensionLockScreenCamera.appex/InstagramExtensionLockScreenCamera via ptrace (pid=52557)
    · decrypted main InstagramExtensionLockScreenCamera (29.5 MB)
    · packaged -> stdout
  ✓ decrypted 14 image(s): 9 main, 5 framework (299.7 MB → /tmp/ig-c.ipa)
  ✗ verify failed: 1 still encrypted

Patched:

  ✓ ipadecrypt dev · mobile@… iOS 15.4 arm64e iPhone14,3 (Dopamine)
  ✓ found installed com.burbn.instagram v442.0.0
  ✓ helper ready
    · CS enforcement lax (csflags=0x32007001); debugger attach not needed
    · event=target.csflags cdhash="1931c0971d150bc7e63a5e958843303e2e8a8d6a" pid="52580" csflags="0x32007001" platform="0"
    · spawned com.burbn.instagram via SBS (pid=52580)
    · decrypted main Instagram (235.5 MB)
    · event=patch.dyld_base_diff dyld="0x116694000" libdyld="0x0"
    · event=patch.applied tag="diag_error" addr="0x1166d92e4"
    · event=patch.applied addr="0x1166d9310" tag="diag_error"
    · symtab patches: 2 (Diagnostics::error ret)
    · target trapped: EXC_BAD_ACCESS (skips=0 pac_strips=0)
    · decrypted Frameworks/FBSharedFramework.framework/FBSharedFramework (37.5 MB)
    · decrypted Frameworks/SpotifyiOS.framework/SpotifyiOS (176.0 KB)
    · decrypted Frameworks/libavcodec.framework/libavcodec (512.0 KB)
    · decrypted Frameworks/libavutil.framework/libavutil (80.0 KB)
    · decrypted Frameworks/GoogleCast.framework/GoogleCast (2.2 MB)
    · event=patch.api_lock_scan callers="0" dyld_base="0x116694000" scanned="3178496" found="0" prims="0"
    · threadpool: spawned 34/34 fresh pthreads
    · threadpool ready: 34 fresh pthreads to hijack
    · decrypted Frameworks/libmobile_first_frame_pipeline.framework/libmobile_first_frame_pipeline (864.0 KB)
    · inject pass 0 loaded 1
    · inject pass 1 loaded 0
    · bundle done: 6 framework(s) decrypted
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramNotificationExtension.appex/InstagramNotificationExtension via ptrace (pid=52582)
    · decrypted main InstagramNotificationExtension (9.5 MB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramWidgetExtensionLockScreenCameraControl.appex/InstagramWidgetExtensionLockScreenCameraControl via ptrace (pid=52583)
    · decrypted main InstagramWidgetExtensionLockScreenCameraControl (10.3 MB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramShareExtension.appex/InstagramShareExtension via ptrace (pid=52584)
    · decrypted main InstagramShareExtension (160.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramWidgetExtension.appex/InstagramWidgetExtension via ptrace (pid=52585)
    · decrypted main InstagramWidgetExtension (10.5 MB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramNotificationContentExtension.appex/InstagramNotificationContentExtension via ptrace (pid=52586)
    · decrypted main InstagramNotificationContentExtension (144.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramWidgetExtensionLiveActivities.appex/InstagramWidgetExtensionLiveActivities via ptrace (pid=52587)
    · decrypted main InstagramWidgetExtensionLiveActivities (128.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/PlugIns/InstagramBroadcastSampleHandlerExtension.appex/InstagramBroadcastSampleHandlerExtension via ptrace (pid=52588)
    · decrypted main InstagramBroadcastSampleHandlerExtension (64.0 KB)
    · spawned /var/containers/Bundle/Application/712E03E4-0BAC-4297-8375-5324AFE5B8B4/Instagram.app/Extensions/InstagramExtensionLockScreenCamera.appex/InstagramExtensionLockScreenCamera via ptrace (pid=52589)
    · decrypted main InstagramExtensionLockScreenCamera (29.5 MB)
    · packaged -> stdout
  ✓ decrypted 15 image(s): 9 main, 6 framework (299.3 MB → /tmp/ig-f.ipa)
  ✓ 15 Mach-O(s) verified
Successfully installed "com.burbn.instagram"!

otool -l on that framework, from the two produced IPAs:

unpatched   cryptoff 16384   cryptsize 884736   cryptid 1
patched     cryptoff 16384   cryptsize 884736   cryptid 0

Entropy of the 884736 byte crypt region: 7.816 unpatched, 6.553 patched. The
load command geometry is identical in both, so the region is decrypted rather
than rewritten.

Unpacking both IPAs and hashing every file: 2330 files compared, and exactly one
differs, the framework above. Nothing else in the output changes.

Reproducing

Any app with a framework that is not already resident in the target process will
exercise the inject pass, on any PAC device where something signs a return
address in front of dlopen. Two cases are used here: Pokemon GO 0.423.1 with
SwiftProtobuf, which is linked only by an app extension, and Instagram 442.0.0
with libmobile_first_frame_pipeline. In both, the affected image is the only
one that fails, and it fails the same way.

Notes

If you take this, the embedded
internal/device/ipadecrypt-helper-arm64 needs rebuilding through the pinned
toolchain rather than by hand. Two builds of identical source differ in their
LC_UUID, so an out of band helper binary is not reproducible against yours.

Issues #23 and #35 report frameworks that fail to decrypt and may look related,
but both reporters are on pre PAC hardware (A8X and A11), so they are probably a
different problem. I am not claiming this closes them.

One separate observation, not addressed here: when the verify step reports
verify failed, the process still exits 0. That is likely why this went
unreported, since a failing decrypt looks like a successful run to anything
checking the exit code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions