Skip to content

Commit

Permalink
add info feature
Browse files Browse the repository at this point in the history
  • Loading branch information
REAndroid committed May 31, 2023
1 parent 0d1d68a commit fd780b4
Show file tree
Hide file tree
Showing 23 changed files with 2,535 additions and 615 deletions.
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# APKEditor
### Powerful android apk resources editor
This tool uses [ARSCLib](https://github.com/REAndroid/ARSCLib) to edit any apk resources and has five main features
This tool uses [ARSCLib](https://github.com/REAndroid/ARSCLib) to edit any apk resources and has six main features

<details><summary><code>java -jar APKEditor.jar <b>-h</b></code></summary>

Expand All @@ -20,6 +20,7 @@ Usage:
3) m | merge - Merges split apk files from directory or XAPK, APKM, APKS ...
4) x | refactor - Refactors obfuscated resource names
5) p | protect - Protects/Obfuscates apk resource
6) info - Prints information of apk
run with <command> -h to get detailed help about each command
```
Expand Down Expand Up @@ -122,7 +123,7 @@ $ java -jar APKEditor.jar x -i input.apk

</details>

#### 5- Protect (⭐NEW⭐)
#### 5- Protect
Protects apk resources against almost all known decompile/modify tools.
<details> <summary><code>java -jar APKEditor.jar <b>p</b> -i path/to/input.apk</code></summary>

Expand All @@ -143,7 +144,30 @@ Protects apk resources against almost all known decompile/modify tools.
```

</details>


#### 6- Info (⭐NEW⭐)
Prints/dumps from basic up to detailed information of apk.
<details> <summary><code>java -jar APKEditor.jar <b>info</b> -v -resources -i input.apk </code></summary>

```ShellSession
Package name=com.mypackage id=0x7f
type string id=1 entryCount=1
resource 0x7f010000 string/app_name
() My Application
(-de) Meine Bewerbung
(-ru-rRU) Мое заявление
type mipmap id=2 entryCount=1
resource 0x7f020000 mipmap/ic_launcher_round
() res/mipmap/ic_launcher_round.png
type drawable id=3 entryCount=1
resource 0x7f030000 drawable/ic_launcher
() #006400

```

</details>


---

***Build executable jar***
Expand Down
Binary file modified libs/ARSCLib.jar
Binary file not shown.
92 changes: 71 additions & 21 deletions src/main/java/com/reandroid/apkeditor/BaseCommand.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,81 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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.
*/
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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 com.reandroid.apkeditor;

import com.reandroid.apk.APKLogger;
import com.reandroid.archive.APKArchive;
import com.reandroid.apk.ApkModule;
import com.reandroid.commons.utils.log.Logger;

import java.io.IOException;
import java.util.regex.Pattern;

