ApkDecoder use apkFile and unknownFiles from ApkInfo (#3242)

This commit is contained in:
sv99 2023-08-01 13:57:22 +03:00 committed by GitHub
parent e52c3b0f56
commit 9d7d58016e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 33 additions and 71 deletions

View File

@ -21,8 +21,6 @@ import brut.androlib.exceptions.InFileNotFoundException;
import brut.androlib.exceptions.OutDirExistsException; import brut.androlib.exceptions.OutDirExistsException;
import brut.androlib.apk.ApkInfo; import brut.androlib.apk.ApkInfo;
import brut.androlib.res.ResourcesDecoder; import brut.androlib.res.ResourcesDecoder;
import brut.androlib.res.data.*;
import brut.androlib.res.xml.ResXmlPatcher;
import brut.androlib.src.SmaliDecoder; import brut.androlib.src.SmaliDecoder;
import brut.directory.Directory; import brut.directory.Directory;
import brut.directory.ExtFile; import brut.directory.ExtFile;
@ -41,9 +39,7 @@ public class ApkDecoder {
private final static Logger LOGGER = Logger.getLogger(ApkDecoder.class.getName()); private final static Logger LOGGER = Logger.getLogger(ApkDecoder.class.getName());
private final Config mConfig; private final Config mConfig;
private final ExtFile mApkFile; private final ApkInfo mApkInfo;
protected final ResUnknownFiles mResUnknownFiles;
private ApkInfo mApkInfo;
private int mMinSdkVersion = 0; private int mMinSdkVersion = 0;
private final static String SMALI_DIRNAME = "smali"; private final static String SMALI_DIRNAME = "smali";
@ -73,17 +69,17 @@ public class ApkDecoder {
public ApkDecoder(Config config, ExtFile apkFile) { public ApkDecoder(Config config, ExtFile apkFile) {
mConfig = config; mConfig = config;
mApkFile = apkFile; mApkInfo = new ApkInfo(apkFile);
mResUnknownFiles = new ResUnknownFiles();
} }
public ApkInfo decode(File outDir) throws AndrolibException, IOException, DirectoryException { public ApkInfo decode(File outDir) throws AndrolibException, IOException, DirectoryException {
ExtFile apkFile = mApkInfo.getApkFile();
try { try {
if (!mConfig.forceDelete && outDir.exists()) { if (!mConfig.forceDelete && outDir.exists()) {
throw new OutDirExistsException(); throw new OutDirExistsException();
} }
if (!mApkFile.isFile() || !mApkFile.canRead()) { if (!apkFile.isFile() || !apkFile.canRead()) {
throw new InFileNotFoundException(); throw new InFileNotFoundException();
} }
@ -94,11 +90,9 @@ public class ApkDecoder {
} }
outDir.mkdirs(); outDir.mkdirs();
LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkFile.getName()); LOGGER.info("Using Apktool " + ApktoolProperties.getVersion() + " on " + mApkInfo.apkFileName);
mApkInfo = new ApkInfo(mApkFile); ResourcesDecoder resourcesDecoder = new ResourcesDecoder(mConfig, mApkInfo);
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(mConfig, mApkFile, mApkInfo);
if (mApkInfo.hasResources()) { if (mApkInfo.hasResources()) {
switch (mConfig.decodeResources) { switch (mConfig.decodeResources) {
@ -136,7 +130,7 @@ public class ApkDecoder {
if (mApkInfo.hasMultipleSources()) { if (mApkInfo.hasMultipleSources()) {
// foreach unknown dex file in root, lets disassemble it // foreach unknown dex file in root, lets disassemble it
Set<String> files = mApkFile.getDirectory().getFiles(true); Set<String> files = apkFile.getDirectory().getFiles(true);
for (String file : files) { for (String file : files) {
if (file.endsWith(".dex")) { if (file.endsWith(".dex")) {
if (!file.equalsIgnoreCase("classes.dex")) { if (!file.equalsIgnoreCase("classes.dex")) {
@ -174,7 +168,7 @@ public class ApkDecoder {
return mApkInfo; return mApkInfo;
} finally { } finally {
try { try {
mApkFile.close(); apkFile.close();
} catch (IOException ignored) {} } catch (IOException ignored) {}
} }
} }
@ -186,7 +180,7 @@ public class ApkDecoder {
private void copyManifestRaw(File outDir) throws AndrolibException { private void copyManifestRaw(File outDir) throws AndrolibException {
try { try {
LOGGER.info("Copying raw manifest..."); LOGGER.info("Copying raw manifest...");
mApkFile.getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES); mApkInfo.getApkFile().getDirectory().copyToDir(outDir, APK_MANIFEST_FILENAMES);
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);
} }
@ -195,7 +189,7 @@ public class ApkDecoder {
private void copyResourcesRaw(File outDir) throws AndrolibException { private void copyResourcesRaw(File outDir) throws AndrolibException {
try { try {
LOGGER.info("Copying raw resources..."); LOGGER.info("Copying raw resources...");
mApkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES); mApkInfo.getApkFile().getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);
} }
@ -204,7 +198,7 @@ public class ApkDecoder {
private void copySourcesRaw(File outDir, String filename) throws AndrolibException { private void copySourcesRaw(File outDir, String filename) throws AndrolibException {
try { try {
LOGGER.info("Copying raw " + filename + " file..."); LOGGER.info("Copying raw " + filename + " file...");
mApkFile.getDirectory().copyToDir(outDir, filename); mApkInfo.getApkFile().getDirectory().copyToDir(outDir, filename);
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);
} }
@ -222,7 +216,7 @@ public class ApkDecoder {
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
smaliDir.mkdirs(); smaliDir.mkdirs();
LOGGER.info("Baksmaling " + filename + "..."); LOGGER.info("Baksmaling " + filename + "...");
DexFile dexFile = SmaliDecoder.decode(mApkFile, smaliDir, filename, DexFile dexFile = SmaliDecoder.decode(mApkInfo.getApkFile(), smaliDir, filename,
mConfig.baksmaliDebugMode, mConfig.apiLevel); mConfig.baksmaliDebugMode, mConfig.apiLevel);
int minSdkVersion = dexFile.getOpcodes().api; int minSdkVersion = dexFile.getOpcodes().api;
if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) { if (mMinSdkVersion == 0 || mMinSdkVersion > minSdkVersion) {
@ -236,7 +230,7 @@ public class ApkDecoder {
private void copyRawFiles(File outDir) throws AndrolibException { private void copyRawFiles(File outDir) throws AndrolibException {
LOGGER.info("Copying assets and libs..."); LOGGER.info("Copying assets and libs...");
try { try {
Directory in = mApkFile.getDirectory(); Directory in = mApkInfo.getApkFile().getDirectory();
if (mConfig.decodeAssets == Config.DECODE_ASSETS_FULL) { if (mConfig.decodeAssets == Config.DECODE_ASSETS_FULL) {
if (in.containsDir("assets")) { if (in.containsDir("assets")) {
@ -270,7 +264,7 @@ public class ApkDecoder {
LOGGER.info("Copying unknown files..."); LOGGER.info("Copying unknown files...");
File unknownOut = new File(outDir, UNK_DIRNAME); File unknownOut = new File(outDir, UNK_DIRNAME);
try { try {
Directory unk = mApkFile.getDirectory(); Directory unk = mApkInfo.getApkFile().getDirectory();
// loop all items in container recursively, ignoring any that are pre-defined by aapt // loop all items in container recursively, ignoring any that are pre-defined by aapt
Set<String> files = unk.getFiles(true); Set<String> files = unk.getFiles(true);
@ -281,11 +275,9 @@ public class ApkDecoder {
unk.copyToDir(unknownOut, file); unk.copyToDir(unknownOut, file);
// let's record the name of the file, and its compression type // let's record the name of the file, and its compression type
// so that we may re-include it the same way // so that we may re-include it the same way
mResUnknownFiles.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(file))); mApkInfo.addUnknownFileInfo(file, String.valueOf(unk.getCompressionLevel(file)));
} }
} }
// update apk info
mApkInfo.unknownFiles = mResUnknownFiles.getUnknownFiles();
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);
} }
@ -300,7 +292,7 @@ public class ApkDecoder {
} }
try { try {
Directory in = mApkFile.getDirectory(); Directory in = mApkInfo.getApkFile().getDirectory();
if (in.containsFile("AndroidManifest.xml")) { if (in.containsFile("AndroidManifest.xml")) {
in.copyToDir(originalDir, "AndroidManifest.xml"); in.copyToDir(originalDir, "AndroidManifest.xml");
} }
@ -326,7 +318,7 @@ public class ApkDecoder {
private void recordUncompressedFiles(Map<String, String> resFileMapping) throws AndrolibException { private void recordUncompressedFiles(Map<String, String> resFileMapping) throws AndrolibException {
try { try {
List<String> uncompressedFilesOrExts = new ArrayList<>(); List<String> uncompressedFilesOrExts = new ArrayList<>();
Directory unk = mApkFile.getDirectory(); Directory unk = mApkInfo.getApkFile().getDirectory();
Set<String> files = unk.getFiles(true); Set<String> files = unk.getFiles(true);
for (String file : files) { for (String file : files) {

View File

@ -39,7 +39,7 @@ public class ApkInfo implements YamlSerializable {
public boolean resourcesAreCompressed; public boolean resourcesAreCompressed;
public boolean sharedLibrary; public boolean sharedLibrary;
public boolean sparseResources; public boolean sparseResources;
public Map<String, String> unknownFiles; public Map<String, String> unknownFiles = new LinkedHashMap<>();
public List<String> doNotCompress; public List<String> doNotCompress;
/** @deprecated use {@link #resourcesAreCompressed} */ /** @deprecated use {@link #resourcesAreCompressed} */
@ -120,6 +120,10 @@ public class ApkInfo implements YamlSerializable {
} }
} }
public void addUnknownFileInfo(String file, String value) {
unknownFiles.put(file, value);
}
public String checkTargetSdkVersionBounds() { public String checkTargetSdkVersionBounds() {
int target = mapSdkShorthandToVersion(getTargetSdkVersion()); int target = mapSdkShorthandToVersion(getTargetSdkVersion());
@ -295,7 +299,9 @@ public class ApkInfo implements YamlSerializable {
writer.writeBool("resourcesAreCompressed", resourcesAreCompressed); writer.writeBool("resourcesAreCompressed", resourcesAreCompressed);
writer.writeBool("sharedLibrary", sharedLibrary); writer.writeBool("sharedLibrary", sharedLibrary);
writer.writeBool("sparseResources", sparseResources); writer.writeBool("sparseResources", sparseResources);
writer.writeStringMap("unknownFiles", unknownFiles); if (unknownFiles.size() > 0) {
writer.writeStringMap("unknownFiles", unknownFiles);
}
writer.writeList("doNotCompress", doNotCompress); writer.writeList("doNotCompress", doNotCompress);
} }
} }

View File

@ -27,7 +27,6 @@ import brut.androlib.res.xml.ResValuesXmlSerializable;
import brut.androlib.res.xml.ResXmlPatcher; import brut.androlib.res.xml.ResXmlPatcher;
import brut.directory.Directory; import brut.directory.Directory;
import brut.directory.DirectoryException; import brut.directory.DirectoryException;
import brut.directory.ExtFile;
import brut.directory.FileDirectory; import brut.directory.FileDirectory;
import org.xmlpull.v1.XmlSerializer; import org.xmlpull.v1.XmlSerializer;
@ -39,7 +38,6 @@ public class ResourcesDecoder {
private final static Logger LOGGER = Logger.getLogger(ResourcesDecoder.class.getName()); private final static Logger LOGGER = Logger.getLogger(ResourcesDecoder.class.getName());
private final Config mConfig; private final Config mConfig;
private final ExtFile mApkFile;
private final ApkInfo mApkInfo; private final ApkInfo mApkInfo;
private final ResTable mResTable; private final ResTable mResTable;
private final Map<String, String> mResFileMapping = new HashMap<>(); private final Map<String, String> mResFileMapping = new HashMap<>();
@ -48,9 +46,8 @@ public class ResourcesDecoder {
"android", "com.htc", "com.lge", "com.lge.internal", "yi", "flyme", "air.com.adobe.appentry", "android", "com.htc", "com.lge", "com.lge.internal", "yi", "flyme", "air.com.adobe.appentry",
"FFFFFFFFFFFFFFFFFFFFFF" }; "FFFFFFFFFFFFFFFFFFFFFF" };
public ResourcesDecoder(Config config, ExtFile apkFile, ApkInfo apkInfo) { public ResourcesDecoder(Config config, ApkInfo apkInfo) {
mConfig = config; mConfig = config;
mApkFile = apkFile;
mApkInfo = apkInfo; mApkInfo = apkInfo;
mResTable = new ResTable(mConfig, mApkInfo); mResTable = new ResTable(mConfig, mApkInfo);
} }
@ -68,7 +65,7 @@ public class ResourcesDecoder {
} }
public void loadMainPkg() throws AndrolibException { public void loadMainPkg() throws AndrolibException {
mResTable.loadMainPkg(mApkFile); mResTable.loadMainPkg(mApkInfo.getApkFile());
} }
public void decodeManifest(File outDir) throws AndrolibException { public void decodeManifest(File outDir) throws AndrolibException {
@ -81,7 +78,7 @@ public class ResourcesDecoder {
Directory inApk, out; Directory inApk, out;
try { try {
inApk = mApkFile.getDirectory(); inApk = mApkInfo.getApkFile().getDirectory();
out = new FileDirectory(outDir); out = new FileDirectory(outDir);
if (mApkInfo.hasResources()) { if (mApkInfo.hasResources()) {
@ -147,7 +144,7 @@ public class ResourcesDecoder {
return; return;
} }
mResTable.loadMainPkg(mApkFile); mResTable.loadMainPkg(mApkInfo.getApkFile());
ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); ResStreamDecoderContainer decoders = new ResStreamDecoderContainer();
decoders.setDecoder("raw", new ResRawStreamDecoder()); decoders.setDecoder("raw", new ResRawStreamDecoder());
@ -161,7 +158,7 @@ public class ResourcesDecoder {
try { try {
out = new FileDirectory(outDir); out = new FileDirectory(outDir);
in = mApkFile.getDirectory(); in = mApkInfo.getApkFile().getDirectory();
out = out.createDir("res"); out = out.createDir("res");
} catch (DirectoryException ex) { } catch (DirectoryException ex) {
throw new AndrolibException(ex); throw new AndrolibException(ex);

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.res.data;
import java.util.LinkedHashMap;
import java.util.Map;
public class ResUnknownFiles {
private final Map<String, String> mUnknownFiles = new LinkedHashMap<>();
public void addUnknownFileInfo(String file, String value) {
mUnknownFiles.put(file, value);
}
public Map<String, String> getUnknownFiles() {
return mUnknownFiles;
}
}

View File

@ -54,7 +54,7 @@ public class NonStandardPkgIdTest extends BaseTest {
LOGGER.info("Decoding pkgid8.apk..."); LOGGER.info("Decoding pkgid8.apk...");
ApkInfo testInfo = new ApkInfo(testApk); ApkInfo testInfo = new ApkInfo(testApk);
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), testApk, testInfo); ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), testInfo);
sTestNewDir.mkdirs(); sTestNewDir.mkdirs();
resourcesDecoder.decodeResources(sTestNewDir); resourcesDecoder.decodeResources(sTestNewDir);

View File

@ -55,7 +55,7 @@ public class DecodeArrayTest extends BaseTest {
ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk"); ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk");
ApkInfo apkInfo = new ApkInfo(apkFile); ApkInfo apkInfo = new ApkInfo(apkFile);
//ApkDecoder apkDecoder = new ApkDecoder(apkFile); //ApkDecoder apkDecoder = new ApkDecoder(apkFile);
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkFile, apkInfo); ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkInfo);
resourcesDecoder.loadMainPkg(); resourcesDecoder.loadMainPkg();
ResTable resTable = resourcesDecoder.getResTable(); ResTable resTable = resourcesDecoder.getResTable();
@ -68,7 +68,7 @@ public class DecodeArrayTest extends BaseTest {
public void decodeArray() throws BrutException { public void decodeArray() throws BrutException {
ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk"); ExtFile apkFile = new ExtFile(sTmpDir, "issue1994.apk");
ApkInfo apkInfo = new ApkInfo(apkFile); ApkInfo apkInfo = new ApkInfo(apkFile);
ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkFile, apkInfo); ResourcesDecoder resourcesDecoder = new ResourcesDecoder(Config.getDefaultConfig(), apkInfo);
resourcesDecoder.loadMainPkg(); resourcesDecoder.loadMainPkg();
ResTable resTable = resourcesDecoder.getResTable(); ResTable resTable = resourcesDecoder.getResTable();