Skip to content

fix: tolerate spurious encrypted zip CEN headers on decode - #4208

Open
atirna wants to merge 3 commits into
iBotPeaches:mainfrom
atirna:fix/encrypted-cen-header-4028
Open

fix: tolerate spurious encrypted zip CEN headers on decode#4208
atirna wants to merge 3 commits into
iBotPeaches:mainfrom
atirna:fix/encrypted-cen-header-4028

Conversation

@atirna

@atirna atirna commented Aug 16, 2026

Copy link
Copy Markdown

Description

I changed decode so apktool can open APKs that set the zip encrypted-entry bit (or bogus compression methods) without actually encrypting payload data. AOSP/libziparchive accepts those packages; java.util.zip.ZipFile rejects them with invalid CEN header (encrypted entry).

When that happens, apktool now repairs the central-directory and local-header flags in a temp copy, keeps the original apkFileName for rebuild, and deletes the repair copy after decode.

Fixes #4028

Why

Malware and packer APKs that install fine on Android were failing at the first zip open during apktool d, blocking analysis on the same samples reporters attached to #4028 and related threads.

Verification

  • before, on current main: ./gradlew :brut.apktool:apktool-lib:test --tests brut.androlib.EncryptedCenHeaderTest — test did not exist; manual corrupt-bit APK fails with ZipDexContainer$NotAZipFileException
  • after: same Gradle test — passes (decode + apktool.yml keeps encrypted_cen.apk + rebuild writes dist/encrypted_cen.apk)

Made with Cursor

atirna added 2 commits August 17, 2026 00:54
APKs that AOSP accepts can set the encrypted-entry bit (or bogus compression
methods) without actually encrypting entries. java.util.zip rejects those CEN
headers while libziparchive ignores them.

Repair headers in a temp copy when ZipFile fails with invalid CEN header, so
apktool d works on the same class of packages reported in iBotPeaches#4028.

Fixes iBotPeaches#4028

Signed-off-by: Atirna <288419661+atirna@users.noreply.github.com>
Track the user path separately from the repaired zip source, delete the
repair copy after decode, and set zip64 validation bypass for library
entrypoints. Extend the regression test to cover apktool.yml and rebuild
output naming.

Signed-off-by: Atirna <288419661+atirna@users.noreply.github.com>
@iBotPeaches

Copy link
Copy Markdown
Owner

Always thought we'd need a complex return of ZipUtils, but this creation with AI might be a shortened version.

@atirna
atirna force-pushed the fix/encrypted-cen-header-4028 branch from e38997c to f7cef94 Compare August 17, 2026 06:00
@atirna

atirna commented Aug 18, 2026

Copy link
Copy Markdown
Author

yeah its a shorter path than wrapping ZipUtils. decode still repairs CEN/local flags in a temp copy when java.util.zip rejects encrypted-entry bits that AOSP accepts, then it keeps the original apkFileName for rebuild.

@iBotPeaches

Copy link
Copy Markdown
Owner

So ultimately its a choice whether maintaining a chunk of code is worth it vs an alternative library. I'm sure @IgorEisberg has some opinions as well

@IgorEisberg

IgorEisberg commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

So here are my impressions:

  1. It's not Apktool's job to fix objectively invalid ZIPs.
  2. If Android accepts objectively invalid ZIPs, and we want to replicate that, then we should include our own ZIP handling library under a dedicated module, like brut.j.zip, where we have full control over its behavior.
  3. This is way too many logic changes in ApkDecoder and ZipRODirectory. Hard to follow and maintain this path juggling that was added for the sole purpose of handling a tiny subset of intentionally manipulated APKs.
  4. This smells like AI slop. Even the test is way longer than it should be.

@iBotPeaches

Copy link
Copy Markdown
Owner

If we make brut.j.zip - I imagine the userland changes should be just swapping out the backing ZipFile in the brut.j.dir. Nothing in Apktool userland should change, since its all hopefully routed through ExtFile.

@iBotPeaches iBotPeaches left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed a bit. Onboard if we introduce a new area (brut.j.zip) and can do with no userland changes, as everything should be handled via ExtFile.

If you have to change anything elsewhere. Please let me know what led to that and why.

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.

[BUG] Invalid CEN header (encrypted entry)

3 participants