objection icon indicating copy to clipboard operation
objection copied to clipboard

[bug] objection patchapk fails to inject frida-gadget

Open radon-at-beeper opened this issue 2 months ago • 4 comments

Describe the bug A patched application starts up normally instead of pausing, indicating that frida-gadget wasn't injected correctly.

To Reproduce See below for example application.

Steps to reproduce the behavior:

  1. objection patchapk -s base.apk
  2. objection signapk split_*.apk
  3. adb install-multiple *.objection.apk
  4. Launch the app, it launches normally rather than pausing at startup

Similar issues didn't see any

Expected behavior According to https://github.com/sensepost/objection/wiki/Running-Patched-Android-Applications, a patched application should pause at startup.

Evidence / Logs / Screenshots Any output from objection, such as stack traces or errors that occurred. Be sure to run objection with the --debug flag so that errors from the agent are verbose enough to debug. For example:

% /tmp/venv/bin/objection -d patchapk -s base.apk
No architecture specified. Determining it using `adb`...
Detected target device architecture as: arm64-v8a
Using latest Github gadget version: 17.4.1
Patcher will be using Gadget version: 17.4.1
Detected apktool version as: 2.12.1
Running apktool empty-framework-dir...
Unpacking base.apk
An error may have occurred while extracting the APK.
Invocation: /usr/bin/apktool decode -f -o /tmp/tmpaifwfkfx.apktemp base.apk
W: Unknown data detected at end of type chunk. Skipping: 80 byte(s)

App already has android.permission.INTERNET
Target class not specified, searching for launchable activity instead...
Unable to determine the launchable activity using aapt, trying to manually parse the AndroidManifest for activity aliases...
Smali not found in smali directory. This might be a multidex APK. Searching...
Found smali at: /tmp/tmpaifwfkfx.apktemp/smali_classes2/com/instagram/mainactivity/InstagramMainActivity.smali
Reading smali from: /tmp/tmpaifwfkfx.apktemp/smali_classes2/com/instagram/mainactivity/InstagramMainActivity.smali
Injecting into an existing constructor
Injecting loadLibrary call at line: 165
Attempting to fix the constructors .locals count
Current locals value is 2, updating to 3:
Writing patched smali back to: /tmp/tmpaifwfkfx.apktemp/smali_classes2/com/instagram/mainactivity/InstagramMainActivity.smali
Copying Frida gadget to libs path...
Rebuilding the APK with the frida-gadget loaded...
Rebuilding the APK may have failed. Read the following output to determine if apktool actually had an error: 

W: /tmp/tmpaifwfkfx.apktemp/res/values-h640dp/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values-h640dp/layouts.xml: error: file failed to compile.
W: /tmp/tmpaifwfkfx.apktemp/res/values-land/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values-land/layouts.xml:4: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values-land/layouts.xml: error: file failed to compile.
W: /tmp/tmpaifwfkfx.apktemp/res/values-sw600dp/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values-sw600dp/layouts.xml:4: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values-sw600dp/layouts.xml: error: file failed to compile.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:4: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:5: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:6: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:7: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:8: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:9: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:10: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:11: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:12: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:13: error: invalid value for type 'layout'. Expected a reference.
W: /tmp/tmpaifwfkfx.apktemp/res/values/layouts.xml:14: error: invalid value for type 'layout'. Expected a reference.
Exception in thread "main" brut.androlib.exceptions.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [/tmp/brut_util_Jar_148049056042784291774775889863617329001.tmp, compile, --dir, /tmp/tmpaifwfkfx.apktemp/res, --legacy, -o, /tmp/tmpaifwfkfx.apktemp/build/resources.zip]
	at brut.androlib.AaptInvoker.invoke(SourceFile:105)
	at brut.androlib.ApkBuilder.buildResources(SourceFile:328)
	at brut.apktool.Main.main(SourceFile:96)
Caused by: brut.common.BrutException: could not exec (exit code = 1): [/tmp/brut_util_Jar_148049056042784291774775889863617329001.tmp, compile, --dir, /tmp/tmpaifwfkfx.apktemp/res, --legacy, -o, /tmp/tmpaifwfkfx.apktemp/build/resources.zip]
	at brut.util.OS.exec(SourceFile:148)
	at brut.androlib.AaptInvoker.invoke(SourceFile:101)
	... 2 more

Built new APK with injected loadLibrary and frida-gadget
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmpaifwfkfx.apktemp.aligned.objection.apk to base.objection.apk in current directory...
Cleaning up temp files...

