diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index f5e9c16b..dc6e48ca 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -199,8 +199,8 @@ public class Main { apkOptions.forceBuildAll = true; } if (cli.hasOption("d") || cli.hasOption("debug")) { - System.err.println("SmaliDebugging has been removed in 2.1.0 onward. Please see: https://github.com/iBotPeaches/Apktool/issues/1061"); - System.exit(1); + System.out.println("SmaliDebugging has been removed in 2.1.0 onward. Please see: https://github.com/iBotPeaches/Apktool/issues/1061"); + apkOptions.debugMode = true; } if (cli.hasOption("v") || cli.hasOption("verbose")) { apkOptions.verbose = true; @@ -286,7 +286,7 @@ public class Main { .create(); Option debugBuiOption = OptionBuilder.withLongOpt("debug") - .withDescription("Builds in debug mode. Check project page for more info.") + .withDescription("Sets android:debuggable to \"true\" in the APK's compiled manifest") .create("d"); Option noDbgOption = OptionBuilder.withLongOpt("no-debug-info") diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index f11ba5d5..0aae3938 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -409,6 +409,10 @@ public class Androlib { newFiles(APK_RESOURCES_FILENAMES, apkDir))) { LOGGER.info("Building resources..."); + if (apkOptions.debugMode) { + ResXmlPatcher.removeApplicationDebugTag(new File(appDir, "AndroidManifest.xml")); + } + File apkFile = File.createTempFile("APKTOOL", null); apkFile.delete(); @@ -476,7 +480,6 @@ public class Androlib { Directory tmpDir = new ExtFile(apkFile).getDirectory(); tmpDir.copyToDir(apkDir, APK_MANIFEST_FILENAMES); - } return true; } catch (IOException | DirectoryException ex) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java index cc778c8d..df4774fd 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkOptions.java @@ -19,6 +19,7 @@ import java.util.Collection; public class ApkOptions { public boolean forceBuildAll = false; + public boolean debugMode = false; public boolean verbose = false; public boolean copyOriginalFiles = false; public boolean updateFiles = false; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java index 12f861c9..60dd33f1 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java @@ -346,6 +346,9 @@ final public class AndrolibResources { if (apkOptions.updateFiles) { cmd.add("-u"); } + if (apkOptions.debugMode) { // inject debuggable="true" into manifest + cmd.add("--debug-mode"); + } // force package id so that some frameworks build with correct id // disable if user adds own aapt (can't know if they have this feature) if (mPackageId != null && ! customAapt && ! mSharedLibrary) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java index e63a83aa..4e989aa1 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/xml/ResXmlPatcher.java @@ -40,6 +40,35 @@ import java.io.IOException; * @author Connor Tumbleson */ public final class ResXmlPatcher { + + /** + * Removes "debug" tag from file + * + * @param file AndroidManifest file + * @throws AndrolibException + */ + public static void removeApplicationDebugTag(File file) throws AndrolibException { + if (file.exists()) { + try { + Document doc = loadDocument(file); + Node application = doc.getElementsByTagName("application").item(0); + + // load attr + NamedNodeMap attr = application.getAttributes(); + Node debugAttr = attr.getNamedItem("android:debuggable"); + + // remove application:debuggable + if (debugAttr != null) { + attr.removeNamedItem("android:debuggable"); + } + + saveDocument(file, doc); + + } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { + } + } + } + /** * Any @string reference in a value in AndroidManifest.xml will break on * build, thus preventing the application from installing. This is from a bug/error diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/DebugTagRetainedTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/DebugTagRetainedTest.java new file mode 100644 index 00000000..7cde0856 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/DebugTagRetainedTest.java @@ -0,0 +1,90 @@ +/** + * Copyright 2014 Ryszard Wiśniewski + * + * 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 + * + * http://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; + +import brut.androlib.res.util.ExtFile; +import brut.common.BrutException; +import brut.util.OS; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.logging.Logger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Connor Tumbleson + */ +public class DebugTagRetainedTest { + + @BeforeClass + public static void beforeClass() throws Exception, BrutException { + TestUtils.cleanFrameworkFile(); + sTmpDir = new ExtFile(OS.createTempDirectory()); + sTestOrigDir = new ExtFile(sTmpDir, "issue1235-orig"); + sTestNewDir = new ExtFile(sTmpDir, "issue1235-new"); + LOGGER.info("Unpacking issue1235..."); + TestUtils.copyResourceDir(BuildAndDecodeJarTest.class, "brut/apktool/issue1235/", sTestOrigDir); + + LOGGER.info("Building issue1235.apk..."); + ApkOptions apkOptions = new ApkOptions(); + apkOptions.debugMode = true; + + File testApk = new File(sTmpDir, "issue1235.apk"); + new Androlib(apkOptions).build(sTestOrigDir, testApk); + + LOGGER.info("Decoding issue1235.apk..."); + ApkDecoder apkDecoder = new ApkDecoder(testApk); + apkDecoder.setOutDir(sTestNewDir); + apkDecoder.decode(); + } + + @AfterClass + public static void afterClass() throws BrutException { + OS.rmdir(sTmpDir); + } + + @Test + public void buildAndDecodeTest() throws BrutException { + assertTrue(sTestNewDir.isDirectory()); + } + + @Test + public void DebugIsTruePriorToBeingFalseTest() throws BrutException, IOException { + String apk = "issue1235-new"; + + String expected = TestUtils.replaceNewlines("\n" + + "\n" + + " " + + ""); + + byte[] encoded = Files.readAllBytes(Paths.get(sTmpDir + File.separator + apk + File.separator + "AndroidManifest.xml")); + String obtained = TestUtils.replaceNewlines(new String(encoded)); + assertEquals(expected, obtained); + } + + private static ExtFile sTmpDir; + private static ExtFile sTestOrigDir; + private static ExtFile sTestNewDir; + + private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeJarTest.class.getName()); +} \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/ProviderAttributeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/ProviderAttributeTest.java index d8eb7ec8..0d19efef 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/ProviderAttributeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/ProviderAttributeTest.java @@ -66,7 +66,7 @@ public class ProviderAttributeTest { apkDecoder.setOutDir(new File(sTmpDir + File.separator + apk + ".out.two")); apkDecoder.decode(); - String expected = replaceNewlines("\n" + + String expected = TestUtils.replaceNewlines("\n" + "\n" + " \n" + " \n" + @@ -76,7 +76,7 @@ public class ProviderAttributeTest { byte[] encoded = Files.readAllBytes(Paths.get(sTmpDir + File.separator + apk + ".out.two" + File.separator + "AndroidManifest.xml")); - String obtained = replaceNewlines(new String(encoded)); + String obtained = TestUtils.replaceNewlines(new String(encoded)); assertEquals(expected, obtained); } @@ -84,9 +84,5 @@ public class ProviderAttributeTest { return Files.exists(Paths.get(sTmpDir.getAbsolutePath() + File.separator + filepath)); } - private String replaceNewlines(String value) { - return value.replace("\n", "").replace("\r", ""); - } - private static ExtFile sTmpDir; } diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java index c5a9747d..d62d1d8b 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/TestUtils.java @@ -159,4 +159,8 @@ public abstract class TestUtils { return controlType.equals(testType) && control.getAttribute("name").equals(test.getAttribute("name")); } } + + public static String replaceNewlines(String value) { + return value.replace("\n", "").replace("\r", ""); + } } diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/AndroidManifest.xml b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/AndroidManifest.xml new file mode 100644 index 00000000..f770201e --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/apktool.yml b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/apktool.yml new file mode 100644 index 00000000..55bbffe5 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/apktool.yml @@ -0,0 +1,12 @@ +version: 2.0.0 +apkFileName: issue1235.apk +isFrameworkApk: false +usesFramework: + ids: + - 1 +packageInfo: + forced-package-id: '127' +versionInfo: + versionCode: '1' + versionName: '1.0' +compressionType: false \ No newline at end of file diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/res/values/strings.xml b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/res/values/strings.xml new file mode 100644 index 00000000..9999efc0 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/issue1235/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Hello World +