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");
}
}