% objection signapk split_*.apk
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmpeffi9su6.apktemp.aligned.objection.apk to split_config.xxhdpi.objection.apk in current directory...
Cleaning up temp files...
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmpnz1nww8t.apktemp.aligned.objection.apk to split_executorch.objection.apk in current directory...
Cleaning up temp files...
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmpp67ga6qi.apktemp.aligned.objection.apk to split_heliumcore.objection.apk in current directory...
Cleaning up temp files...
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmp4bj9io1r.apktemp.aligned.objection.apk to split_heliumiab.objection.apk in current directory...
Cleaning up temp files...
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmp3mlrnnyd.apktemp.aligned.objection.apk to split_pytorch.objection.apk in current directory...
Cleaning up temp files...
Performing zipalign
Zipalign completed
Signing new APK.
Signed the new APK
Copying final apk from /tmp/tmpc8e30h__.apktemp.aligned.objection.apk to split_spm.objection.apk in current directory...
Cleaning up temp files...

Environment (please complete the following information):

  • Device: Google Pixel 7
  • OS: Android 15, LineageOS 22.2-20250919-NIGHTLY-panther
  • Frida Version: 17.4.1
  • Objection Version: 1.11.0 at https://github.com/sensepost/objection/commit/e282ea00ec74dde0cc8fc97104a3d942298c944d with https://github.com/sensepost/objection/pull/768

Application Recent Instagram split APK: https://drive.google.com/file/d/1nuh8lf19biR5yamCy8s_fEAMnp9jBVU-/view?usp=drive_link

Additional context If there are troubleshooting steps or other command-line options that should be tried, or ways of validating whether patching is happening successfully, it would be extremely helpful if those were documented on the wiki.

radon-at-beeper avatar Oct 28 '25 21:10 radon-at-beeper

Objection currently does not support multipart apks, (the shared object libraries do not reside in base.apk). However you can try this method: https://github.com/sensepost/objection/issues/679#issuecomment-2250758446 I need to experiment/research a bit more with it before I implement it

IPMegladon avatar Oct 29 '25 05:10 IPMegladon

Hmmm, are you sure the shared object libraries do not reside in base.apk? I see this in the APK attached to the issue report:

% unzip -l base.apk | grep arm64    
    10096  01-01-1981 01:01   lib/arm64-v8a/libandroidx.graphics.path.so
   117272  01-01-1981 01:01   lib/arm64-v8a/libarcore_sdk_jni.so
   504080  01-01-1981 01:01   lib/arm64-v8a/libbreakpad.so
     7424  01-01-1981 01:01   lib/arm64-v8a/libbreakpad_cpp_helper.so
   454128  01-01-1981 01:01   lib/arm64-v8a/libc++_shared.so
   275408  01-01-1981 01:01   lib/arm64-v8a/libfbunwindstack.so
   212112  01-01-1981 01:01   lib/arm64-v8a/libgraphics-core.so
   207448  01-01-1981 01:01   lib/arm64-v8a/libsuperpack-jni.so
    11488  01-01-1981 01:01   lib/arm64-v8a/libunwindstack_binary.so

Notably, there is no architecture-specific split like split_config.arm64_v8a.apk in this APK, the splits are as follows:

base.apk
split_config.xxhdpi.apk
split_executorch.apk
split_heliumcore.apk
split_heliumiab.apk
split_pytorch.apk
split_spm.apk

radon-at-beeper avatar Oct 29 '25 15:10 radon-at-beeper

Nope, first time I see that format. Few things you can try:

  • Perhaps try skip step 3&4 of that linked comment and just check if you need to add - lib/arm64-v8a/libfrida-gadget.so to the apktool.yml of base.apk in the tmp directory provided by objection.
  • You can try https://github.com/REAndroid/APKEditor to merge the apps.
  • Can try using LIEF instead: https://lief.re/doc/stable/tutorials/09_frida_lief.html for the patching. (or https://blog.nviso.eu/2025/10/14/patching-android-arm64-library-initializers-for-easy-frida-instrumentation-and-debugging/)

IPMegladon avatar Oct 30 '25 10:10 IPMegladon

Wait, while testing the options you outlined, I found the bug. If re-packing the patched APK fails, then objection silently continues on to re-pack the unpatched APK. This would clearly never be correct, and I don't know why that is not simply reported as a fatal error.

