Skip to content

fix: resolve meta-data resource refs, spoof SigningInfo history, hook binder entry points - #2

Open
aartzz wants to merge 1 commit into
rushiiMachine:masterfrom
aartzz:fix/resolve-metadata-refs-and-hook-binder-entry
Open

aartzz wants to merge 1 commit into
rushiiMachine:masterfrom
aartzz:fix/resolve-metadata-refs-and-hook-binder-entry

Conversation

@aartzz

@aartzz aartzz commented Sep 26, 2026

Copy link
Copy Markdown

Summary

This PR fixes three issues that prevented signature spoofing from working with microG (and similar consumers) on some ROMs:

  1. Resource references in <meta-data> are not resolved

    fake-signature and fake-signature-only are read with Bundle#getString/getBoolean. When a manifest declares a resource reference, e.g. microG's android:value="@string/fake_signature", the framework stores the integer resource ID in the bundle, not the value. getString then returns null and spoofing is silently skipped.

    The PR resolves integer meta-data values against the target application's resources (AssetManager#addAssetPath + Resources#getValue, cached per APK path), supporting string, boolean, integer and fallback (coerced) values.

  2. The SigningInfo / SigningDetails path is not spoofed for single-signer packages

    SigningInfo#getApkContentsSigners() returns a copy of the underlying array, so the previous origSignatures[0] = sig early-return path modified a throwaway array. SigningDetails#mSignatures/signatures was never updated, and mPastSigningCertificates/pastSigningCertificates was not updated either. Consumers that inspect the signing certificate history (e.g. microG's PackageUtils#firstSignatureDigestBytes) therefore still saw the original certificate.

    The PR always writes the SigningDetails signature field and keeps the certificate history in sync when it is a Signature[].

  3. Only ComputerEngine#generatePackageInfo was hooked

    On some ROMs (observed on Samsung One UI 5 / Android 13, SM-M325FV) mutating the PackageInfo produced by the engine class is not enough: the object returned to callers over the binder is not the one modified there. The PR additionally hooks the binder entry points (IPackageManagerBase on Android 13+, PackageManagerService$IPackageManagerImpl on Android 12) and getPackageInfo/getPackageInfoVersioned, with safe lookup so missing classes/methods are skipped on other versions.

Testing

  • Device: Samsung Galaxy M32 (SM-M325FV), Android 13 (One UI 5), KernelSU-Next, Vector (LSPosed fork) as the Xposed implementation.
  • Target: microG GmsCore / Phonesky declared with fake-signature pointing at the Google certificate (38918a453d07199354f8b19af05ec6562ced5788).
  • A PackageManager probe run against both the binder interface and the app-level PackageManager now returns 38918a453d07199354f8b19af05ec6562ced5788 for signatures[0], signingInfo.getApkContentsSigners()[0] and signingInfo.getSigningCertificateHistory()[0].
  • microG Self-Check (Підтримка підміни підпису) reports: system signature spoofing OK, microG Services correct signature OK, microG Companion / Play Store correct signature OK.
  • The build was also smoke-tested on the same device without the meta-data resolution path (hardcoded certificate) to isolate the changes.

Happy to adjust the approach (e.g. split into separate commits/PRs) if you prefer.

@aartzz

aartzz commented Sep 26, 2026

Copy link
Copy Markdown
Author

For anyone who wants to test this before it is reviewed: I published a signed test build of this branch on my fork.

https://github.com/aartzz/XSpoofSignatures/releases/tag/v1.0.1-fix.1

It was built from the same source as this PR and verified on a Samsung Galaxy M32 (Android 13, One UI 5) with microG: Self-Check reports all signature checks as OK. Note that it is signed with a test key, not the upstream release key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant