Skip to content

fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.39.0 (#43) - #46

Open
plant-saver3000 wants to merge 8 commits into
docbt:devfrom
plant-saver3000:dev
Open

plant-saver3000 wants to merge 8 commits into
docbt:devfrom
plant-saver3000:dev

Conversation

@plant-saver3000

@plant-saver3000 plant-saver3000 commented Jul 27, 2026 •

Copy link
Copy Markdown

Edit 2026-09-05:

The Hide-Pur patch stopped working for versions > 2026.30.0 as the developers completely changed the underlying technology of the settings menu. So I had to update the patch. I also bumped the version to the newest 2026.36.0.

Original message from 2026-07-27:

First things first:

Although I have a bit of experience in writing Python code, I'm very new to Kotlin, Patching APKs and the Morphe project in whole. So if there is any big mistake from my side, I apologize in advance.

But I really like the Morphe project and also your patches, so I wanted to contribute and give something back. As I'm not that familiar with APKs and Kotlin, I mainly use Claude AI to help me fixing the patches. Then I double checked the logic of the patches that Claude offered me and tested it thoroughly.

fix: resolve Pur visibility toggle by content instead of position

Fixes #31 (Pur still visible after patching). The previous fingerprint identified the target row by parameter shape (>= 5 boolean params) and patched the first IF_EQZ instruction found in the method — neither was actually tied to the Pur row specifically, so both broke silently once the compiled method signature shifted in a later app release.

Rewrites the fingerprint to anchor on content instead of shape/position:

  • Matches via resourceLiteral(ResourceType.STRING, "ka_gbl_pur"), resolved from the APK's own resource table at patch time rather than hardcoded.
  • Identifies the specific setVisibility(I)V call belonging to the Pur row, not just the first one in the method (there are ~14, one per settings row).
  • Patches the visibility argument directly to View.GONE instead of intercepting the boolean flag that gates it, so it no longer depends on which register or branch opcode (IF_EQZ/IF_NEZ) the compiler happens to emit.

refactor: harden share-url fingerprint against the same failure mode

Applies the same anchoring fix to
ShareUrlParamBuilderFingerprint, which previously locked onto an obfuscated class type name directly (Lebk/ui/vip/compose/content/e;). Now identifies the class by co-occurring string literals from the share-target switch statement, and explicitly throws if more than one method matches the target shape instead of silently taking the first match. "Remove Tracking parameters" stopped working for me in some newer versions, that's why I changed the design of the fingerprint to make it more robust.

feat: bump supported Kleinanzeigen version to 2026.30.0

Closes #43 (support newer Kleinanzeigen versions — previously pinned to 2026.16.1). Hide Pur, Hide Ads, and Remove Tracking Params now all target 2026.30.0. Older AppTarget entries were dropped rather than kept alongside

chore: bump app.morphe.patches to 1.3.0 and add morphe-patches-library

Needed for resourceLiteral/resourceMappingPatch, used by the Hide Pur fix above. Bumped app.morphe.patches 1.2.0 -> 1.3.0 (Kotlin 2.0.21 -> 2.2.0) and added morphe-patches-library 1.2.0, the release
confirmed built against morphe-patcher 1.3.3.

Deliberately stayed on plugin 1.3.0 rather than 1.3.1+, which also bumps AGP 8.13.2 -> 9.1.0 — kept this change scoped to the Kotlin version bump only, since that's the only piece actually required here.

Re-ran the full Google News patch set against the updated toolchain to confirm the plugin bump doesn't regress anything outside this PR's scope — all patches there still build and match correctly.

I've verified the Kleinanzeigen patches against several versions between 2026.14.2 and the newest 2026.30.0. All the versions worked, so in the AppTarget we could also include various older versions if you like. I'm not sure what the practice is here. Only target the newest version? The 3 newest versions? Several versions? Feel free to give a suggestion.

Closes #31
Closes #43

@plant-saver3000 plant-saver3000 changed the title fix: hide pur (#31), harden share-url fingerprint and bump Kleinanzeigen versions (#43) fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump Kleinanzeigen versions (#43) Jul 27, 2026
@plant-saver3000 plant-saver3000 changed the title fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump Kleinanzeigen versions (#43) fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump AppTarget versions (#43) Jul 27, 2026
@plant-saver3000 plant-saver3000 changed the title fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump AppTarget versions (#43) fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.36.0 (#43) Sep 4, 2026
@plant-saver3000

Copy link
Copy Markdown
Author

Just tested with V2026.37.1 and it worked without problems, so I bumped the version to the latest one.

@plant-saver3000 plant-saver3000 changed the title fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.36.0 (#43) fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.37.1 (#43) Sep 10, 2026
@plant-saver3000

Copy link
Copy Markdown
Author

Just tested with V2026.38.3 and it worked without problems, so I bumped the version to the latest one.

@plant-saver3000 plant-saver3000 changed the title fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.37.1 (#43) fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.38.3 (#43) Sep 17, 2026
@xnisayx

xnisayx commented Sep 18, 2026

Copy link
Copy Markdown

Tested this branch against Kleinanzeigen 2026.37.1 and 2026.38.3. 37.1 works fine with all three patches. 38.3 crashes the app immediately on launch, and the cause is in HideAdsPatch, not in the two patches this PR reworked.

Hide Ads crashes on 2026.38.3

LibertyInitFingerprint anchors on KEY_LIBERTY_REFRESH_INTERVAL. In 2026.38.3 that string moved out of the init method into a new suspend config builder:

version method holding the string return type
2026.37.1 ebk/core/liberty/d.g(Ljava/util/ArrayList;)V V
2026.38.3 ebk/core/liberty/d.s(Ljava/util/List;Lkotlin/coroutines/…/c;)Ljava/lang/Object; Ljava/lang/Object;

So on 38.3 the patch injects return-void into a method whose return type is Object. That is unverifiable bytecode — the class fails verification and the app dies at startup. d.s also genuinely returns a freshly constructed de/kleinanzeigen/liberty/h config object at its normal exit, so returning early from it is wrong regardless of the opcode used.

The actual init method is unchanged: ebk/core/liberty/d.g(Ljava/util/ArrayList;)V still exists in 2026.38.3, same name, same signature, still void, and still contains the Microsoft Clarity setup. Only the anchor string left it.

What worked for me:

internal object LibertyInitFingerprint : Fingerprint(
    strings = listOf("MicrosoftClarityService: Failed to initialize Microsoft Clarity SDK"),
    custom = { method, _ -> method.returnType == "V" },
)

The return-type guard matters as much as the new anchor: it turns exactly this failure mode into a patch-time error instead of an APK that installs fine and crashes on launch.

Hide Pur matches more than one method

Not a crash, but worth tightening while you are in here. resourceLiteral(ResourceType.STRING, "ka_gbl_pur") is not unique — four methods reference it in both versions: the settings list builder, the ad comparison screen, the ad-free landing page and a GDPR bottom sheet. Which one the fingerprint returns depends on class iteration order, and the settings builder is not first in 38.3.

The settings builder is the only one taking the settings-and-help state as a parameter, and it gets renamed between releases while that package path does not:

  • 2026.37.1 — androidx/appcompat/widget/b0.z(Lebk/ui/preferences/settings/settings_and_help/state/e;…)Ljava/io/Serializable;
  • 2026.38.3 — ebk/ui/home/usecase/n.k(Lebk/ui/preferences/settings/settings_and_help/state/e;…)Ljava/io/Serializable;
custom = { method, _ ->
    method.parameterTypes.any {
        it.toString().startsWith("Lebk/ui/preferences/settings/settings_and_help/state/")
    }
},

The backward walk to the nearest IF_EQZ/IF_NEZ itself is correct on 38.3 — it lands on the booleanValue() gate right before the AD_FREE_SUBSCRIPTION row is added, with the gate register below v16, so const/4 still encodes.

Remove Tracking Params

No change needed. On 2026.38.3 the anchor strings all land in one class (L_COROUTINE/a;) and it has exactly one (String, String) -> String method, so the fingerprint resolves cleanly and the PatchException guard does not fire.

Also checked

No libpairipcore.so or comparable integrity library in either base APK, so the startup crash is not an anti-tamper reaction.

With the two fingerprint changes above, all three patches work on 2026.38.3 here. Happy to open a PR against your branch with them if that is easier than folding them in yourself.

@plant-saver3000

Copy link
Copy Markdown
Author

@xnisayx Thanks a lot for the detailed review! I really appreciate it.

Funnily enough, I've been working on the new version 2026.38.3 the last few hours (before reading your comment) and also realized the few things you've mentioned. With the help of Gemini I also got it figured out - maybe a bit of a different approach than you had, but it works on my end. So feel free to test it. Quick notes:

Hide Ads crashes on 2026.38.3

Correct, KEY_LIBERTY_REFRESH_INTERVAL moved. I've found a different string than you, that still targets the correct method: https://prebid-server.rubiconproject.com/openrtb2/auction

I think the URL should be even more stable across versions than the error message you've proposed. What do you think?
Thanks for the tip with the return-type guard. I'll add it to my code.

Hide Pur matches more than one method

Correct, I also just realized that Pur was still visible in 2026.38.3. Geminis idea was to target a second string ka_settings_v2_top_ad_free_subscription_pur_subtitle. Both appear together only in one method, the targeted one. I've tested it and it worked. But let me know if you feel like your way is better/more stable across versions. 😊

@plant-saver3000 plant-saver3000 changed the title fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.38.3 (#43) fix(kleinanzeigen): hide pur (#31), harden share-url fingerprint and bump version to 2026.39.0 (#43) Sep 24, 2026
@plant-saver3000

plant-saver3000 commented Sep 24, 2026 •

Copy link
Copy Markdown
Author

Bumped the version to 2026.39.0. Seems like the fingerprints were stable enough to bump versions without changing the code. Nice 🎉

Closes #31
Closes #43
Closes #51

@xnisayx

xnisayx commented Sep 29, 2026 •

Copy link
Copy Markdown

If you’ve got time, would it perhaps be an option for you to make your fork available in such a way that we can integrate the patch directly into Morphe via your fork?

Most of the patches currently available for Morphe come from the AI, or at least help out. So there’s no problem there.

I don’t think there’s any point in submitting any more pull requests here, as docbt hasn’t been in touch or incorporated the code for months.

@plant-saver3000

Copy link
Copy Markdown
Author

@xnisayx Sorry, but I'm not really keen on creating my own fork of patches and integrate it to the Morphe patch system. I love to contribute but I don't see myself maintaining the patches. I hope you understand.

Hopefully @docbt will soon find some time to merge my PR(s). 😊

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.

2 participants