You can see in the logs I attached to the original issue report that there is a fatal error when re-packing the APK. However, since objection continued on to generate an allegedly patched APK, I assumed that the error must have not actually been fatal, because it would make no sense to continue if the file literally couldn't be generated. However, that appears to be exactly what objection is doing.

Why is there a fallback in this line of code?

https://github.com/sensepost/objection/blob/e282ea00ec74dde0cc8fc97104a3d942298c944d/objection/utils/patchers/android.py#L920

Original issue text

For the first option, got:

Target class not specified, searching for launchable activity instead...
Unable to determine the launchable activity using aapt, trying to manually parse the AndroidManifest for activity aliases...
Cannot manually parse the AndroidManifest.xml when --skip-resources is set, remove this and try again, or manually specify a manifest with --manifest.

So, I ran apktool d base.apk first and then added --manifest base/AndroidManifest.xml to the objection command line.

With 3&4 omitted, the only difference from what I'd previously done by default with objection was manually adding frida-gadget to doNotCompress, as well as the extra command-line options you provided. I observe the same behavior as in the initial issue report.

For the second option, I took the Objection-patched APKs from the first option and combined them with apkeditor, then re-signed with Objection. The merged APK installed fine, but the behavior was the same as in the initial issue report.

For the third option, I checked adb logcat to see what .so from lib/arm64-v8a was mentioned first. It was:

10-30 09:05:28.202 21669 21706 D nativeloader: Load /data/app/~~6fEn1U21lmi4SpgDH0YALQ==/com.instagram.android-8kv1h4ko-_JdlIg6BHtAUQ==/lib/arm64/libbreakpad.so using class loader ns clns-8 (caller=/data/app/~~6fEn1U21lmi4SpgDH0YALQ==/com.instagram.android-8kv1h4ko-_JdlIg6BHtAUQ==/base.apk!classes11.dex): ok

Thus I unpacked the base apk with apktool, copied in libfrida-gadget.so, added it as a dependency to libbreakpad.so using lief, re-packed with apktool, and re-signed with objection.

>>> import lief
>>> lib = lief.parse("base/lib/arm64-v8a/libbreakpad.so")
>>> lib.add_library("libfrida-gadget.so")
<lief._lief.ELF.DynamicEntryLibrary object at 0x7f9f335cad30>
>>> lib.write("base/lib/arm64-v8a/libbreakpad.so")

As is also shown in the logs provided in the original issue report, there is an error while re-packing the apk:

W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-h640dp/layouts.xml:3: error: invalid value for type '��'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-h640dp/layouts.xml: error: file failed to compile.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-land/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-land/layouts.xml:4: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-land/layouts.xml: error: file failed to compile.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-sw600dp/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-sw600dp/layouts.xml:4: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values-sw600dp/layouts.xml: error: file failed to compile.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:3: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:4: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:5: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:6: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:7: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:8: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:9: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:10: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:11: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:12: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:13: error: invalid value for type 'layout'. Expected a reference.
W: /home/radon/files/reverse/instagram-android/20251024/patched/base/res/values/layouts.xml:14: error: invalid value for type 'layout'. Expected a reference.
Exception in thread "main" brut.androlib.exceptions.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [/tmp/brut_util_Jar_119157818769616552008870111022751565261.tmp, compile, --dir, /home/radon/files/reverse/instagram-android/20251024/patched/base/res, --legacy, -o, /home/radon/files/reverse/instagram-android/20251024/patched/base/build/resources.zip]
	at brut.androlib.AaptInvoker.invoke(SourceFile:105)
	at brut.androlib.ApkBuilder.buildResources(SourceFile:328)
	at brut.apktool.Main.main(SourceFile:96)
Caused by: brut.common.BrutException: could not exec (exit code = 1): [/tmp/brut_util_Jar_119157818769616552008870111022751565261.tmp, compile, --dir, /home/radon/files/reverse/instagram-android/20251024/patched/base/res, --legacy, -o, /home/radon/files/reverse/instagram-android/20251024/patched/base/build/resources.zip]
	at brut.util.OS.exec(SourceFile:148)
	at brut.androlib.AaptInvoker.invoke(SourceFile:101)
	... 2 more

But the re-packed APK is not written, so patching cannot continue.

For reference, the upstream apktool issue is https://github.com/iBotPeaches/Apktool/issues/2618.

radon-at-beeper avatar Oct 30 '25 16:10 radon-at-beeper