fix: update deps and fix proto resource loading (AAB) (#1129)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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('.');
|
||||
|
||||
Reference in New Issue
Block a user