From b6c8c6be2bbd984fcc6565242c9328b5b9a18af9 Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Thu, 13 Jun 2019 18:11:39 -0400 Subject: [PATCH] GT-2926 remove special case matching for zlib headers in DMG filesystem (#583). Some pre-mac appstore DMGs contained zlib compressed payloads. The naive check for zlib enabled the DMG file system to catch those cases, at the expense of false positives for other zlib content. This commit stops the DMG file system from claiming zlib formatted files. Also fix unreleased filehandle in DmgDecryptorStream --- .../ios/dmg/DmgClientFileSystemFactory.java | 10 ++--- .../formats/ios/dmg/DmgDecryptorStream.java | 41 ++++++++++++------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgClientFileSystemFactory.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgClientFileSystemFactory.java index 909b5b6470..d00585282a 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgClientFileSystemFactory.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgClientFileSystemFactory.java @@ -21,7 +21,6 @@ import java.io.IOException; import generic.jar.ResourceFile; import ghidra.app.util.bin.ByteProvider; import ghidra.file.formats.xar.XARUtil; -import ghidra.file.formats.zlib.ZLIB; import ghidra.formats.gfilesystem.*; import ghidra.formats.gfilesystem.factory.GFileSystemFactoryWithFile; import ghidra.formats.gfilesystem.factory.GFileSystemProbeFull; @@ -46,7 +45,7 @@ public class DmgClientFileSystemFactory @Override public boolean probe(FSRL containerFSRL, ByteProvider byteProvider, File containerFile, FileSystemService fsService, TaskMonitor taskMonitor) - throws IOException, CancelledException { + throws IOException, CancelledException { if (!isDmgPresent()) { return false; @@ -56,9 +55,6 @@ public class DmgClientFileSystemFactory if (XARUtil.isXAR(byteProvider)) { return false; } - if (ZLIB.isZLIB(byteProvider)) { - return true; - } return isEncrypted(containerFile); } @@ -84,7 +80,7 @@ public class DmgClientFileSystemFactory @Override public DmgClientFileSystem create(FSRL containerFSRL, FSRLRoot targetFSRL, File containerFile, FileSystemService fsService, TaskMonitor monitor) - throws IOException, CancelledException { + throws IOException, CancelledException { String dmgName = containerFSRL.getName(); @@ -103,7 +99,7 @@ public class DmgClientFileSystemFactory fsService.getDerivedFile(containerFSRL, "decrypted " + containerName, (srcFile) -> { monitor.initialize(srcFile.length()); return new DmgDecryptorStream(containerName, dmgName, srcFile); - } , monitor); + }, monitor); decrypted_dmg_file = fce.file; } else { diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgDecryptorStream.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgDecryptorStream.java index 0cf7a7251b..6d088c0552 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgDecryptorStream.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgDecryptorStream.java @@ -15,15 +15,15 @@ */ package ghidra.file.formats.ios.dmg; +import java.io.*; +import java.util.Arrays; + import ghidra.app.util.bin.*; import ghidra.file.crypto.*; import ghidra.file.formats.ios.generic.iOS_AesCrypto; import ghidra.file.formats.ios.generic.iOS_Sha1Crypto; import ghidra.util.exception.CryptoException; -import java.io.*; -import java.util.Arrays; - /** * An {@link InputStream} that decrypts a DMG file on the fly. *

@@ -76,19 +76,32 @@ public class DmgDecryptorStream extends InputStream { public DmgDecryptorStream(String containerName, String dmgName, ByteProvider provider) throws IOException { + try { + CryptoKey cryptoKey = CryptoKeyFactory.getCryptoKey(containerName, dmgName); + if (cryptoKey.key.length != 36) { + throw new CryptoException("Invalid key length."); + } + if (cryptoKey.iv.length != 0) { + throw new CryptoException("Invalid initialization vector (IV) length."); + } + + aes_key = Arrays.copyOfRange(cryptoKey.key, 0, 16); + sha1_key = Arrays.copyOfRange(cryptoKey.key, 16, 16 + 20); + } + catch (IOException e) { + // Release the provider before this exception finishes since the #close() method can't + // be called later to release it. + try { + provider.close(); + } + catch (IOException ioe) { + // ignore + } + throw e; + } + this.provider = provider; - CryptoKey cryptoKey = CryptoKeyFactory.getCryptoKey(containerName, dmgName); - if (cryptoKey.key.length != 36) { - throw new CryptoException("Invalid key length."); - } - if (cryptoKey.iv.length != 0) { - throw new CryptoException("Invalid initialization vector (IV) length."); - } - - aes_key = Arrays.copyOfRange(cryptoKey.key, 0, 16); - sha1_key = Arrays.copyOfRange(cryptoKey.key, 16, 16 + 20); - sha1 = new iOS_Sha1Crypto(sha1_key); BinaryReader reader = new BinaryReader(provider, false);