Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
bc9164b9
Commit
bc9164b9
authored
Dec 26, 2015
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: refactor file loading, add 'aar' support (fix #95)
parent
7c34be26
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
158 additions
and
118 deletions
+158
-118
JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+1
-6
ResourceType.java
jadx-core/src/main/java/jadx/api/ResourceType.java
+3
-3
ResourcesLoader.java
jadx-core/src/main/java/jadx/api/ResourcesLoader.java
+6
-7
ConvertToClsSet.java
jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java
+7
-19
DexNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
+5
-5
RootNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+12
-9
RenameVisitor.java
...e/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
+6
-4
DexFile.java
jadx-core/src/main/java/jadx/core/utils/files/DexFile.java
+32
-0
FileUtils.java
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
+11
-0
InputFile.java
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
+75
-65
No files found.
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
View file @
bc9164b9
...
...
@@ -116,12 +116,7 @@ public final class JadxDecompiler {
inputFiles
.
clear
();
for
(
File
file
:
files
)
{
try
{
InputFile
inputFile
=
new
InputFile
(
file
);
inputFiles
.
add
(
inputFile
);
while
(
inputFile
.
nextDexIndex
!=
-
1
)
{
inputFile
=
new
InputFile
(
file
,
inputFile
.
nextDexIndex
);
inputFiles
.
add
(
inputFile
);
}
InputFile
.
addFilesFrom
(
file
,
inputFiles
);
}
catch
(
IOException
e
)
{
throw
new
JadxException
(
"Error load file: "
+
file
,
e
);
}
...
...
jadx-core/src/main/java/jadx/api/ResourceType.java
View file @
bc9164b9
package
jadx
.
api
;
public
enum
ResourceType
{
CODE
(
".dex"
,
".class"
),
CODE
(
".dex"
,
".
jar"
,
".
class"
),
MANIFEST
(
"AndroidManifest.xml"
),
XML
(
".xml"
),
// TODO binary or not?
ARSC
(
".arsc"
),
// TODO decompile !!!
XML
(
".xml"
),
ARSC
(
".arsc"
),
FONT
(
".ttf"
),
IMG
(
".png"
,
".gif"
,
".jpg"
),
LIB
(
".so"
),
...
...
jadx-core/src/main/java/jadx/api/ResourcesLoader.java
View file @
bc9164b9
...
...
@@ -85,12 +85,7 @@ public final class ResourcesLoader {
return
decodeStream
(
rf
,
new
ResourceDecoder
()
{
@Override
public
ResContainer
decode
(
long
size
,
InputStream
is
)
throws
IOException
{
if
(
size
>
LOAD_SIZE_LIMIT
)
{
return
ResContainer
.
singleFile
(
rf
.
getName
(),
new
CodeWriter
().
add
(
"File too big, size: "
+
String
.
format
(
"%.2f KB"
,
size
/
1024
.)));
}
return
loadContent
(
jadxRef
,
rf
,
is
);
return
loadContent
(
jadxRef
,
rf
,
is
,
size
);
}
});
}
catch
(
JadxException
e
)
{
...
...
@@ -103,7 +98,7 @@ public final class ResourcesLoader {
}
private
static
ResContainer
loadContent
(
JadxDecompiler
jadxRef
,
ResourceFile
rf
,
InputStream
inputStream
)
throws
IOException
{
InputStream
inputStream
,
long
size
)
throws
IOException
{
switch
(
rf
.
getType
())
{
case
MANIFEST:
case
XML:
...
...
@@ -113,6 +108,10 @@ public final class ResourcesLoader {
case
ARSC:
return
new
ResTableParser
().
decodeFiles
(
inputStream
);
}
if
(
size
>
LOAD_SIZE_LIMIT
)
{
return
ResContainer
.
singleFile
(
rf
.
getName
(),
new
CodeWriter
().
add
(
"File too big, size: "
+
String
.
format
(
"%.2f KB"
,
size
/
1024
.)));
}
return
ResContainer
.
singleFile
(
rf
.
getName
(),
loadToCodeWriter
(
inputStream
));
}
...
...
jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java
View file @
bc9164b9
...
...
@@ -36,12 +36,7 @@ public class ConvertToClsSet {
if
(
f
.
isDirectory
())
{
addFilesFromDirectory
(
f
,
inputFiles
);
}
else
{
InputFile
inputFile
=
new
InputFile
(
f
);
inputFiles
.
add
(
inputFile
);
while
(
inputFile
.
nextDexIndex
!=
-
1
)
{
inputFile
=
new
InputFile
(
f
,
inputFile
.
nextDexIndex
);
inputFiles
.
add
(
inputFile
);
}
InputFile
.
addFilesFrom
(
f
,
inputFiles
);
}
}
for
(
InputFile
inputFile
:
inputFiles
)
{
...
...
@@ -58,8 +53,7 @@ public class ConvertToClsSet {
LOG
.
info
(
"done"
);
}
private
static
void
addFilesFromDirectory
(
File
dir
,
List
<
InputFile
>
inputFiles
)
throws
IOException
,
DecodeException
{
private
static
void
addFilesFromDirectory
(
File
dir
,
List
<
InputFile
>
inputFiles
)
{
File
[]
files
=
dir
.
listFiles
();
if
(
files
==
null
)
{
return
;
...
...
@@ -67,19 +61,13 @@ public class ConvertToClsSet {
for
(
File
file
:
files
)
{
if
(
file
.
isDirectory
())
{
addFilesFromDirectory
(
file
,
inputFiles
);
}
String
fileName
=
file
.
getName
();
if
(
fileName
.
endsWith
(
".dex"
)
||
fileName
.
endsWith
(
".jar"
)
||
fileName
.
endsWith
(
".apk"
))
{
InputFile
inputFile
=
new
InputFile
(
file
);
inputFiles
.
add
(
inputFile
);
while
(
inputFile
.
nextDexIndex
!=
-
1
)
{
inputFile
=
new
InputFile
(
file
,
inputFile
.
nextDexIndex
);
inputFiles
.
add
(
inputFile
);
}
else
{
try
{
InputFile
.
addFilesFrom
(
file
,
inputFiles
);
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Skip file: {}, load error: {}"
,
file
,
e
.
getMessage
());
}
}
}
}
}
jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
View file @
bc9164b9
...
...
@@ -6,7 +6,7 @@ import jadx.core.dex.info.InfoStorage;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.files.
Input
File
;
import
jadx.core.utils.files.
Dex
File
;
import
java.util.ArrayList
;
import
java.util.Collections
;
...
...
@@ -34,7 +34,7 @@ public class DexNode {
private
final
RootNode
root
;
private
final
Dex
dexBuf
;
private
final
Input
File
file
;
private
final
Dex
File
file
;
private
final
List
<
ClassNode
>
classes
=
new
ArrayList
<
ClassNode
>();
private
final
Map
<
ClassInfo
,
ClassNode
>
clsMap
=
new
HashMap
<
ClassInfo
,
ClassNode
>();
...
...
@@ -43,10 +43,10 @@ public class DexNode {
private
final
InfoStorage
infoStorage
=
new
InfoStorage
();
public
DexNode
(
RootNode
root
,
Input
File
input
)
{
public
DexNode
(
RootNode
root
,
Dex
File
input
)
{
this
.
root
=
root
;
this
.
file
=
input
;
this
.
dexBuf
=
input
.
getDexBuf
fer
();
this
.
dexBuf
=
input
.
getDexBuf
();
}
public
void
loadClasses
()
throws
DecodeException
{
...
...
@@ -163,7 +163,7 @@ public class DexNode {
return
infoStorage
;
}
public
InputFile
getInput
File
()
{
public
DexFile
getDex
File
()
{
return
file
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
View file @
bc9164b9
...
...
@@ -9,6 +9,7 @@ import jadx.core.dex.info.ClassInfo;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.files.DexFile
;
import
jadx.core.utils.files.InputFile
;
import
jadx.core.xmlgen.ResContainer
;
import
jadx.core.xmlgen.ResTableParser
;
...
...
@@ -42,16 +43,18 @@ public class RootNode {
this
.
args
=
args
;
}
public
void
load
(
List
<
InputFile
>
dexFiles
)
throws
DecodeException
{
dexNodes
=
new
ArrayList
<
DexNode
>(
dexFiles
.
size
());
for
(
InputFile
dex
:
dexFiles
)
{
DexNode
dexNode
;
try
{
dexNode
=
new
DexNode
(
this
,
dex
);
}
catch
(
Exception
e
)
{
throw
new
DecodeException
(
"Error decode file: "
+
dex
,
e
);
public
void
load
(
List
<
InputFile
>
inputFiles
)
throws
DecodeException
{
dexNodes
=
new
ArrayList
<
DexNode
>();
for
(
InputFile
input
:
inputFiles
)
{
for
(
DexFile
dexFile
:
input
.
getDexFiles
())
{
try
{
LOG
.
debug
(
"Load: {}"
,
dexFile
);
DexNode
dexNode
=
new
DexNode
(
this
,
dexFile
);
dexNodes
.
add
(
dexNode
);
}
catch
(
Exception
e
)
{
throw
new
DecodeException
(
"Error decode file: "
+
dexFile
,
e
);
}
}
dexNodes
.
add
(
dexNode
);
}
for
(
DexNode
dexNode
:
dexNodes
)
{
dexNode
.
loadClasses
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
View file @
bc9164b9
...
...
@@ -14,11 +14,13 @@ import jadx.core.dex.nodes.FieldNode;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.files.InputFile
;
import
java.io.File
;
import
java.util.HashSet
;
import
java.util.Set
;
import
org.apache.commons.io.FilenameUtils
;
import
org.apache.commons.io.IOCase
;
public
class
RenameVisitor
extends
AbstractVisitor
{
...
...
@@ -31,10 +33,10 @@ public class RenameVisitor extends AbstractVisitor {
public
void
init
(
RootNode
root
)
{
IJadxArgs
args
=
root
.
getArgs
();
final
String
firstInputFileName
=
root
.
getDexNodes
().
get
(
0
).
getInputFile
().
getFile
().
getAbsolutePath
();
final
String
inputPath
=
org
.
apache
.
commons
.
io
.
FilenameUtils
.
getFullPathNoEndSeparator
(
firstInputFileName
);
final
String
inputName
=
org
.
apache
.
commons
.
io
.
FilenameUtils
.
getBaseName
(
firstInputFileName
);
InputFile
firstInputFile
=
root
.
getDexNodes
().
get
(
0
).
getDexFile
().
getInputFile
();
final
String
firstInputFileName
=
firstInputFile
.
getFile
().
getAbsolutePath
();
final
String
inputPath
=
FilenameUtils
.
getFullPathNoEndSeparator
(
firstInputFileName
);
final
String
inputName
=
FilenameUtils
.
getBaseName
(
firstInputFileName
);
File
deobfMapFile
=
new
File
(
inputPath
,
inputName
+
".jobf"
);
deobfuscator
=
new
Deobfuscator
(
args
,
root
.
getDexNodes
(),
deobfMapFile
);
...
...
jadx-core/src/main/java/jadx/core/utils/files/DexFile.java
0 → 100644
View file @
bc9164b9
package
jadx
.
core
.
utils
.
files
;
import
com.android.dex.Dex
;
public
class
DexFile
{
private
final
InputFile
inputFile
;
private
final
String
name
;
private
final
Dex
dexBuf
;
public
DexFile
(
InputFile
inputFile
,
String
name
,
Dex
dexBuf
)
{
this
.
inputFile
=
inputFile
;
this
.
name
=
name
;
this
.
dexBuf
=
dexBuf
;
}
public
String
getName
()
{
return
name
;
}
public
Dex
getDexBuf
()
{
return
dexBuf
;
}
public
InputFile
getInputFile
()
{
return
inputFile
;
}
@Override
public
String
toString
()
{
return
inputFile
.
toString
()
+
(
name
.
isEmpty
()
?
""
:
":"
+
name
);
}
}
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
View file @
bc9164b9
...
...
@@ -48,4 +48,15 @@ public class FileUtils {
}
}
}
public
static
File
createTempFile
(
String
suffix
)
{
File
temp
;
try
{
temp
=
File
.
createTempFile
(
"jadx-tmp-"
,
System
.
nanoTime
()
+
"-"
+
suffix
);
temp
.
deleteOnExit
();
}
catch
(
IOException
e
)
{
throw
new
JadxRuntimeException
(
"Failed to create temp file with suffix: "
+
suffix
);
}
return
temp
;
}
}
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
View file @
bc9164b9
...
...
@@ -3,16 +3,19 @@ package jadx.core.utils.files;
import
jadx.core.utils.AsmUtils
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.jar.JarOutputStream
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipFile
;
import
org.apache.commons.io.IOUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -22,49 +25,95 @@ public class InputFile {
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
InputFile
.
class
);
private
final
File
file
;
private
final
Dex
dexBuf
;
public
int
nextDexIndex
=
-
1
;
private
final
int
dexIndex
;
private
final
List
<
DexFile
>
dexFiles
=
new
ArrayList
<
DexFile
>();
public
InputFile
(
File
file
)
throws
IOException
,
DecodeException
{
this
(
file
,
0
);
public
static
void
addFilesFrom
(
File
file
,
List
<
InputFile
>
list
)
throws
IOException
,
DecodeException
{
InputFile
inputFile
=
new
InputFile
(
file
);
inputFile
.
searchDexFiles
();
list
.
add
(
inputFile
);
}
p
ublic
InputFile
(
File
file
,
int
dexIndex
)
throws
IOException
,
DecodeException
{
p
rivate
InputFile
(
File
file
)
throws
IOException
,
DecodeException
{
if
(!
file
.
exists
())
{
throw
new
IOException
(
"File not found: "
+
file
.
getAbsolutePath
());
}
this
.
dexIndex
=
dexIndex
;
this
.
file
=
file
;
this
.
dexBuf
=
loadDexBuffer
();
}
private
Dex
loadDexBuffer
()
throws
IOException
,
DecodeException
{
private
void
searchDexFiles
()
throws
IOException
,
DecodeException
{
String
fileName
=
file
.
getName
();
if
(
fileName
.
endsWith
(
".dex"
))
{
return
new
Dex
(
file
);
addDexFile
(
new
Dex
(
file
));
return
;
}
if
(
fileName
.
endsWith
(
".class"
))
{
return
loadFromClassFile
(
file
);
addDexFile
(
loadFromClassFile
(
file
));
return
;
}
if
(
fileName
.
endsWith
(
".apk"
)
||
fileName
.
endsWith
(
".zip"
))
{
Dex
dex
=
loadFromZip
(
this
,
file
);
if
(
dex
==
null
)
{
throw
new
IOException
(
"File 'classes.dex' not found in file: "
+
file
);
}
return
dex
;
loadFromZip
(
".dex"
);
return
;
}
if
(
fileName
.
endsWith
(
".jar"
))
{
// check if jar contains 'classes.dex'
Dex
dex
=
loadFromZip
(
this
,
file
);
if
(
dex
!=
null
)
{
return
dex
;
// check if jar contains '.dex' files
if
(
loadFromZip
(
".dex"
))
{
return
;
}
return
loadFromJar
(
file
);
addDexFile
(
loadFromJar
(
file
));
return
;
}
if
(
fileName
.
endsWith
(
".aar"
))
{
loadFromZip
(
".jar"
);
return
;
}
throw
new
DecodeException
(
"Unsupported input file format: "
+
file
);
}
private
void
addDexFile
(
Dex
dexBuf
)
throws
IOException
{
addDexFile
(
""
,
dexBuf
);
}
private
void
addDexFile
(
String
fileName
,
Dex
dexBuf
)
throws
IOException
{
dexFiles
.
add
(
new
DexFile
(
this
,
fileName
,
dexBuf
));
}
private
boolean
loadFromZip
(
String
ext
)
throws
IOException
,
DecodeException
{
ZipFile
zf
=
new
ZipFile
(
file
);
int
index
=
0
;
while
(
true
)
{
String
entryName
=
"classes"
+
(
index
==
0
?
""
:
index
)
+
ext
;
ZipEntry
entry
=
zf
.
getEntry
(
entryName
);
if
(
entry
==
null
)
{
break
;
}
InputStream
inputStream
=
zf
.
getInputStream
(
entry
);
try
{
if
(
ext
.
equals
(
".dex"
))
{
addDexFile
(
entryName
,
new
Dex
(
inputStream
));
}
else
if
(
ext
.
equals
(
".jar"
))
{
File
jarFile
=
FileUtils
.
createTempFile
(
entryName
);
FileOutputStream
fos
=
new
FileOutputStream
(
jarFile
);
try
{
IOUtils
.
copy
(
inputStream
,
fos
);
}
finally
{
fos
.
close
();
}
addDexFile
(
entryName
,
loadFromJar
(
jarFile
));
}
else
{
throw
new
JadxRuntimeException
(
"Unexpected extension in zip: "
+
ext
);
}
}
finally
{
inputStream
.
close
();
}
index
++;
if
(
index
==
1
)
{
index
=
2
;
}
}
zf
.
close
();
return
index
>
0
;
}
private
static
Dex
loadFromJar
(
File
jarFile
)
throws
DecodeException
{
try
{
LOG
.
info
(
"converting to dex: {} ..."
,
jarFile
.
getName
());
...
...
@@ -81,47 +130,8 @@ public class InputFile {
}
}
private
static
Dex
loadFromZip
(
InputFile
ipf
,
File
file
)
throws
IOException
{
ZipFile
zf
=
new
ZipFile
(
file
);
String
dexName
=
"classes.dex"
;
String
futureDexName
=
"classes2.dex"
;
if
(
ipf
.
dexIndex
!=
0
)
{
dexName
=
"classes"
+
ipf
.
dexIndex
+
".dex"
;
futureDexName
=
"classes"
+
(
ipf
.
dexIndex
+
1
)
+
".dex"
;
}
ZipEntry
dex
=
zf
.
getEntry
(
dexName
);
if
(
dex
==
null
)
{
zf
.
close
();
return
null
;
}
try
{
ZipEntry
futureDex
=
zf
.
getEntry
(
futureDexName
);
if
(
futureDex
!=
null
)
{
ipf
.
nextDexIndex
=
ipf
.
dexIndex
==
0
?
2
:
ipf
.
dexIndex
+
1
;
}
}
catch
(
Exception
ex
)
{
}
ByteArrayOutputStream
bytesOut
=
new
ByteArrayOutputStream
();
InputStream
in
=
null
;
try
{
in
=
zf
.
getInputStream
(
dex
);
byte
[]
buffer
=
new
byte
[
8192
];
int
count
;
while
((
count
=
in
.
read
(
buffer
))
!=
-
1
)
{
bytesOut
.
write
(
buffer
,
0
,
count
);
}
}
finally
{
if
(
in
!=
null
)
{
in
.
close
();
}
zf
.
close
();
}
return
new
Dex
(
bytesOut
.
toByteArray
());
}
private
static
Dex
loadFromClassFile
(
File
file
)
throws
IOException
,
DecodeException
{
File
outFile
=
File
.
createTempFile
(
"jadx-tmp-"
,
System
.
nanoTime
()
+
".jar"
);
outFile
.
deleteOnExit
();
File
outFile
=
FileUtils
.
createTempFile
(
"cls.jar"
);
FileOutputStream
out
=
null
;
JarOutputStream
jo
=
null
;
try
{
...
...
@@ -147,12 +157,12 @@ public class InputFile {
return
file
;
}
public
Dex
getDexBuffer
()
{
return
dex
Buf
;
public
List
<
DexFile
>
getDexFiles
()
{
return
dex
Files
;
}
@Override
public
String
toString
()
{
return
file
.
toString
();
return
file
.
getAbsolutePath
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment