Skip to content

Commit

Permalink
fix: update deps and fix proto resource loading (AAB) (#1129)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 14, 2022
1 parent 5b5524a commit a0f4ccb
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 41 deletions.
9 changes: 4 additions & 5 deletions jadx-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ dependencies {
api(project(':jadx-plugins:jadx-plugins-api'))

implementation 'com.google.code.gson:gson:2.9.0'
implementation 'com.android.tools.build:aapt2-proto:4.2.1-7147631'
constraints {
// Force protobuf version to prevent Java-7 issue
implementation 'com.google.protobuf:protobuf-java:3.11.4'
}

// TODO: move resources decoding to separate plugin module
implementation 'com.android.tools.build:aapt2-proto:7.2.1-7984345'
implementation 'com.google.protobuf:protobuf-java:3.21.2' // forcing latest version

testImplementation 'org.apache.commons:commons-lang3:3.12.0'

Expand Down
28 changes: 14 additions & 14 deletions jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
import jadx.core.utils.Utils;
import jadx.core.utils.android.AndroidResourcesUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.xmlgen.ResTableParser;
import jadx.core.xmlgen.IResParser;
import jadx.core.xmlgen.ResDecoder;
import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.core.xmlgen.entry.ValuesParser;
Expand Down Expand Up @@ -163,23 +164,13 @@ public void addClassNode(ClassNode clsNode) {
}

public void loadResources(List<ResourceFile> resources) {
ResourceFile arsc = null;
for (ResourceFile rf : resources) {
if (rf.getType() == ResourceType.ARSC) {
arsc = rf;
break;
}
}
ResourceFile arsc = getResourceFile(resources);
if (arsc == null) {
LOG.debug("'.arsc' file not found");
return;
}
try {
ResTableParser parser = ResourcesLoader.decodeStream(arsc, (size, is) -> {
ResTableParser tableParser = new ResTableParser(this);
tableParser.decode(is);
return tableParser;
});
IResParser parser = ResourcesLoader.decodeStream(arsc, (size, is) -> ResDecoder.decode(this, arsc, is));
if (parser != null) {
processResources(parser.getResStorage());
updateObfuscatedFiles(parser, resources);
Expand All @@ -189,6 +180,15 @@ public void loadResources(List<ResourceFile> resources) {
}
}

private @Nullable ResourceFile getResourceFile(List<ResourceFile> resources) {
for (ResourceFile rf : resources) {
if (rf.getType() == ResourceType.ARSC) {
return rf;
}
}
return null;
}

public void processResources(ResourceStorage resStorage) {
constValues.setResourcesNames(resStorage.getResourcesNames());
appPackage = resStorage.getAppPackage();
Expand All @@ -209,7 +209,7 @@ public void initClassPath() {
}
}

private void updateObfuscatedFiles(ResTableParser parser, List<ResourceFile> resources) {
private void updateObfuscatedFiles(IResParser parser, List<ResourceFile> resources) {
if (args.isSkipResources()) {
return;
}
Expand Down
13 changes: 13 additions & 0 deletions jadx-core/src/main/java/jadx/core/xmlgen/IResParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package jadx.core.xmlgen;

import java.io.IOException;
import java.io.InputStream;

public interface IResParser {

void decode(InputStream inputStream) throws IOException;

ResourceStorage getResStorage();

String[] getStrings();
}
31 changes: 31 additions & 0 deletions jadx-core/src/main/java/jadx/core/xmlgen/ResDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package jadx.core.xmlgen;

import java.io.IOException;
import java.io.InputStream;

import jadx.api.ResourceFile;
import jadx.api.ResourceType;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.exceptions.JadxRuntimeException;

public class ResDecoder {

public static IResParser decode(RootNode root, ResourceFile resFile, InputStream is) throws IOException {
if (resFile.getType() != ResourceType.ARSC) {
throw new IllegalArgumentException("Unexpected resource type for decode: " + resFile.getType() + ", expect ARSC");
}
IResParser parser = null;
String fileName = resFile.getOriginalName();
if (fileName.endsWith(".arsc")) {
parser = new ResTableParser(root);
}
if (fileName.endsWith(".pb")) {
parser = new ResProtoParser(root);
}
if (parser == null) {
throw new JadxRuntimeException("Unknown type of resource file: " + fileName);
}
parser.decode(is);
return parser;
}
}
30 changes: 20 additions & 10 deletions jadx-core/src/main/java/jadx/core/xmlgen/ResProtoParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
import com.android.aapt.Resources.Styleable;
import com.android.aapt.Resources.Type;
import com.android.aapt.Resources.Value;
import com.google.protobuf.InvalidProtocolBufferException;

import jadx.api.ICodeInfo;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.files.FileUtils;
import jadx.core.xmlgen.entry.EntryConfig;
import jadx.core.xmlgen.entry.ProtoValue;
import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.core.xmlgen.entry.ValuesParser;

public class ResProtoParser {
public class ResProtoParser implements IResParser {
private final RootNode root;
private final ResourceStorage resStorage = new ResourceStorage();

Expand All @@ -38,18 +38,23 @@ public ResProtoParser(RootNode root) {
}

public ResContainer decodeFiles(InputStream inputStream) throws IOException {
ResourceTable table = decodeProto(inputStream);
for (Package p : table.getPackageList()) {
parse(p);
}
resStorage.finish();
decode(inputStream);
ValuesParser vp = new ValuesParser(new String[0], resStorage.getResourcesNames());
ResXmlGen resGen = new ResXmlGen(resStorage, vp);
ICodeInfo content = XmlGenUtils.makeXmlDump(root.makeCodeWriter(), resStorage);
List<ResContainer> xmlFiles = resGen.makeResourcesXml();
return ResContainer.resourceTable("res", xmlFiles, content);
}

@Override
public void decode(InputStream inputStream) throws IOException {
ResourceTable table = ResourceTable.parseFrom(FileUtils.streamToByteArray(inputStream));
for (Package p : table.getPackageList()) {
parse(p);
}
resStorage.finish();
}

private void parse(Package p) {
String name = p.getPackageName();
resStorage.setAppPackage(name);
Expand Down Expand Up @@ -241,8 +246,13 @@ private String parse(Item i) {
return "";
}

private ResourceTable decodeProto(InputStream inputStream)
throws InvalidProtocolBufferException, IOException {
return ResourceTable.parseFrom(XmlGenUtils.readData(inputStream));
@Override
public ResourceStorage getResStorage() {
return resStorage;
}

@Override
public String[] getStrings() {
return new String[0];
}
}
21 changes: 12 additions & 9 deletions jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.core.xmlgen.entry.ValuesParser;

public class ResTableParser extends CommonBinaryParser {
public class ResTableParser extends CommonBinaryParser implements IResParser {
private static final Logger LOG = LoggerFactory.getLogger(ResTableParser.class);

private static final Pattern VALID_RES_KEY_PATTERN = Pattern.compile("[\\w\\d_]+");
Expand Down Expand Up @@ -76,6 +76,7 @@ public ResTableParser(RootNode root, boolean useRawResNames) {
this.useRawResName = useRawResNames;
}

@Override
public void decode(InputStream inputStream) throws IOException {
is = new ParserStream(inputStream);
decodeTableChunk();
Expand All @@ -93,14 +94,6 @@ public ResContainer decodeFiles(InputStream inputStream) throws IOException {
return ResContainer.resourceTable("res", xmlFiles, content);
}

public ResourceStorage getResStorage() {
return resStorage;
}

public String[] getStrings() {
return strings;
}

void decodeTableChunk() throws IOException {
is.checkInt16(RES_TABLE_TYPE, "Not a table chunk");
is.checkInt16(0x000c, "Unexpected table header size");
Expand Down Expand Up @@ -434,4 +427,14 @@ private String readScriptOrVariantChar(int length) throws IOException {
is.skipToPos(start + length, "readScriptOrVariantChar");
return sb.toString();
}

@Override
public ResourceStorage getResStorage() {
return resStorage;
}

@Override
public String[] getStrings() {
return strings;
}
}
2 changes: 1 addition & 1 deletion jadx-gui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies {

implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
implementation "com.github.akarnokd:rxjava2-swing:0.3.7"
implementation 'com.android.tools.build:apksig:4.2.1'
implementation 'com.android.tools.build:apksig:7.2.1'
implementation 'io.github.hqktech:jdwp:1.0'

// TODO: Switch back to upstream once this PR gets merged:
Expand Down
4 changes: 2 additions & 2 deletions jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ public String getSyntaxName() {

case MANIFEST:
case XML:
case ARSC:
return SyntaxConstants.SYNTAX_STYLE_XML;

default:
Expand All @@ -249,8 +250,7 @@ public String getSyntaxName() {
"yaml", SyntaxConstants.SYNTAX_STYLE_YAML,
"properties", SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE,
"ini", SyntaxConstants.SYNTAX_STYLE_INI,
"sql", SyntaxConstants.SYNTAX_STYLE_SQL,
"arsc", SyntaxConstants.SYNTAX_STYLE_XML);
"sql", SyntaxConstants.SYNTAX_STYLE_SQL);

private String getSyntaxByExtension(String name) {
int dot = name.lastIndexOf('.');
Expand Down

0 comments on commit a0f4ccb

Please sign in to comment.