Merge pull request #299 from skylot/public_xml_impl
Generates and saves public.xml in apktool style
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package jadx.core.utils.files;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -14,14 +15,25 @@ public class ZipSecurity {
|
||||
|
||||
private ZipSecurity() {}
|
||||
|
||||
private static boolean isInSubDirectory(File base, File file) {
|
||||
if (file == null) {
|
||||
private static boolean isInSubDirectoryInternal(File baseDir, File canonFile) {
|
||||
if (canonFile == null) {
|
||||
return false;
|
||||
}
|
||||
if (file.equals(base)) {
|
||||
if (canonFile.equals(baseDir)) {
|
||||
return true;
|
||||
}
|
||||
return isInSubDirectory(base, file.getParentFile());
|
||||
return isInSubDirectoryInternal(baseDir, canonFile.getParentFile());
|
||||
}
|
||||
|
||||
public static boolean isInSubDirectory(File baseDir, File file) {
|
||||
try {
|
||||
file = file.getCanonicalFile();
|
||||
baseDir = baseDir.getCanonicalFile();
|
||||
}
|
||||
catch(IOException e) {
|
||||
return false;
|
||||
}
|
||||
return isInSubDirectoryInternal(baseDir, file);
|
||||
}
|
||||
|
||||
// checks that entry name contains no any traversals
|
||||
@@ -30,7 +42,7 @@ public class ZipSecurity {
|
||||
try {
|
||||
File currentPath = new File(".").getCanonicalFile();
|
||||
File canonical = new File(currentPath, entryName).getCanonicalFile();
|
||||
if (isInSubDirectory(currentPath, canonical)) {
|
||||
if (isInSubDirectoryInternal(currentPath, canonical)) {
|
||||
return true;
|
||||
}
|
||||
LOG.error("Path traversal attack detected, invalid name: {}", entryName);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
ResXmlGen resGen = new ResXmlGen(resStorage, vp);
|
||||
|
||||
ResContainer res = ResContainer.multiFile("res");
|
||||
res.setContent(makeDump());
|
||||
res.setContent(makeXmlDump());
|
||||
res.getSubFiles().addAll(resGen.makeResourcesXml());
|
||||
return res;
|
||||
}
|
||||
@@ -82,6 +82,23 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
writer.finish();
|
||||
return writer;
|
||||
}
|
||||
|
||||
public CodeWriter makeXmlDump() {
|
||||
CodeWriter writer = new CodeWriter();
|
||||
writer.startLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
||||
writer.startLine("<resources>");
|
||||
writer.incIndent();
|
||||
|
||||
for (ResourceEntry ri : resStorage.getResources()) {
|
||||
String format = String.format("<public type=\"%s\" name=\"%s\" id=\"%s\" />",
|
||||
ri.getTypeName(), ri.getKeyName(), ri.getId());
|
||||
writer.startLine(format);
|
||||
}
|
||||
writer.decIndent();
|
||||
writer.startLine("</resources>");
|
||||
writer.finish();
|
||||
return writer;
|
||||
}
|
||||
|
||||
public ResourceStorage getResStorage() {
|
||||
return resStorage;
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.api.ResourceType;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.utils.files.ZipSecurity;
|
||||
|
||||
import static jadx.core.utils.files.FileUtils.prepareFile;
|
||||
|
||||
@@ -46,6 +47,7 @@ public class ResourcesSaver implements Runnable {
|
||||
if (subFiles.isEmpty()) {
|
||||
save(rc, outDir);
|
||||
} else {
|
||||
saveToFile(rc, new File(outDir, "res/values/public.xml"));
|
||||
for (ResContainer subFile : subFiles) {
|
||||
saveResources(subFile);
|
||||
}
|
||||
@@ -59,12 +61,29 @@ public class ResourcesSaver implements Runnable {
|
||||
String ext = FilenameUtils.getExtension(outFile.getName());
|
||||
try {
|
||||
outFile = prepareFile(outFile);
|
||||
|
||||
if(!ZipSecurity.isInSubDirectory(outDir, outFile)) {
|
||||
LOG.error("Path traversal attack detected, invalid resource name: {}",
|
||||
outFile.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
ImageIO.write(image, ext, outFile);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to save image: {}", rc.getName(), e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ZipSecurity.isInSubDirectory(outDir, outFile)) {
|
||||
LOG.error("Path traversal attack detected, invalid resource name: {}",
|
||||
rc.getFileName());
|
||||
return;
|
||||
}
|
||||
saveToFile(rc, outFile);
|
||||
}
|
||||
|
||||
private void saveToFile(ResContainer rc, File outFile) {
|
||||
CodeWriter cw = rc.getContent();
|
||||
if (cw != null) {
|
||||
cw.save(outFile);
|
||||
|
||||
Reference in New Issue
Block a user