public class BaseCommand {
public class BaseCommand implements APKLogger {
private String mLogTag;
private boolean mEnableLog;
public BaseCommand(){
mLogTag = "";
mEnableLog = true;
}
public void run() throws IOException{

protected static void removeSignature(ApkModule module){
APKArchive archive = module.getApkArchive();
archive.removeAll(Pattern.compile("^META-INF/(?!services/).*"));
archive.remove("stamp-cert-sha256");
}
}

protected void setLogTag(String tag) {
if(tag == null){
tag = "";
}
this.mLogTag = tag;
}
public void setEnableLog(boolean enableLog) {
this.mEnableLog = enableLog;
}
@Override
public void logMessage(String msg) {
if(!mEnableLog){
return;
}
Logger.i(mLogTag + msg);
}
@Override
public void logError(String msg, Throwable tr) {
if(!mEnableLog){
return;
}
Logger.e(mLogTag + msg, tr);
}
@Override
public void logVerbose(String msg) {
if(!mEnableLog){
return;
}
Logger.sameLine(mLogTag + msg);
}
public void logWarn(String msg) {
Logger.e(mLogTag + msg);
}

protected static void clearMeta(ApkModule module){
removeSignature(module);
module.setApkSignatureBlock(null);
}
protected static void removeSignature(ApkModule module){
APKArchive archive = module.getApkArchive();
archive.removeAll(Pattern.compile("^META-INF/.+\\.(([MS]F)|(RSA))"));
archive.remove("stamp-cert-sha256");
}
}

68 changes: 41 additions & 27 deletions src/main/java/com/reandroid/apkeditor/Main.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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.
*/
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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 com.reandroid.apkeditor;

import com.reandroid.apkeditor.cloner.Cloner;
import com.reandroid.apkeditor.compile.Builder;
import com.reandroid.apkeditor.decompile.Decompiler;
import com.reandroid.apkeditor.info.Info;
import com.reandroid.apkeditor.merge.Merger;
import com.reandroid.apkeditor.protect.Protector;
import com.reandroid.apkeditor.refactor.Refactor;
import com.reandroid.apkeditor.utils.StringHelper;
import com.reandroid.commons.command.ARGException;
import com.reandroid.apk.xmlencoder.EncodeException;

Expand Down Expand Up @@ -77,6 +80,14 @@ private static void execute(String command, String[] args) throws ARGException,
Protector.execute(args);
return;
}
if(Cloner.isCommand(command)){
Cloner.execute(args);
return;
}
if(Info.isCommand(command)){
Info.execute(args);
return;
}
throw new ARGException("Unknown command: "+command);
}
private static String getHelp(){
Expand All @@ -85,18 +96,21 @@ private static String getHelp(){
builder.append("\nUsage: \n");
builder.append(" java -jar ").append(APKEditor.getJarName());
builder.append(" <command> <args>");
builder.append("\n commands: ");
builder.append("\n 1) ").append(Decompiler.ARG_SHORT).append(" | ").append(Decompiler.ARG_LONG);
builder.append(" - ").append(Decompiler.DESCRIPTION);
builder.append("\n 2) ").append(Builder.ARG_SHORT).append(" | ").append(Builder.ARG_LONG);
builder.append(" - ").append(Builder.DESCRIPTION);
builder.append("\n 3) ").append(Merger.ARG_SHORT).append(" | ").append(Merger.ARG_LONG);
builder.append(" - ").append(Merger.DESCRIPTION);
builder.append("\n 4) ").append(Refactor.ARG_SHORT).append(" | ").append(Refactor.ARG_LONG);
builder.append(" - ").append(Refactor.DESCRIPTION);
builder.append("\n 5) ").append(Protector.ARG_SHORT).append(" | ").append(Protector.ARG_LONG);
builder.append(" - ").append(Protector.DESCRIPTION);
builder.append("\n run with <command> -h to get detailed help about each command");
builder.append("\n commands: \n");
String[][] table = new String[][]{
new String[]{" 1) " + Decompiler.ARG_SHORT + " | " + Decompiler.ARG_LONG, Decompiler.DESCRIPTION},
new String[]{" 2) " + Builder.ARG_SHORT + " | " + Builder.ARG_LONG, Builder.DESCRIPTION},
new String[]{" 3) " + Merger.ARG_SHORT + " | " + Merger.ARG_LONG, Merger.DESCRIPTION},
new String[]{" 4) " + Refactor.ARG_SHORT + " | " + Refactor.ARG_LONG, Refactor.DESCRIPTION},
new String[]{" 5) " + Protector.ARG_SHORT + " | " + Protector.ARG_LONG, Protector.DESCRIPTION},
//new String[]{" 6) " + Cloner.ARG_SHORT + " | " + Cloner.ARG_LONG, Cloner.DESCRIPTION},
new String[]{" 6) " + Info.ARG_SHORT, Info.DESCRIPTION}
};

StringHelper.printTwoColumns(builder, " ", " - ", Options.PRINT_WIDTH, table);

builder.append("\n\n run with <command> -h to get detailed help about each command\n");

return builder.toString();
}
private static String getWelcome(){
Expand Down
64 changes: 46 additions & 18 deletions src/main/java/com/reandroid/apkeditor/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,8 @@ protected void parseFrameworkVersion(String[] args) throws ARGException {
}
}
protected void parseType(String[] args) throws ARGException {
this.type = parseArgValue(ARG_type, true, args);
if(type == null){
type = TYPE_JSON;
return;
}
type = type.trim().toLowerCase();
if(TYPE_JSON.equals(type)
|| TYPE_XML.equals(type)
|| TYPE_SIG.equals(type)){
return;
}
throw new ARGException("Unknown decompile type: "+type);
String[] choices = new String[]{TYPE_JSON, TYPE_XML, TYPE_SIG};
this.type = parseType(ARG_type, args, choices, TYPE_JSON);
}
protected void parseSignaturesDir(String[] args) throws ARGException {
this.signaturesDirectory = parseFile(ARG_sig, args);
Expand All @@ -72,6 +62,32 @@ protected void checkUnknownOptions(String[] args) throws ARGException {
}
throw new ARGException("Unknown option: "+args[0]);
}

protected String parseType(String argSwitch, String[] args, String[] availableTypes, String def) throws ARGException {
String type = parseArgValue(argSwitch, args);
if(type == null){
return def;
}
type = type.trim();
String typeLower = type.toLowerCase();
for(String choice : availableTypes){
if(typeLower.equals(choice)){
return typeLower;
}
}
StringBuilder builder = new StringBuilder();
builder.append("Unknown type: '");
builder.append(type);
builder.append("' , must be one of {");
for(int i = 0; i < availableTypes.length; i++){
if(i != 0){
builder.append(", ");
}
builder.append(availableTypes[i]);
}
builder.append("}");
throw new ARGException(builder.toString());
}
protected String parseArgValue(String argSwitch, String[] args) throws ARGException {
return parseArgValue(argSwitch, true, args);
}
Expand Down Expand Up @@ -132,7 +148,16 @@ protected File parseFile(String argSwitch, String[] args) throws ARGException {
}
return null;
}
protected boolean containsArg(String argSwitch, boolean ignore_case, String[] args) throws ARGException {
protected boolean containsArg(String argSwitch, String[] args) {
return containsArg(argSwitch, true, args, false);
}
protected boolean containsArg(String argSwitch, String[] args, boolean def) {
return containsArg(argSwitch, true, args, def);
}
protected boolean containsArg(String argSwitch, boolean ignore_case, String[] args){
return containsArg(argSwitch, ignore_case, args, false);
}
protected boolean containsArg(String argSwitch, boolean ignore_case, String[] args, boolean def) {
if(ignore_case){
argSwitch=argSwitch.toLowerCase();
}
Expand All @@ -151,9 +176,14 @@ protected boolean containsArg(String argSwitch, boolean ignore_case, String[] ar
return true;
}
}
return false;
return def;
}

public static final int PRINT_WIDTH = 75;

protected static final String ARG_ALL_help = "-h|-help";
protected static final String ARG_DESC_help = "Prints this help";

protected static final String ARG_output="-o";
protected static final String ARG_DESC_output="output path";
protected static final String ARG_input="-i";
Expand All @@ -173,12 +203,10 @@ protected boolean containsArg(String argSwitch, boolean ignore_case, String[] ar
protected static final String ARG_DESC_framework_version = "preferred framework version number";
public static final String ARG_type = "-t";

public static final String ARG_DESC_type = "Decode types: \n1) json \n2) xml \n3) sig \n default=json" +
"\n * Output directory contains \n a) res package directory(s) name={index number}-{package name}" +
"\n b) root: directory of raw files like dex, assets, lib ... \n c) AndroidManifest.xml";

public static final String TYPE_SIG = "sig";
public static final String TYPE_JSON = "json";
public static final String TYPE_XML = "xml";
public static final String TYPE_TEXT = "text";

protected static final String LINE = " ------------------------------------------------------------------------";
}
Loading

0 comments on commit fd780b4

Please sign in to comment.