package fuzion24.device.vulnerability.vulnerabilities.framework.zip; import android.content.Context; import org.apache.commons.compress.archivers.zip.ModdedZipArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import fuzion24.device.vulnerability.util.CPUArch; import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityTest; /* C++ Header 64k Local File header name Data +--------> +----------------------> +----------> length=64k classes.dex dex\035\A... dex\035\B... +--------> +---------> +----------> Java Header 11 Name Data */ public class ZipBug9950697 implements VulnerabilityTest { public String getCVEorID(){ return "ZipBug 9950697"; } @Override public List<CPUArch> getSupportedArchitectures() { ArrayList<CPUArch> archs = new ArrayList<>(); archs.add(CPUArch.ALL); return archs; } public boolean isVulnerable(Context context) throws Exception { ByteArrayOutputStream fileNameFunz = new ByteArrayOutputStream(); ModdedZipArchiveOutputStream zaos = new ModdedZipArchiveOutputStream(fileNameFunz); ZipArchiveEntry zae = new ZipArchiveEntry("test_file"); byte [] originalData = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes(); byte [] modifiedData = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB".getBytes(); zae.setMethod(ZipEntry.STORED); zae.setSize(originalData.length); CRC32 checker = new CRC32(); checker.update(originalData); zae.setCrc(checker.getValue()); zaos.putArchiveEntry(zae, originalData); zaos.write(originalData); zaos.closeArchiveEntry(); zaos.writeRaw(modifiedData, 0, modifiedData.length); for(int i = 0; i < originalData.length - modifiedData.length; i++){ zaos.writeRaw(new byte[]{0}, 0, 1); } zaos.flush(); List<ZipArchiveEntry> entries = new ArrayList<>(); entries.add(zae); zaos.finish(entries, new ArrayList<ZipArchiveEntry>()); byte [] testZip = fileNameFunz.toByteArray(); // write the result to a file File outputDir = context.getCacheDir(); File badZip = File.createTempFile("prefix", "extension", outputDir); badZip.deleteOnExit(); FileOutputStream outstream = new FileOutputStream(badZip); outstream.write(testZip); outstream.close(); // see if we can still handle it ZipFile bad = new ZipFile(badZip); if(bad.size() != 1) throw new ZipException("Unexpected number of entries"); ZipEntry ze = bad.entries().nextElement(); DataInputStream dis = new DataInputStream(bad.getInputStream(ze)); byte [] buf = new byte[(int)ze.getSize()]; dis.readFully(buf); bad.close(); return new String(buf).startsWith("AAAAAAAAAAAAAAA"); } }