fix: update deps and fix proto resource loading (AAB) (#1129)

This commit is contained in:
Skylot
2022-07-14 14:23:30 +01:00
parent 5b5524a7dd
commit a0f4ccb7a4
8 changed files with 97 additions and 41 deletions
+4 -5
View File
@@ -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'
@@ -42,7 +42,8 @@ import jadx.core.utils.StringUtils;
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;
@@ -163,23 +164,13 @@ public class RootNode {
}
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);
@@ -189,6 +180,15 @@ public class RootNode {
}
}
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();
@@ -209,7 +209,7 @@ public class RootNode {
}
}
private void updateObfuscatedFiles(ResTableParser parser, List<ResourceFile> resources) {
private void updateObfuscatedFiles(IResParser parser, List<ResourceFile> resources) {
if (args.isSkipResources()) {
return;
}
@@ -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();
}
@@ -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;
}
}
@@ -20,16 +20,16 @@ import com.android.aapt.Resources.Style;
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();
@@ -38,11 +38,7 @@ public class ResProtoParser {
}
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);
@@ -50,6 +46,15 @@ public class ResProtoParser {
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);
@@ -241,8 +246,13 @@ public class ResProtoParser {
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];
}
}
@@ -24,7 +24,7 @@ import jadx.core.xmlgen.entry.RawValue;
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_]+");
@@ -76,6 +76,7 @@ public class ResTableParser extends CommonBinaryParser {
this.useRawResName = useRawResNames;
}
@Override
public void decode(InputStream inputStream) throws IOException {
is = new ParserStream(inputStream);
decodeTableChunk();
@@ -93,14 +94,6 @@ public class ResTableParser extends CommonBinaryParser {
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");
@@ -434,4 +427,14 @@ public class ResTableParser extends CommonBinaryParser {
is.skipToPos(start + length, "readScriptOrVariantChar");
return sb.toString();
}
@Override
public ResourceStorage getResStorage() {
return resStorage;
}
@Override
public String[] getStrings() {
return strings;
}
}
+1 -1
View File
@@ -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:
@@ -226,6 +226,7 @@ public class JResource extends JLoadableNode {
case MANIFEST:
case XML:
case ARSC:
return SyntaxConstants.SYNTAX_STYLE_XML;
default:
@@ -249,8 +250,7 @@ public class JResource extends JLoadableNode {
"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('.');