Skip to content

Commit ecf09c9

Browse files
committed
* Updated VFS library
* zip unpack algorithm optimized to unpack files in memory structure
1 parent 179e935 commit ecf09c9

21 files changed

+954
-1061
lines changed

core/.idea/workspace.xml

Lines changed: 424 additions & 603 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/main/java/droidefense/analysis/UnpackAnalysis.java

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
import apkr.external.modules.helpers.log4j.Log;
44
import apkr.external.modules.helpers.log4j.LoggerType;
55
import droidefense.analysis.base.AbstractAndroidAnalysis;
6-
import droidefense.handler.*;
7-
import droidefense.handler.base.AbstractHandler;
8-
import droidefense.handler.base.DirScannerFilter;
6+
import droidefense.handler.FileIOHandler;
97
import droidefense.sdk.helpers.DroidDefenseParams;
108
import droidefense.sdk.helpers.Util;
11-
import droidefense.sdk.model.base.APKFile;
129
import droidefense.sdk.model.base.HashedFile;
1310

1411
import java.io.File;
@@ -22,12 +19,10 @@ public final class UnpackAnalysis extends AbstractAndroidAnalysis {
2219
private transient ArrayList<HashedFile> files;
2320

2421
public UnpackAnalysis() {
25-
files = new ArrayList<>();
2622
}
2723

2824
@Override
2925
public boolean analyze() {
30-
AbstractHandler handler;
3126
Log.write(LoggerType.TRACE, "Unpacking .apk...");
3227
//prepare folder
3328
File outputDir = FileIOHandler.getUnpackOutputFile(apkFile);
@@ -36,75 +31,16 @@ public boolean analyze() {
3631
Util.deleteFolder(outputDir);
3732
}
3833
//unpack file
39-
switch (apkFile.getTechnique()) {
40-
case APKFile.APKTOOL: {
41-
//unpacks and decode on the same step
42-
handler = new APKToolHandler(apkFile, outputDir);
43-
handler.doTheJob();
44-
Log.write(LoggerType.TRACE, "Listing unpacked files...");
45-
46-
//enumerate unpacked files and get information
47-
boolean generateHashes = true;
48-
DirScannerHandler dirHandler = new DirScannerHandler(outputDir, generateHashes, new DirScannerFilter() {
49-
@Override
50-
public boolean addFile(File f) {
51-
return true;
52-
}
53-
});
54-
dirHandler.doTheJob();
55-
files = dirHandler.getFiles();
56-
Log.write(LoggerType.TRACE, "Files found: " + files.size());
57-
58-
//save files count
59-
currentProject.setFolderCount(dirHandler.getNfolder());
60-
currentProject.setFilesCount(dirHandler.getNfiles());
61-
positiveMatch = files != null && files.size() > 0;
62-
//SET APP FILES & CALCULATE THEIR HASHES, FUZZING HASH, EXTENSION, SIGNATURE
63-
currentProject.setAppFiles(getFiles());
64-
timeStamp.stop();
65-
break;
66-
}
67-
case APKFile.AXML: {
68-
//only unpacks
69-
handler = new FileUnzipHandler(apkFile, outputDir);
70-
handler.doTheJob();
71-
Log.write(LoggerType.TRACE, "Listing unpacked files...");
72-
73-
//enumerate unpacked files and getAsDotGraph information
74-
boolean generateHashes = true;
75-
DirScannerHandler dirHandler = new DirScannerHandler(outputDir, generateHashes, new DirScannerFilter() {
76-
@Override
77-
public boolean addFile(File f) {
78-
return true;
79-
}
80-
});
81-
handler.doTheJob();
82-
83-
//get extracted files
84-
files = dirHandler.getFiles();
85-
Log.write(LoggerType.TRACE, "Files found: " + files.size());
86-
87-
//save files count
88-
currentProject.setFolderCount(dirHandler.getNfolder());
89-
currentProject.setFilesCount(dirHandler.getNfiles());
90-
positiveMatch = files != null && files.size() > 0;
91-
92-
//SET APP FILES & CALCULATE THEIR HASHES, FUZZING HASH, EXTENSION, SIGNATURE
93-
currentProject.setAppFiles(getFiles());
94-
95-
Log.write(LoggerType.TRACE, "Decoding XML resources");
96-
//decode unpacked files
97-
AXMLDecoderHandler decoder = new AXMLDecoderHandler(files);
98-
decoder.doTheJob();
99-
100-
Log.write(LoggerType.TRACE, "Generating file juiciy information...");
101-
//getAsDotGraph hash, ssdeep, extension,... information
102-
103-
timeStamp.stop();
104-
break;
105-
}
34+
files = apkFile.unpackWithTechnique(outputDir, currentProject);
35+
if (files != null) {
36+
//save files count
37+
positiveMatch = files.size() > 0;
38+
//SET APP FILES & CALCULATE THEIR HASHES, FUZZING HASH, EXTENSION, SIGNATURE
39+
currentProject.setAppFiles(getFiles());
40+
timeStamp.stop();
41+
return true;
10642
}
107-
return true;
43+
return false;
10844
}
10945

11046
@Override
@@ -113,8 +49,6 @@ public String getName() {
11349
}
11450

11551
public ArrayList<HashedFile> getFiles() {
116-
if (files == null)
117-
new ArrayList<>();
11852
return files;
11953
}
12054
}

core/src/main/java/droidefense/analysis/base/PluginAnalysis.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import apkr.external.modules.helpers.enums.ProcessStatus;
44
import apkr.external.modules.helpers.log4j.Log;
55
import apkr.external.modules.helpers.log4j.LoggerType;
6+
import droidefense.sdk.helpers.Util;
67
import droidefense.sdk.model.base.APKFile;
78
import droidefense.sdk.model.base.DroidefenseProject;
89
import droidefense.sdk.model.base.ExecutionTimer;
10+
import droidefense.util.JsonStyle;
911

1012
import java.io.Serializable;
1113

@@ -40,4 +42,12 @@ public void setApk(APKFile apk) {
4042
}
4143

4244
protected abstract String getPluginName();
45+
46+
protected String getResultAsJson() {
47+
return Util.toJson(this, JsonStyle.JSON_COMPRESSED);
48+
}
49+
50+
protected String getResultAsHTML() {
51+
return html;
52+
}
4353
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package droidefense.cli;
2+
3+
import apkr.external.modules.helpers.log4j.Log;
4+
import apkr.external.modules.helpers.log4j.LoggerType;
5+
import droidefense.handler.APKToolHandler;
6+
import droidefense.handler.AXMLDecoderHandler;
7+
import droidefense.handler.DirScannerHandler;
8+
import droidefense.handler.FileUnzipVFSHandler;
9+
import droidefense.handler.base.DirScannerFilter;
10+
import droidefense.sdk.model.base.APKFile;
11+
import droidefense.sdk.model.base.DroidefenseProject;
12+
import droidefense.sdk.model.base.HashedFile;
13+
14+
import java.io.File;
15+
import java.util.ArrayList;
16+
17+
/**
18+
* Created by .local on 14/10/2016.
19+
*/
20+
public enum APKUnpacker {
21+
22+
APKTOOL_UNPACKER {
23+
@Override
24+
public ArrayList<HashedFile> unpackWithTechnique(DroidefenseProject currentProject, APKFile apkFile, File outputDir) {
25+
//unpacks and decode on the same step
26+
APKToolHandler handler = new APKToolHandler(apkFile, outputDir);
27+
handler.doTheJob();
28+
Log.write(LoggerType.TRACE, "Listing unpacked files...");
29+
30+
//enumerate unpacked files and get information
31+
DirScannerHandler dirHandler = new DirScannerHandler(outputDir, GENERATE_HASHES, new DirScannerFilter() {
32+
@Override
33+
public boolean addFile(File f) {
34+
return true;
35+
}
36+
});
37+
dirHandler.doTheJob();
38+
ArrayList<HashedFile> files = dirHandler.getFiles();
39+
Log.write(LoggerType.TRACE, "Files found: " + files.size());
40+
41+
//save metadata
42+
currentProject.setFolderCount(dirHandler.getNfolder());
43+
currentProject.setFilesCount(dirHandler.getNfiles());
44+
45+
return files;
46+
}
47+
}, ZIP_UNPACKER {
48+
@Override
49+
public ArrayList<HashedFile> unpackWithTechnique(DroidefenseProject currentProject, APKFile apkFile, File outputDir) {
50+
//only unpacks
51+
FileUnzipVFSHandler handler = new FileUnzipVFSHandler(currentProject, apkFile);
52+
handler.doTheJob();
53+
Log.write(LoggerType.TRACE, "Listing unpacked files...");
54+
55+
//TODO generate hashes of the files
56+
DirScannerHandler dirHandler = new DirScannerHandler(outputDir, GENERATE_HASHES, new DirScannerFilter() {
57+
@Override
58+
public boolean addFile(File f) {
59+
return true;
60+
}
61+
});
62+
handler.doTheJob();
63+
64+
//get extracted files
65+
ArrayList<HashedFile> files = dirHandler.getFiles();
66+
Log.write(LoggerType.TRACE, "Files found: " + files.size());
67+
68+
Log.write(LoggerType.TRACE, "Decoding XML resources");
69+
//decode unpacked files
70+
AXMLDecoderHandler decoder = new AXMLDecoderHandler(files);
71+
decoder.doTheJob();
72+
73+
//save metadata
74+
currentProject.setFolderCount(dirHandler.getNfolder());
75+
currentProject.setFilesCount(dirHandler.getNfiles());
76+
77+
return files;
78+
}
79+
};
80+
81+
public static final boolean GENERATE_HASHES = true;
82+
83+
public abstract ArrayList<HashedFile> unpackWithTechnique(DroidefenseProject currentProject, APKFile apkFile, File outputDir);
84+
}

core/src/main/java/droidefense/cli/DroidefenseScan.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ public DroidefenseScan(String[] args) throws InvalidScanParametersException {
3939
profilingAlert("activate");
4040
}
4141

42+
//get user selected unpacker. default apktool
43+
String unpackerStr = settings.getUnpacker();
44+
APKUnpacker unpacker = APKUnpacker.APKTOOL_UNPACKER;
45+
if (unpackerStr != null) {
46+
if (unpackerStr.equalsIgnoreCase("apktool")) {
47+
unpacker = APKUnpacker.APKTOOL_UNPACKER;
48+
} else if (unpackerStr.equalsIgnoreCase("zip")) {
49+
unpacker = APKUnpacker.ZIP_UNPACKER;
50+
}
51+
}
52+
4253
if (settings.getVersion()) {
4354
System.out.println("Current version of droidefense: " + InternalConstant.ENGINE_VERSION);
4455
System.out.println("Check out on Github: https://github.com/droidefense");
@@ -47,7 +58,7 @@ public DroidefenseScan(String[] args) throws InvalidScanParametersException {
4758
//security check
4859
File file = settings.getInput();
4960
if (file != null) {
50-
initScan(file);
61+
initScan(file, unpacker);
5162
//profiler wait time | stop
5263
if (settings.profilingEnabled()) {
5364
profilingAlert("deactivate");
@@ -78,15 +89,15 @@ public void stop() {
7889
Log.write(LoggerType.TRACE, "Droidefense scan finished");
7990
}
8091

81-
private void initScan(File file) {
92+
private void initScan(File file, APKUnpacker unpacker) {
8293
//execute only once
8394
try {
8495
loadVariables();
8596
//read dex file from foldex x file y
8697
APKFile apk;
8798

8899
Log.write(LoggerType.TRACE, "Reading .apk from local file");
89-
apk = new APKFile(file, APKFile.APKTOOL);
100+
apk = new APKFile(file, unpacker);
90101

91102
Log.write(LoggerType.TRACE, "Building project");
92103
project = new DroidefenseProject(apk);
@@ -100,6 +111,7 @@ private void initScan(File file) {
100111

101112
//Start analysis
102113
project.analyze(analyzer);
114+
103115
//stop scan
104116
this.stop();
105117
} catch (ConfigFileNotFoundException e) {

core/src/main/java/droidefense/cli/DroidefenseSettings.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public class DroidefenseSettings {
2828
@Parameter(names = {"-p", "--profiling"}, description = "Enable JVM profiling")
2929
private boolean profiling;
3030

31+
@Parameter(names = {"-u", "--unpack"}, description = "Select unpacker: ZIP, APKTOOL")
32+
private String unpacker;
33+
3134
public DroidefenseSettings(String[] args) {
3235
cmm = new JCommander(this);
3336
if (args != null && args.length > 0) {
@@ -62,4 +65,12 @@ public boolean hasFile() {
6265
public boolean profilingEnabled() {
6366
return profiling;
6467
}
68+
69+
public String getUnpacker() {
70+
return unpacker;
71+
}
72+
73+
public void setUnpacker(String unpacker) {
74+
this.unpacker = unpacker;
75+
}
6576
}

core/src/main/java/droidefense/handler/DirScannerHandler.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public DirScannerHandler(File outputDir, boolean generateInformation, DirScanner
2828
this.outputDir = outputDir;
2929
this.generateInformation = generateInformation;
3030
this.filter = filter;
31+
files = new ArrayList<>();
3132
}
3233

3334
@Override
@@ -37,8 +38,6 @@ public boolean doTheJob() {
3738
}
3839

3940
private ArrayList<HashedFile> enumFiles() {
40-
files = new ArrayList<>();
41-
4241
//walk file tree
4342
final Path sourceDir = Paths.get(outputDir.getAbsolutePath());
4443
try {

0 commit comments

Comments
 (0)