Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
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
c5c4499a
Commit
c5c4499a
authored
Feb 10, 2015
by
skylot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #49 from NeoSpb/basic_deobfuscation
core: added deobfuscation feature (basic functionality)
parents
883429fa
30138f7a
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
794 additions
and
13 deletions
+794
-13
JadxCLIArgs.java
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+32
-0
build.gradle
jadx-core/build.gradle
+1
-0
DefaultJadxArgs.java
jadx-core/src/main/java/jadx/api/DefaultJadxArgs.java
+20
-0
IJadxArgs.java
jadx-core/src/main/java/jadx/api/IJadxArgs.java
+8
-0
JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+47
-0
JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+5
-4
JavaPackage.java
jadx-core/src/main/java/jadx/api/JavaPackage.java
+3
-1
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+7
-5
MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+2
-1
DefaultDeobfuscator.java
...re/src/main/java/jadx/core/deobf/DefaultDeobfuscator.java
+415
-0
Deobfuscator.java
jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
+37
-0
IDeobfuscator.java
jadx-core/src/main/java/jadx/core/deobf/IDeobfuscator.java
+18
-0
PackageNode.java
jadx-core/src/main/java/jadx/core/deobf/PackageNode.java
+147
-0
StubDeobfuscator.java
...-core/src/main/java/jadx/core/deobf/StubDeobfuscator.java
+48
-0
DotGraphVisitor.java
...src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
+2
-1
SaveCode.java
jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
+2
-1
No files found.
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
View file @
c5c4499a
...
...
@@ -50,6 +50,18 @@ public final class JadxCLIArgs implements IJadxArgs {
@Parameter
(
names
=
{
"-v"
,
"--verbose"
},
description
=
"verbose output"
)
protected
boolean
verbose
=
false
;
@Parameter
(
names
=
{
"--deobf"
},
description
=
"activate deobfuscation"
)
protected
boolean
deobfuscationOn
=
false
;
@Parameter
(
names
=
{
"--deobf-min"
},
description
=
"min length of name"
)
protected
int
deobfuscationMinLength
=
2
;
@Parameter
(
names
=
{
"--deobf-max"
},
description
=
"max length of name"
)
protected
int
deobfuscationMaxLength
=
40
;
@Parameter
(
names
=
{
"--deobf-rewrite-cfg"
},
description
=
"force to save deobfuscation map"
)
protected
boolean
deobfuscationForceSave
=
false
;
@Parameter
(
names
=
{
"-h"
,
"--help"
},
description
=
"print this help"
,
help
=
true
)
protected
boolean
printHelp
=
false
;
...
...
@@ -209,4 +221,24 @@ public final class JadxCLIArgs implements IJadxArgs {
public
boolean
isVerbose
()
{
return
verbose
;
}
@Override
public
boolean
isDeobfuscationOn
()
{
return
deobfuscationOn
;
}
@Override
public
int
getDeobfuscationMinLength
()
{
return
deobfuscationMinLength
;
}
@Override
public
int
getDeobfuscationMaxLength
()
{
return
deobfuscationMaxLength
;
}
@Override
public
boolean
isDeobfuscationForceSave
()
{
return
deobfuscationForceSave
;
}
}
jadx-core/build.gradle
View file @
c5c4499a
...
...
@@ -6,6 +6,7 @@ dependencies {
runtime
files
(
jadxClasspath
)
compile
files
(
'lib/dx-1.10.jar'
)
compile
'commons-io:commons-io:2.4'
compile
'org.ow2.asm:asm:5.0.3'
compile
'com.intellij:annotations:12.0'
...
...
jadx-core/src/main/java/jadx/api/DefaultJadxArgs.java
View file @
c5c4499a
...
...
@@ -48,4 +48,24 @@ public class DefaultJadxArgs implements IJadxArgs {
public
boolean
isSkipSources
()
{
return
false
;
}
@Override
public
boolean
isDeobfuscationOn
()
{
return
false
;
}
@Override
public
int
getDeobfuscationMinLength
()
{
return
Integer
.
MIN_VALUE
+
1
;
}
@Override
public
int
getDeobfuscationMaxLength
()
{
return
Integer
.
MAX_VALUE
-
1
;
}
@Override
public
boolean
isDeobfuscationForceSave
()
{
return
false
;
}
}
jadx-core/src/main/java/jadx/api/IJadxArgs.java
View file @
c5c4499a
...
...
@@ -20,4 +20,12 @@ public interface IJadxArgs {
boolean
isSkipResources
();
boolean
isSkipSources
();
boolean
isDeobfuscationOn
();
int
getDeobfuscationMinLength
();
int
getDeobfuscationMaxLength
();
boolean
isDeobfuscationForceSave
();
}
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
View file @
c5c4499a
...
...
@@ -3,6 +3,8 @@ package jadx.api;
import
jadx.core.Jadx
;
import
jadx.core.ProcessClass
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.deobf.DefaultDeobfuscator
;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.RootNode
;
...
...
@@ -253,6 +255,51 @@ public final class JadxDecompiler {
root
=
new
RootNode
();
LOG
.
info
(
"loading ..."
);
root
.
load
(
inputFiles
);
if
(
args
.
isDeobfuscationOn
())
{
final
String
firstInputFileName
=
inputFiles
.
get
(
0
).
getFile
().
getAbsolutePath
();
final
String
inputPath
=
org
.
apache
.
commons
.
io
.
FilenameUtils
.
getFullPathNoEndSeparator
(
firstInputFileName
);
final
String
inputName
=
org
.
apache
.
commons
.
io
.
FilenameUtils
.
getBaseName
(
firstInputFileName
);
final
File
deobfuscationMapFile
=
new
File
(
inputPath
,
inputName
+
".jobf"
);
DefaultDeobfuscator
deobfuscator
=
new
DefaultDeobfuscator
();
if
(
deobfuscationMapFile
.
exists
())
{
try
{
deobfuscator
.
load
(
deobfuscationMapFile
);
}
catch
(
IOException
e
)
{
LOG
.
error
(
"Failed to load deobfuscation map file '{}'"
,
deobfuscationMapFile
.
getAbsolutePath
());
}
}
deobfuscator
.
setInputData
(
root
.
getDexNodes
());
deobfuscator
.
setMinNameLength
(
args
.
getDeobfuscationMinLength
());
deobfuscator
.
setMaxNameLength
(
args
.
getDeobfuscationMaxLength
());
deobfuscator
.
process
();
try
{
if
(
deobfuscationMapFile
.
exists
())
{
if
(
args
.
isDeobfuscationForceSave
())
{
deobfuscator
.
save
(
deobfuscationMapFile
);
}
else
{
LOG
.
warn
(
"Deobfuscation map file '{}' exists. Use command line option '--deobf=rewrite-cfg'"
+
" to rewrite it"
,
deobfuscationMapFile
.
getAbsolutePath
());
}
}
else
{
deobfuscator
.
save
(
deobfuscationMapFile
);
}
}
catch
(
IOException
e
)
{
LOG
.
error
(
"Failed to load deobfuscation map file '{}'"
,
deobfuscationMapFile
.
getAbsolutePath
());
}
Deobfuscator
.
setDeobfuscator
(
deobfuscator
);
}
root
.
loadResources
(
getResources
());
root
.
initAppResClass
();
}
...
...
jadx-core/src/main/java/jadx/api/JavaClass.java
View file @
c5c4499a
package
jadx
.
api
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.nodes.LineAttrNode
;
import
jadx.core.dex.info.AccessInfo
;
...
...
@@ -150,16 +151,16 @@ public final class JavaClass implements JavaNode {
@Override
public
String
getName
()
{
return
cls
.
getShortName
(
);
return
Deobfuscator
.
instance
().
getClassShortName
(
cls
);
}
@Override
public
String
getFullName
()
{
return
cls
.
getFullName
(
);
return
Deobfuscator
.
instance
().
getClassFullName
(
cls
);
}
public
String
getPackage
()
{
return
cls
.
getPackage
(
);
return
Deobfuscator
.
instance
().
getPackageName
(
cls
.
getPackage
()
);
}
@Override
...
...
@@ -202,6 +203,6 @@ public final class JavaClass implements JavaNode {
@Override
public
String
toString
()
{
return
getFullName
()
;
return
cls
.
getFullName
()
+
"[ "
+
getFullName
()
+
" ]"
;
}
}
jadx-core/src/main/java/jadx/api/JavaPackage.java
View file @
c5c4499a
package
jadx
.
api
;
import
jadx.core.deobf.Deobfuscator
;
import
java.util.List
;
import
org.jetbrains.annotations.NotNull
;
...
...
@@ -9,7 +11,7 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
private
final
List
<
JavaClass
>
classes
;
JavaPackage
(
String
name
,
List
<
JavaClass
>
classes
)
{
this
.
name
=
name
;
this
.
name
=
Deobfuscator
.
instance
().
getPackageName
(
name
)
;
this
.
classes
=
classes
;
}
...
...
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
c5c4499a
...
...
@@ -2,6 +2,7 @@ package jadx.core.codegen;
import
jadx.api.IJadxArgs
;
import
jadx.core.Consts
;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AttrNode
;
...
...
@@ -80,14 +81,14 @@ public class ClassGen {
CodeWriter
clsCode
=
new
CodeWriter
();
if
(!
""
.
equals
(
cls
.
getPackage
()))
{
clsCode
.
add
(
"package "
).
add
(
cls
.
getPackage
(
)).
add
(
';'
);
clsCode
.
add
(
"package "
).
add
(
Deobfuscator
.
instance
().
getPackageName
(
cls
.
getPackage
()
)).
add
(
';'
);
clsCode
.
newLine
();
}
int
importsCount
=
imports
.
size
();
if
(
importsCount
!=
0
)
{
List
<
String
>
sortImports
=
new
ArrayList
<
String
>(
importsCount
);
for
(
ClassInfo
ic
:
imports
)
{
sortImports
.
add
(
ic
.
getFullName
(
));
sortImports
.
add
(
Deobfuscator
.
instance
().
getClassFullName
(
ic
));
}
Collections
.
sort
(
sortImports
);
...
...
@@ -142,7 +143,7 @@ public class ClassGen {
}
else
{
clsCode
.
add
(
"class "
);
}
clsCode
.
add
(
cls
.
getShortName
(
));
clsCode
.
add
(
Deobfuscator
.
instance
().
getClassShortName
(
cls
));
addGenericMap
(
clsCode
,
cls
.
getGenericMap
());
clsCode
.
add
(
' '
);
...
...
@@ -453,7 +454,8 @@ public class ClassGen {
if
(
fallback
)
{
return
fullName
;
}
String
shortName
=
classInfo
.
getShortName
();
fullName
=
Deobfuscator
.
instance
().
getClassFullName
(
classInfo
);
String
shortName
=
Deobfuscator
.
instance
().
getClassShortName
(
classInfo
);
if
(
classInfo
.
getPackage
().
equals
(
"java.lang"
)
&&
classInfo
.
getParentClass
()
==
null
)
{
return
shortName
;
}
else
{
...
...
@@ -474,7 +476,7 @@ public class ClassGen {
return
fullName
;
}
if
(
classInfo
.
getPackage
().
equals
(
useCls
.
getPackage
()))
{
fullName
=
classInfo
.
getNameWithoutPackage
(
);
fullName
=
Deobfuscator
.
instance
().
getClassName
(
classInfo
);
}
for
(
ClassInfo
importCls
:
getImports
())
{
if
(!
importCls
.
equals
(
classInfo
)
...
...
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
View file @
c5c4499a
package
jadx
.
core
.
codegen
;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.annotations.MethodParameters
;
...
...
@@ -85,7 +86,7 @@ public class MethodGen {
code
.
add
(
' '
);
}
if
(
mth
.
getAccessFlags
().
isConstructor
())
{
code
.
add
(
classGen
.
getClassNode
().
getShortName
(
));
// constructor
code
.
add
(
Deobfuscator
.
instance
().
getClassShortName
(
classGen
.
getClassNode
()
));
// constructor
}
else
{
classGen
.
useType
(
code
,
mth
.
getReturnType
());
code
.
add
(
' '
);
...
...
jadx-core/src/main/java/jadx/core/deobf/DefaultDeobfuscator.java
0 → 100644
View file @
c5c4499a
package
jadx
.
core
.
deobf
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.DexNode
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TreeSet
;
import
org.apache.commons.io.FileUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
public
class
DefaultDeobfuscator
implements
IDeobfuscator
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
DefaultDeobfuscator
.
class
);
private
static
final
boolean
DEBUG
=
false
;
public
static
final
char
classNameSepearator
=
'.'
;
private
int
maxLength
=
40
;
private
int
minLength
=
2
;
private
int
pkgIndex
=
0
;
private
int
clsIndex
=
0
;
private
List
<
DexNode
>
dexNodes
;
private
static
PackageNode
rootPackage
=
new
PackageNode
(
""
);
private
static
final
String
MAP_FILE_CHARSET
=
"UTF-8"
;
/**
* Gets package node for full package name
*
* @param fullPkgName full package name
* @param _creat if {@code true} then will create all absent objects
*
* @return package node object or {@code null} if no package found and <b>_creat</b> set to {@code false}
*/
public
static
PackageNode
getPackageNode
(
String
fullPkgName
,
boolean
_creat
)
{
if
(
fullPkgName
.
isEmpty
()
||
fullPkgName
.
equals
(
classNameSepearator
))
{
return
rootPackage
;
}
PackageNode
result
=
rootPackage
;
PackageNode
parentNode
;
do
{
String
pkgName
;
int
idx
=
fullPkgName
.
indexOf
(
classNameSepearator
);
if
(
idx
>
-
1
)
{
pkgName
=
fullPkgName
.
substring
(
0
,
idx
);
fullPkgName
=
fullPkgName
.
substring
(
idx
+
1
);
}
else
{
pkgName
=
fullPkgName
;
fullPkgName
=
""
;
}
parentNode
=
result
;
result
=
result
.
getInnerPackageByName
(
pkgName
);
if
((
result
==
null
)
&&
(
_creat
))
{
result
=
new
PackageNode
(
pkgName
);
parentNode
.
addInnerPackage
(
result
);
}
}
while
(!
fullPkgName
.
isEmpty
()
&&
(
result
!=
null
));
return
result
;
}
private
class
DefaultDeobfuscatorClassInfo
{
public
ClassNode
cls
;
public
PackageNode
pkg
;
public
String
alias
;
public
DefaultDeobfuscatorClassInfo
(
ClassNode
cls
,
PackageNode
pkg
)
{
this
.
cls
=
cls
;
this
.
pkg
=
pkg
;
}
public
String
getNameWithoutPackage
(
DefaultDeobfuscatorClassInfo
deobfClsInfo
)
{
final
ClassNode
clsNode
=
deobfClsInfo
.
cls
;
String
prefix
;
ClassNode
parentClass
=
clsNode
.
getParentClass
();
if
(
parentClass
!=
clsNode
)
{
DefaultDeobfuscatorClassInfo
parentDeobfClassInfo
=
DefaultDeobfuscator
.
clsMap
.
get
(
parentClass
.
getClassInfo
());
if
(
parentDeobfClassInfo
!=
null
)
{
prefix
=
getNameWithoutPackage
(
parentDeobfClassInfo
)
+
DefaultDeobfuscator
.
classNameSepearator
;
}
else
{
prefix
=
DefaultDeobfuscator
.
getNameWithoutPackage
(
parentClass
.
getClassInfo
())
+
DefaultDeobfuscator
.
classNameSepearator
;
}
}
else
{
prefix
=
""
;
}
return
prefix
+
((
deobfClsInfo
.
alias
!=
null
)
?
deobfClsInfo
.
alias
:
deobfClsInfo
.
cls
.
getShortName
());
}
public
String
getFullName
()
{
return
pkg
.
getFullAlias
()
+
DefaultDeobfuscator
.
classNameSepearator
+
getNameWithoutPackage
(
this
);
}
}
private
Map
<
String
,
String
>
preloadClsMap
=
Collections
.
emptyMap
();
private
static
Map
<
ClassInfo
,
DefaultDeobfuscatorClassInfo
>
clsMap
=
new
HashMap
<
ClassInfo
,
DefaultDeobfuscatorClassInfo
>();
public
static
String
getNameWithoutPackage
(
ClassInfo
clsInfo
)
{
String
prefix
;
ClassInfo
parentClsInfo
=
clsInfo
.
getParentClass
();
if
(
parentClsInfo
!=
null
)
{
DefaultDeobfuscatorClassInfo
parentDeobfClsInfo
=
DefaultDeobfuscator
.
clsMap
.
get
(
parentClsInfo
);
if
(
parentDeobfClsInfo
!=
null
)
{
prefix
=
parentDeobfClsInfo
.
getNameWithoutPackage
(
parentDeobfClsInfo
)
+
DefaultDeobfuscator
.
classNameSepearator
;
}
else
{
prefix
=
getNameWithoutPackage
(
parentClsInfo
)
+
DefaultDeobfuscator
.
classNameSepearator
;
}
}
else
{
prefix
=
""
;
}
return
prefix
+
clsInfo
.
getShortName
();
}
private
void
doClass
(
ClassNode
cls
)
{
final
String
pkgFullName
=
cls
.
getPackage
();
PackageNode
pkg
=
getPackageNode
(
pkgFullName
,
true
);
doPkg
(
pkg
,
pkgFullName
);
if
(
preloadClsMap
.
containsKey
(
cls
.
getFullName
()))
{
DefaultDeobfuscatorClassInfo
clsInfo
=
new
DefaultDeobfuscatorClassInfo
(
cls
,
pkg
);
clsInfo
.
alias
=
preloadClsMap
.
get
(
cls
.
getFullName
());
clsMap
.
put
(
cls
.
getClassInfo
(),
clsInfo
);
return
;
}
if
(
clsMap
.
containsKey
(
cls
))
{
return
;
}
final
String
className
=
cls
.
getShortName
();
if
(
shouldRename
(
className
))
{
DefaultDeobfuscatorClassInfo
clsInfo
=
new
DefaultDeobfuscatorClassInfo
(
cls
,
pkg
);
clsInfo
.
alias
=
String
.
format
(
"C%04d%s"
,
clsIndex
++,
short4LongName
(
className
));
clsMap
.
put
(
cls
.
getClassInfo
(),
clsInfo
);
}
}
private
String
short4LongName
(
String
name
)
{
if
(
name
.
length
()
>
maxLength
)
{
return
"x"
+
Integer
.
toHexString
(
name
.
hashCode
());
}
else
{
return
name
;
}
}
private
Set
<
String
>
pkgSet
=
new
TreeSet
<
String
>();
private
void
doPkg
(
PackageNode
pkg
,
String
fullName
)
{
if
(
pkgSet
.
contains
(
fullName
))
{
return
;
}
pkgSet
.
add
(
fullName
);
// doPkg for all parent packages except root that not hasAlisas
PackageNode
parentPkg
=
pkg
.
getParentPackage
();
while
(!
parentPkg
.
getName
().
isEmpty
())
{
if
(!
parentPkg
.
hasAlias
())
{
doPkg
(
parentPkg
,
parentPkg
.
getFullName
());
}
parentPkg
=
parentPkg
.
getParentPackage
();
}
final
String
pkgName
=
pkg
.
getName
();
if
(
shouldRename
(
pkgName
)
&&
!
pkg
.
hasAlias
())
{
final
String
pkgAlias
=
String
.
format
(
"p%03d%s"
,
pkgIndex
++,
short4LongName
(
pkgName
));
pkg
.
setAlias
(
pkgAlias
);
}
}
private
void
preprocess
()
{
if
(
dexNodes
!=
null
)
{
for
(
DexNode
dexNode
:
dexNodes
)
{
for
(
ClassNode
cls
:
dexNode
.
getClasses
())
{
doClass
(
cls
);
}
}
}
}
private
boolean
shouldRename
(
String
s
)
{
return
s
.
length
()
>
maxLength
||
s
.
length
()
<
minLength
||
NameMapper
.
isReserved
(
s
);
}
private
void
dumpClassAlias
(
ClassNode
cls
)
{
PackageNode
pkg
=
getPackageNode
(
cls
.
getPackage
(),
false
);
if
(
pkg
!=
null
)
{
if
(!
cls
.
getFullName
().
equals
(
getClassFullName
(
cls
)))
{
LOG
.
info
(
"Alias name for class '{}' is '{}'"
,
cls
.
getFullName
(),
getClassFullName
(
cls
));
}
}
else
{
LOG
.
error
(
"Can't find package node for '{}'"
,
cls
.
getPackage
());
}
}
private
void
dumpAlias
()
{
for
(
DexNode
dexNode
:
dexNodes
)
{
for
(
ClassNode
cls
:
dexNode
.
getClasses
())
{
dumpClassAlias
(
cls
);
}
}
}
/**
* Sets input data for processing
*
* @param nodes
*
* @return @{code this}
*/
public
DefaultDeobfuscator
setInputData
(
List
<
DexNode
>
nodes
)
{
this
.
dexNodes
=
nodes
;
return
this
;
}
/**
* Sets minimum name length, if name length lesser than value,
* DefaultDeobfuscator will work
*
* @param value
*
* @return @{code this}
*/
public
DefaultDeobfuscator
setMinNameLength
(
int
value
)
{
this
.
minLength
=
value
;
return
this
;
}
/**
* Sets maximum name length, if name length greater than value,
* DefaultDeobfuscator will work
*
* @param value
*
* @return @{code this}
*/
public
DefaultDeobfuscator
setMaxNameLength
(
int
value
)
{
this
.
maxLength
=
value
;
return
this
;
}
/**
* Loads DefaultDeobfuscator presets
*
* @param config
* @throws IOException
*/
public
void
load
(
File
mapFile
)
throws
IOException
{
if
(
mapFile
.
exists
())
{
List
<
String
>
lines
=
FileUtils
.
readLines
(
mapFile
,
MAP_FILE_CHARSET
);
for
(
String
l
:
lines
)
{
if
(
l
.
startsWith
(
"p "
))
{
final
String
rule
=
l
.
substring
(
2
);
final
String
va
[]
=
rule
.
split
(
"="
);
if
(
va
.
length
==
2
)
{
PackageNode
pkg
=
getPackageNode
(
va
[
0
],
true
);
pkg
.
setAlias
(
va
[
1
]);
}
}
else
if
(
l
.
startsWith
(
"c "
))
{
final
String
rule
=
l
.
substring
(
2
);
final
String
va
[]
=
rule
.
split
(
"="
);
if
(
va
.
length
==
2
)
{
if
(
preloadClsMap
.
isEmpty
())
{
preloadClsMap
=
new
HashMap
<
String
,
String
>();
}
preloadClsMap
.
put
(
va
[
0
],
va
[
1
]);
}
}
}
}
}
public
void
process
()
{
preprocess
();
if
(
DEBUG
)
{
dumpAlias
();
}
preloadClsMap
.
clear
();
preloadClsMap
=
Collections
.
emptyMap
();
}
private
static
void
dfsPackageName
(
List
<
String
>
list
,
String
prefix
,
PackageNode
node
)
{
for
(
PackageNode
pp
:
node
.
getInnerPackages
())
{
dfsPackageName
(
list
,
prefix
+
'.'
+
node
.
getName
(),
pp
);
}
if
(
node
.
hasAlias
())
{
list
.
add
(
String
.
format
(
"p %s.%s=%s"
,
prefix
,
node
.
getName
(),
node
.
getAlias
()));
}
}
/**
* Saves DefaultDeobfuscator presets
*
* @param mapFile
* @throws IOException
*/
public
void
save
(
File
mapFile
)
throws
IOException
{
List
<
String
>
list
=
new
ArrayList
<
String
>();
// packages
for
(
PackageNode
p
:
rootPackage
.
getInnerPackages
())
{
for
(
PackageNode
pp
:
p
.
getInnerPackages
())
{
dfsPackageName
(
list
,
p
.
getName
(),
pp
);
}
if
(
p
.
hasAlias
())
{
list
.
add
(
String
.
format
(
"p %s=%s"
,
p
.
getName
(),
p
.
getAlias
()));
}
}
// classes
for
(
DefaultDeobfuscatorClassInfo
deobfClsInfo
:
clsMap
.
values
())
{
if
(
deobfClsInfo
.
alias
!=
null
)
{
list
.
add
(
String
.
format
(
"c %s=%s"
,
deobfClsInfo
.
cls
.
getFullName
(),
deobfClsInfo
.
alias
));
}
}
FileUtils
.
writeLines
(
mapFile
,
MAP_FILE_CHARSET
,
list
);
list
.
clear
();
}
@Override
public
String
getPackageName
(
String
packageName
)
{
final
PackageNode
pkg
=
getPackageNode
(
packageName
,
false
);
if
(
pkg
!=
null
)
{
return
pkg
.
getFullAlias
();
}
return
packageName
;
}
@Override
public
String
getClassShortName
(
ClassNode
cls
)
{
return
getClassShortName
(
cls
.
getClassInfo
());
}
@Override
public
String
getClassShortName
(
ClassInfo
clsInfo
)
{
final
DefaultDeobfuscatorClassInfo
deobfClsInfo
=
clsMap
.
get
(
clsInfo
);
if
(
deobfClsInfo
!=
null
)
{
return
(
deobfClsInfo
.
alias
!=
null
)
?
deobfClsInfo
.
alias
:
clsInfo
.
getShortName
();
}
return
clsInfo
.
getShortName
();
}
@Override
public
String
getClassName
(
ClassNode
cls
)
{
return
getClassName
(
cls
.
getClassInfo
());
}
@Override
public
String
getClassName
(
ClassInfo
clsInfo
)
{
final
DefaultDeobfuscatorClassInfo
deobfClsInfo
=
clsMap
.
get
(
clsInfo
);
if
(
deobfClsInfo
!=
null
)
{
return
deobfClsInfo
.
getNameWithoutPackage
(
deobfClsInfo
);
}
return
getNameWithoutPackage
(
clsInfo
);
}
@Override
public
String
getClassFullName
(
ClassNode
cls
)
{
return
getClassFullName
(
cls
.
getClassInfo
());
}
@Override
public
String
getClassFullName
(
ClassInfo
clsInfo
)
{
final
DefaultDeobfuscatorClassInfo
deobfClsInfo
=
clsMap
.
get
(
clsInfo
);
if
(
deobfClsInfo
!=
null
)
{
return
deobfClsInfo
.
getFullName
();
}
return
getPackageName
(
clsInfo
.
getPackage
())
+
DefaultDeobfuscator
.
classNameSepearator
+
getClassName
(
clsInfo
);
}
@Override
public
String
getClassFullPath
(
ClassInfo
clsInfo
)
{
final
DefaultDeobfuscatorClassInfo
deobfClsInfo
=
clsMap
.
get
(
clsInfo
);
if
(
deobfClsInfo
!=
null
)
{
return
deobfClsInfo
.
pkg
.
getFullAlias
().
replace
(
DefaultDeobfuscator
.
classNameSepearator
,
File
.
separatorChar
)
+
File
.
separatorChar
+
deobfClsInfo
.
getNameWithoutPackage
(
deobfClsInfo
).
replace
(
DefaultDeobfuscator
.
classNameSepearator
,
'_'
);
}
return
getPackageName
(
clsInfo
.
getPackage
()).
replace
(
'.'
,
File
.
separatorChar
)
+
File
.
separatorChar
+
clsInfo
.
getNameWithoutPackage
().
replace
(
'.'
,
'_'
);
}
}
jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
0 → 100644
View file @
c5c4499a
package
jadx
.
core
.
deobf
;
public
class
Deobfuscator
{
private
static
final
StubDeobfuscator
stubDeobfuscator
;
private
static
IDeobfuscator
deobfuscatorInstance
;
static
{
stubDeobfuscator
=
new
StubDeobfuscator
();
deobfuscatorInstance
=
stubDeobfuscator
;
}
/**
* Gets instance of active deobfuscator
*
* @return deobfuscator instance
*/
public
static
IDeobfuscator
instance
()
{
return
deobfuscatorInstance
;
}
/**
* Sets active deobfuscator
*
* @param deobfuscator object that makes deobfuscation or {@code null}
* to set stub deobfuscator
*
*/
public
static
void
setDeobfuscator
(
IDeobfuscator
deobfuscator
)
{
if
(
deobfuscator
!=
null
)
{
deobfuscatorInstance
=
deobfuscator
;
}
else
{
deobfuscatorInstance
=
stubDeobfuscator
;
}
}
}
jadx-core/src/main/java/jadx/core/deobf/IDeobfuscator.java
0 → 100644
View file @
c5c4499a
package
jadx
.
core
.
deobf
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.nodes.ClassNode
;
public
interface
IDeobfuscator
{
public
String
getPackageName
(
String
packageName
);
public
String
getClassShortName
(
ClassNode
cls
);
public
String
getClassShortName
(
ClassInfo
clsInfo
);
public
String
getClassName
(
ClassNode
cls
);
public
String
getClassName
(
ClassInfo
clsInfo
);
public
String
getClassFullName
(
ClassNode
cls
);
public
String
getClassFullName
(
ClassInfo
clsInfo
);
public
String
getClassFullPath
(
ClassInfo
clsInfo
);
}
jadx-core/src/main/java/jadx/core/deobf/PackageNode.java
0 → 100644
View file @
c5c4499a
package
jadx
.
core
.
deobf
;
import
jadx.core.dex.nodes.ClassNode
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Stack
;
public
class
PackageNode
{
private
PackageNode
parentPackage
;
private
List
<
ClassNode
>
innerClasses
=
Collections
.
emptyList
();
private
List
<
PackageNode
>
innerPackages
=
Collections
.
emptyList
();
public
static
final
char
separatorChar
=
'.'
;
private
String
packageName
;
private
String
packageAlias
;
private
String
cachedPackageFullName
;
private
String
cachedPackageFullAlias
;
public
PackageNode
(
String
packageName
)
{
this
.
packageName
=
packageName
;
this
.
parentPackage
=
this
;
}
public
String
getName
()
{
return
packageName
;
}
public
String
getFullName
()
{
if
(
cachedPackageFullName
==
null
)
{
Stack
<
PackageNode
>
pp
=
getParentPackages
();
StringBuilder
result
=
new
StringBuilder
();
result
.
append
(
pp
.
pop
().
getName
());
while
(
pp
.
size
()
>
0
)
{
result
.
append
(
separatorChar
);
result
.
append
(
pp
.
pop
().
getName
());
}
cachedPackageFullName
=
result
.
toString
();
}
return
cachedPackageFullName
;
}
public
String
getAlias
()
{
if
(
packageAlias
!=
null
)
{
return
packageAlias
;
}
return
packageName
;
}
public
void
setAlias
(
String
alias
)
{
packageAlias
=
alias
;
}
public
boolean
hasAlias
()
{
return
(
packageAlias
!=
null
);
}
public
String
getFullAlias
()
{
if
(
cachedPackageFullAlias
==
null
)
{
Stack
<
PackageNode
>
pp
=
getParentPackages
();
StringBuilder
result
=
new
StringBuilder
();
result
.
append
(
pp
.
pop
().
getAlias
());
while
(
pp
.
size
()
>
0
)
{
result
.
append
(
separatorChar
);
result
.
append
(
pp
.
pop
().
getAlias
());
}
cachedPackageFullAlias
=
result
.
toString
();
}
return
cachedPackageFullAlias
;
}
public
PackageNode
getParentPackage
()
{
return
parentPackage
;
}
public
List
<
PackageNode
>
getInnerPackages
()
{
return
innerPackages
;
}
public
List
<
ClassNode
>
getInnerClasses
()
{
return
innerClasses
;
}
public
void
addInnerClass
(
ClassNode
cls
)
{
if
(
innerClasses
.
isEmpty
())
{
innerClasses
=
new
ArrayList
<
ClassNode
>();
}
innerClasses
.
add
(
cls
);
}
public
void
addInnerPackage
(
PackageNode
pkg
)
{
if
(
innerPackages
.
isEmpty
())
{
innerPackages
=
new
ArrayList
<
PackageNode
>();
}
innerPackages
.
add
(
pkg
);
pkg
.
parentPackage
=
this
;
}
/**
* Gets inner package node by name
*
* @param name inner package name
*
* @return package node or {@code null}
*/
public
PackageNode
getInnerPackageByName
(
String
name
)
{
PackageNode
result
=
null
;
for
(
PackageNode
p
:
innerPackages
)
{
if
(
p
.
getName
().
equals
(
name
))
{
result
=
p
;
break
;
}
}
return
result
;
}
/**
* Fills stack with parent packages exclude root node
*
* @return stack with parent packages
*/
private
Stack
<
PackageNode
>
getParentPackages
()
{
Stack
<
PackageNode
>
pp
=
new
Stack
<
PackageNode
>();
PackageNode
currentP
=
this
;
PackageNode
parentP
=
currentP
.
getParentPackage
();
while
(
currentP
!=
parentP
)
{
pp
.
push
(
currentP
);
currentP
=
parentP
;
parentP
=
currentP
.
getParentPackage
();
}
return
pp
;
}
}
jadx-core/src/main/java/jadx/core/deobf/StubDeobfuscator.java
0 → 100644
View file @
c5c4499a
package
jadx
.
core
.
deobf
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.nodes.ClassNode
;
public
class
StubDeobfuscator
implements
IDeobfuscator
{
@Override
public
String
getPackageName
(
String
packageName
)
{
return
packageName
;
}
@Override
public
String
getClassShortName
(
ClassNode
cls
)
{
return
cls
.
getShortName
();
}
@Override
public
String
getClassShortName
(
ClassInfo
clsInfo
)
{
return
clsInfo
.
getShortName
();
}
@Override
public
String
getClassName
(
ClassNode
cls
)
{
return
cls
.
getClassInfo
().
getNameWithoutPackage
();
}
@Override
public
String
getClassName
(
ClassInfo
clsInfo
)
{
return
clsInfo
.
getNameWithoutPackage
();
}
@Override
public
String
getClassFullName
(
ClassNode
cls
)
{
return
cls
.
getFullName
();
}
@Override
public
String
getClassFullName
(
ClassInfo
clsInfo
)
{
return
clsInfo
.
getFullName
();
}
@Override
public
String
getClassFullPath
(
ClassInfo
clsInfo
)
{
return
clsInfo
.
getFullPath
();
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
View file @
c5c4499a
...
...
@@ -2,6 +2,7 @@ package jadx.core.dex.visitors;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.codegen.MethodGen
;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.dex.attributes.IAttributeNode
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.InsnType
;
...
...
@@ -104,7 +105,7 @@ public class DotGraphVisitor extends AbstractVisitor {
+
(
useRegions
?
".regions"
:
""
)
+
(
rawInsn
?
".raw"
:
""
)
+
".dot"
;
dot
.
save
(
dir
,
mth
.
getParentClass
().
getClassInfo
().
getFullPath
(
)
+
"_graphs"
,
fileName
);
dot
.
save
(
dir
,
Deobfuscator
.
instance
().
getClassFullPath
(
mth
.
getParentClass
().
getClassInfo
()
)
+
"_graphs"
,
fileName
);
}
private
void
processMethodRegion
(
MethodNode
mth
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/SaveCode.java
View file @
c5c4499a
...
...
@@ -2,6 +2,7 @@ package jadx.core.dex.visitors;
import
jadx.api.IJadxArgs
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.utils.exceptions.CodegenException
;
...
...
@@ -24,7 +25,7 @@ public class SaveCode extends AbstractVisitor {
public
static
void
save
(
File
dir
,
IJadxArgs
args
,
ClassNode
cls
)
{
CodeWriter
clsCode
=
cls
.
getCode
();
String
fileName
=
cls
.
getClassInfo
().
getFullPath
(
)
+
".java"
;
String
fileName
=
Deobfuscator
.
instance
().
getClassFullPath
(
cls
.
getClassInfo
()
)
+
".java"
;
if
(
args
.
isFallbackMode
())
{
fileName
+=
".jadx"
;
}
...
...
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