jadx icon indicating copy to clipboard operation
jadx copied to clipboard

[core] Caused by: java.util.zip.ZipException: invalid CEN header (bad compression method: 7261)

Open ohyeah521 opened this issue 1 year ago • 9 comments

Issue details

The malware exploits the Android system's failure to verify zip flag tampering, causing an exception to be thrown when parsing the apk.

Relevant log output or stacktrace

jadx.core.utils.exceptions.JadxRuntimeException: Failed to process zip file: C:\Users\test\Desktop\test.apk
        at jadx.api.plugins.utils.ZipSecurity.visitZipEntries(ZipSecurity.java:148)
        at jadx.api.plugins.utils.ZipSecurity.readZipEntries(ZipSecurity.java:154)
        at jadx.plugins.input.java.JavaInputLoader.collectFromZip(JavaInputLoader.java:91)
        at jadx.plugins.input.java.JavaInputLoader.loadReader(JavaInputLoader.java:71)
        at jadx.plugins.input.java.JavaInputLoader.loadFromFile(JavaInputLoader.java:50)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
        at jadx.plugins.input.java.JavaInputLoader.collectFiles(JavaInputLoader.java:37)
        at jadx.plugins.input.java.JavaInputPlugin.loadClassFiles(JavaInputPlugin.java:36)
        at jadx.plugins.input.java.JavaInputPlugin.loadClassFiles(JavaInputPlugin.java:32)
        at jadx.api.JadxDecompiler.loadInputFiles(JadxDecompiler.java:153)
        at jadx.api.JadxDecompiler.load(JadxDecompiler.java:119)
        at jadx.cli.JadxCLI.processAndSave(JadxCLI.java:51)
        at jadx.cli.JadxCLI.execute(JadxCLI.java:38)
        at jadx.cli.JadxCLI.main(JadxCLI.java:22)
Caused by: java.util.zip.ZipException: invalid CEN header (bad compression method: 7261)
        at java.base/java.util.zip.ZipFile$Source.zerror(ZipFile.java:1597)
        at java.base/java.util.zip.ZipFile$Source.initCEN(ZipFile.java:1557)
        at java.base/java.util.zip.ZipFile$Source.<init>(ZipFile.java:1299)
        at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1262)
        at java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:733)
        at java.base/java.util.zip.ZipFile$CleanableResource.get(ZipFile.java:842)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:248)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:177)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:191)
        at jadx.api.plugins.utils.ZipSecurity.visitZipEntries(ZipSecurity.java:130)
        ... 20 common frames omitted

Provide sample and class/method full name

test.zip

Jadx version

1.5.0

ohyeah521 avatar Apr 30 '24 11:04 ohyeah521

It is a known problem that ZIP implementation of Java does not support archives with unknown compression methods. As you can see from the stack trace this happens when creating the ZipFile instance, thus there is no way to ignore or skip this error.

The only way to solve this problem would be using a completely different ZIP implementation.

jpstotz avatar Apr 30 '24 11:04 jpstotz

You are right. Maybe we can analyze the source code by referring to the zip of the source code and ignore some of the verification fields that throw exceptions.

ohyeah521 avatar Apr 30 '24 11:04 ohyeah521

To my knowledge there is no option or other possibility to skip this check. initCEN is always executed when opening a new ZIP file

See https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/util/zip/ZipFile.java

jpstotz avatar Apr 30 '24 11:04 jpstotz

It is true that Java is very difficult to implement. Perhaps introducing an external decompression tool is a better choice. Instead of calling the system library directly, it can be made into a configuration option. When encountering confusion, users can choose the decompression tool themselves. In this way, decompilation can continue. I think this implementation is better than exiting directly.

ohyeah521 avatar Apr 30 '24 11:04 ohyeah521

You have the sample file. Feel free to test other libraries but to my knowledge there are not many like ZIP libraries that have an own implementation. Just two candidates come to my mind: apache-commons-compress and zip4j.

jpstotz avatar Apr 30 '24 11:04 jpstotz

@jpstotz I tried zip4j, but it also not support fake compression method :cry:

Caused by: net.lingala.zip4j.exception.ZipException: Unknown compression method
	at net.lingala.zip4j.model.enums.CompressionMethod.getCompressionMethodFromCode(CompressionMethod.java:52)
	at net.lingala.zip4j.headers.HeaderReader.readLocalFileHeader(HeaderReader.java:543)
	at net.lingala.zip4j.io.inputstream.ZipInputStream.getNextEntry(ZipInputStream.java:115)
	at net.lingala.zip4j.io.inputstream.ZipInputStream.getNextEntry(ZipInputStream.java:105)
	at jadx.api.plugins.utils.ZipSecurity.visitZipEntries(ZipSecurity.java:135)

Will try other lib :confused:

skylot avatar Apr 30 '24 17:04 skylot

Apache Commons Compress also doesn't support fake compression method:

Caused by: org.apache.commons.compress.archivers.zip.UnsupportedZipFeatureException: Unsupported feature compression method used in entry AndroidManifest.xml
	at org.apache.commons.compress.archivers.zip.ZipUtil.checkRequestedFeatures(ZipUtil.java:145)
	at org.apache.commons.compress.archivers.zip.ZipArchiveInputStream.read(ZipArchiveInputStream.java:915)

Looks like the only way to fight such tampering is to write own zip reader implementation :rofl:

skylot avatar Apr 30 '24 19:04 skylot

Looks like the only way to fight such tampering is to write own zip reader implementation

It must be what JEB has done (link to JEB API). It's working fine for me with JEB 5.12:

image

jackwpa avatar May 01 '24 00:05 jackwpa

I actually implemented my own zip parser, and it is working fine :rofl: But looks like this sample use some tricks to prevent parsing AndroidManifest.xml (maybe related to #2182), so I will keep working on this issue.

skylot avatar May 19 '24 16:05 skylot

Fixed in PR #2298 by @qfalconer :tada:

skylot avatar Oct 10 '24 16:10 skylot

Well done, I provide another idea: I first check whether the apk file has modified the zip file format through a third-party tool. If so, use it to decompress, and then use jadx to analyze the dex file. Since this implementation requires the use of third-party tools, I did not provide a PR

ohyeah521 avatar Oct 10 '24 20:10 ohyeah521

Hi @ohyeah521, can I ask you which third-party tool do you use? Thanks

drego85 avatar Nov 19 '24 22:11 drego85

I created this Python script based on the initial work of @qfalconer: https://gist.github.com/drego85/f3fa845b2f14b29e926417d697131134

Any other tools or information is definitely appreciated!

drego85 avatar Nov 20 '24 10:11 drego85

@drego85 https://github.com/mins4416/apk_cure

ohyeah521 avatar Nov 20 '24 10:11 ohyeah521

I created this Python script based on the initial work of @qfalconer: https://gist.github.com/drego85/f3fa845b2f14b29e926417d697131134

Any other tools or information is definitely appreciated!

Maybe you can integrate these 2 projects together. https://github.com/mins4416/apk_cure

ohyeah521 avatar Nov 20 '24 11:11 ohyeah521