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
bc8ad4df
Commit
bc8ad4df
authored
May 25, 2015
by
skylot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #64 from NeoSpb/fix_deobfuscator
Fix deobfuscator
parents
c923d19b
53ac3ec5
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
221 additions
and
5 deletions
+221
-5
JadxCLIArgs.java
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+8
-0
DefaultJadxArgs.java
jadx-core/src/main/java/jadx/api/DefaultJadxArgs.java
+5
-0
IJadxArgs.java
jadx-core/src/main/java/jadx/api/IJadxArgs.java
+2
-0
Deobfuscator.java
jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
+139
-1
OverridedMethodsNode.java
...e/src/main/java/jadx/core/deobf/OverridedMethodsNode.java
+26
-0
MethodInfo.java
jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java
+10
-0
ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+2
-2
MethodNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
+7
-1
RenameVisitor.java
...e/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
+7
-1
JadxSettings.java
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+4
-0
JadxSettingsWindow.java
...i/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
+10
-0
Messages_en_US.properties
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
+1
-0
No files found.
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
View file @
bc8ad4df
...
...
@@ -64,6 +64,9 @@ public class JadxCLIArgs implements IJadxArgs {
@Parameter
(
names
=
{
"--deobf-rewrite-cfg"
},
description
=
"force to save deobfuscation map"
)
protected
boolean
deobfuscationForceSave
=
false
;
@Parameter
(
names
=
{
"--deobf-use-sourcename"
},
description
=
"use source file name as class name alias"
)
protected
boolean
deobfuscationUseSourceNameAsAlias
=
false
;
@Parameter
(
names
=
{
"-h"
,
"--help"
},
description
=
"print this help"
,
help
=
true
)
protected
boolean
printHelp
=
false
;
...
...
@@ -242,4 +245,9 @@ public class JadxCLIArgs implements IJadxArgs {
public
boolean
isDeobfuscationForceSave
()
{
return
deobfuscationForceSave
;
}
@Override
public
boolean
useSourceNameAsClassAlias
()
{
return
deobfuscationUseSourceNameAsAlias
;
}
}
jadx-core/src/main/java/jadx/api/DefaultJadxArgs.java
View file @
bc8ad4df
...
...
@@ -68,4 +68,9 @@ public class DefaultJadxArgs implements IJadxArgs {
public
boolean
isDeobfuscationForceSave
()
{
return
false
;
}
@Override
public
boolean
useSourceNameAsClassAlias
()
{
return
false
;
}
}
jadx-core/src/main/java/jadx/api/IJadxArgs.java
View file @
bc8ad4df
...
...
@@ -28,4 +28,6 @@ public interface IJadxArgs {
int
getDeobfuscationMaxLength
();
boolean
isDeobfuscationForceSave
();
boolean
useSourceNameAsClassAlias
();
}
jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
View file @
bc8ad4df
...
...
@@ -6,13 +6,17 @@ import jadx.core.dex.attributes.nodes.SourceFileAttr;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
java.io.File
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
...
...
@@ -40,11 +44,16 @@ public class Deobfuscator {
private
final
Map
<
FieldInfo
,
String
>
fldMap
=
new
HashMap
<
FieldInfo
,
String
>();
private
final
Map
<
MethodInfo
,
String
>
mthMap
=
new
HashMap
<
MethodInfo
,
String
>();
private
final
Map
<
MethodInfo
,
OverridedMethodsNode
>
ovrdMap
=
new
HashMap
<
MethodInfo
,
OverridedMethodsNode
>();
private
final
List
<
OverridedMethodsNode
>
ovrd
=
new
ArrayList
<
OverridedMethodsNode
>();
private
final
PackageNode
rootPackage
=
new
PackageNode
(
""
);
private
final
Set
<
String
>
pkgSet
=
new
TreeSet
<
String
>();
private
final
int
maxLength
;
private
final
int
minLength
;
private
final
boolean
useSourceNameAsAlias
;
private
int
pkgIndex
=
0
;
private
int
clsIndex
=
0
;
private
int
fldIndex
=
0
;
...
...
@@ -56,6 +65,7 @@ public class Deobfuscator {
this
.
minLength
=
args
.
getDeobfuscationMinLength
();
this
.
maxLength
=
args
.
getDeobfuscationMaxLength
();
this
.
useSourceNameAsAlias
=
args
.
useSourceNameAsClassAlias
();
this
.
deobfPresets
=
new
DeobfPresets
(
this
,
deobfMapFile
);
}
...
...
@@ -95,6 +105,32 @@ public class Deobfuscator {
processClass
(
dexNode
,
cls
);
}
}
postProcess
();
}
private
void
postProcess
()
{
int
id
=
1
;
for
(
OverridedMethodsNode
o
:
ovrd
)
{
Iterator
<
MethodInfo
>
it
=
o
.
getMethods
().
iterator
();
if
(
it
.
hasNext
())
{
MethodInfo
mth
=
it
.
next
();
if
(
mth
.
isRenamed
()
&&
!
mth
.
isAliasFromPreset
())
{
mth
.
setAlias
(
String
.
format
(
"mo%d%s"
,
id
,
makeName
(
mth
.
getName
())));
}
String
firstMethodAlias
=
mth
.
getAlias
();
while
(
it
.
hasNext
())
{
mth
=
it
.
next
();
if
(!
mth
.
getAlias
().
equals
(
firstMethodAlias
))
{
mth
.
setAlias
(
firstMethodAlias
);
}
}
}
id
++;
}
}
void
clear
()
{
...
...
@@ -102,6 +138,98 @@ public class Deobfuscator {
clsMap
.
clear
();
fldMap
.
clear
();
mthMap
.
clear
();
ovrd
.
clear
();
ovrdMap
.
clear
();
}
@Nullable
private
static
ClassNode
resolveOverridingInternal
(
DexNode
dex
,
ClassNode
cls
,
String
signature
,
Set
<
MethodInfo
>
overrideSet
,
ClassNode
rootClass
)
{
ClassNode
result
=
null
;
for
(
MethodNode
m
:
cls
.
getMethods
())
{
if
(
m
.
getMethodInfo
().
getShortId
().
startsWith
(
signature
))
{
result
=
cls
;
if
(!
overrideSet
.
contains
(
m
.
getMethodInfo
()))
{
overrideSet
.
add
(
m
.
getMethodInfo
());
}
break
;
}
}
ArgType
superClass
=
cls
.
getSuperClass
();
if
(
superClass
!=
null
)
{
ClassNode
superNode
=
dex
.
resolveClass
(
superClass
);
if
(
superNode
!=
null
)
{
ClassNode
clsWithMth
=
resolveOverridingInternal
(
dex
,
superNode
,
signature
,
overrideSet
,
rootClass
);
if
(
clsWithMth
!=
null
)
{
if
((
result
!=
null
)
&&
(
result
!=
cls
))
{
if
(
clsWithMth
!=
result
)
{
LOG
.
warn
(
String
.
format
(
"Multiple overriding '%s' from '%s' and '%s' in '%s'"
,
signature
,
result
.
getFullName
(),
clsWithMth
.
getFullName
(),
rootClass
.
getFullName
()));
}
}
else
{
result
=
clsWithMth
;
}
}
}
}
for
(
ArgType
iFaceType
:
cls
.
getInterfaces
())
{
ClassNode
iFaceNode
=
dex
.
resolveClass
(
iFaceType
);
if
(
iFaceNode
!=
null
)
{
ClassNode
clsWithMth
=
resolveOverridingInternal
(
dex
,
iFaceNode
,
signature
,
overrideSet
,
rootClass
);
if
(
clsWithMth
!=
null
)
{
if
((
result
!=
null
)
&&
(
result
!=
cls
))
{
if
(
clsWithMth
!=
result
)
{
LOG
.
warn
(
String
.
format
(
"Multiple overriding '%s' from '%s' and '%s' in '%s'"
,
signature
,
result
.
getFullName
(),
clsWithMth
.
getFullName
(),
rootClass
.
getFullName
()));
}
}
else
{
result
=
clsWithMth
;
}
}
}
}
return
result
;
}
private
void
resolveOverriding
(
DexNode
dex
,
ClassNode
cls
,
MethodNode
mth
)
{
Set
<
MethodInfo
>
overrideSet
=
new
HashSet
<
MethodInfo
>();
resolveOverridingInternal
(
dex
,
cls
,
mth
.
getMethodInfo
().
makeSignature
(
false
),
overrideSet
,
cls
);
if
(
overrideSet
.
size
()
>
1
)
{
OverridedMethodsNode
overrideNode
=
null
;
for
(
MethodInfo
_mth
:
overrideSet
)
{
if
(
ovrdMap
.
containsKey
(
_mth
))
{
overrideNode
=
ovrdMap
.
get
(
_mth
);
break
;
}
}
if
(
overrideNode
==
null
)
{
overrideNode
=
new
OverridedMethodsNode
(
overrideSet
);
ovrd
.
add
(
overrideNode
);
}
for
(
MethodInfo
_mth
:
overrideSet
)
{
if
(!
ovrdMap
.
containsKey
(
_mth
))
{
ovrdMap
.
put
(
_mth
,
overrideNode
);
if
(!
overrideNode
.
contains
(
_mth
))
{
overrideNode
.
add
(
_mth
);
}
}
}
}
else
{
overrideSet
.
clear
();
overrideSet
=
null
;
}
}
private
void
processClass
(
DexNode
dex
,
ClassNode
cls
)
{
...
...
@@ -123,6 +251,10 @@ public class Deobfuscator {
if
(
alias
!=
null
)
{
methodInfo
.
setAlias
(
alias
);
}
if
(
mth
.
isVirtual
())
{
resolveOverriding
(
dex
,
cls
,
mth
);
}
}
}
...
...
@@ -212,7 +344,12 @@ public class Deobfuscator {
private
String
makeClsAlias
(
ClassNode
cls
)
{
ClassInfo
classInfo
=
cls
.
getClassInfo
();
String
alias
=
getAliasFromSourceFile
(
cls
);
String
alias
=
null
;
if
(
this
.
useSourceNameAsAlias
)
{
alias
=
getAliasFromSourceFile
(
cls
);
}
if
(
alias
==
null
)
{
String
clsName
=
classInfo
.
getShortName
();
alias
=
String
.
format
(
"C%04d%s"
,
clsIndex
++,
makeName
(
clsName
));
...
...
@@ -269,6 +406,7 @@ public class Deobfuscator {
alias
=
deobfPresets
.
getForMth
(
methodInfo
);
if
(
alias
!=
null
)
{
mthMap
.
put
(
methodInfo
,
alias
);
methodInfo
.
setAliasFromPreset
(
true
);
return
alias
;
}
if
(
shouldRename
(
mth
.
getName
()))
{
...
...
jadx-core/src/main/java/jadx/core/deobf/OverridedMethodsNode.java
0 → 100644
View file @
bc8ad4df
package
jadx
.
core
.
deobf
;
import
jadx.core.dex.info.MethodInfo
;
import
java.util.Set
;
/* package */
class
OverridedMethodsNode
{
private
Set
<
MethodInfo
>
methods
;
public
OverridedMethodsNode
(
Set
<
MethodInfo
>
methodsSet
)
{
methods
=
methodsSet
;
}
public
boolean
contains
(
MethodInfo
mth
)
{
return
methods
.
contains
(
mth
);
}
public
void
add
(
MethodInfo
mth
)
{
methods
.
add
(
mth
);
}
public
Set
<
MethodInfo
>
getMethods
()
{
return
methods
;
}
}
jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java
View file @
bc8ad4df
...
...
@@ -18,11 +18,13 @@ public final class MethodInfo {
private
final
ClassInfo
declClass
;
private
final
String
shortId
;
private
String
alias
;
private
boolean
aliasFromPreset
;
private
MethodInfo
(
DexNode
dex
,
int
mthIndex
)
{
MethodId
mthId
=
dex
.
getMethodId
(
mthIndex
);
name
=
dex
.
getString
(
mthId
.
getNameIndex
());
alias
=
name
;
aliasFromPreset
=
false
;
declClass
=
ClassInfo
.
fromDex
(
dex
,
mthId
.
getDeclaringClassIndex
());
ProtoId
proto
=
dex
.
getProtoId
(
mthId
.
getProtoIndex
());
...
...
@@ -109,6 +111,14 @@ public final class MethodInfo {
return
!
name
.
equals
(
alias
);
}
public
boolean
isAliasFromPreset
()
{
return
aliasFromPreset
;
}
public
void
setAliasFromPreset
(
boolean
value
)
{
aliasFromPreset
=
value
;
}
@Override
public
int
hashCode
()
{
int
result
=
declClass
.
hashCode
();
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
View file @
bc8ad4df
...
...
@@ -86,10 +86,10 @@ public class ClassNode extends LineAttrNode implements ILoadable {
fields
=
new
ArrayList
<
FieldNode
>(
fieldsCount
);
for
(
Method
mth
:
clsData
.
getDirectMethods
())
{
methods
.
add
(
new
MethodNode
(
this
,
mth
));
methods
.
add
(
new
MethodNode
(
this
,
mth
,
false
));
}
for
(
Method
mth
:
clsData
.
getVirtualMethods
())
{
methods
.
add
(
new
MethodNode
(
this
,
mth
));
methods
.
add
(
new
MethodNode
(
this
,
mth
,
true
));
}
for
(
Field
f
:
clsData
.
getStaticFields
())
{
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
View file @
bc8ad4df
...
...
@@ -56,6 +56,7 @@ public class MethodNode extends LineAttrNode implements ILoadable {
private
int
codeSize
;
private
int
debugInfoOffset
;
private
boolean
noCode
;
private
boolean
methodIsVirtual
;
private
ArgType
retType
;
private
RegisterArg
thisArg
;
...
...
@@ -71,12 +72,13 @@ public class MethodNode extends LineAttrNode implements ILoadable {
private
List
<
ExceptionHandler
>
exceptionHandlers
=
Collections
.
emptyList
();
private
List
<
LoopInfo
>
loops
=
Collections
.
emptyList
();
public
MethodNode
(
ClassNode
classNode
,
Method
mthData
)
{
public
MethodNode
(
ClassNode
classNode
,
Method
mthData
,
boolean
isVirtual
)
{
this
.
mthInfo
=
MethodInfo
.
fromDex
(
classNode
.
dex
(),
mthData
.
getMethodIndex
());
this
.
parentClass
=
classNode
;
this
.
accFlags
=
new
AccessInfo
(
mthData
.
getAccessFlags
(),
AFType
.
METHOD
);
this
.
noCode
=
mthData
.
getCodeOffset
()
==
0
;
this
.
methodData
=
noCode
?
null
:
mthData
;
this
.
methodIsVirtual
=
isVirtual
;
}
@Override
...
...
@@ -538,6 +540,10 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return
result
;
}
public
boolean
isVirtual
()
{
return
methodIsVirtual
;
}
public
int
getRegsCount
()
{
return
regsCount
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
View file @
bc8ad4df
...
...
@@ -30,7 +30,13 @@ public class RenameVisitor extends AbstractVisitor {
@Override
public
void
init
(
RootNode
root
)
{
IJadxArgs
args
=
root
.
getArgs
();
File
deobfMapFile
=
new
File
(
args
.
getOutDir
(),
"deobf_map.jobf"
);
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
);
File
deobfMapFile
=
new
File
(
inputPath
,
inputName
+
".jobf"
);
deobfuscator
=
new
Deobfuscator
(
args
,
root
.
getDexNodes
(),
deobfMapFile
);
boolean
deobfuscationOn
=
args
.
isDeobfuscationOn
();
if
(
deobfuscationOn
)
{
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
View file @
bc8ad4df
...
...
@@ -132,6 +132,10 @@ public class JadxSettings extends JadxCLIArgs {
this
.
deobfuscationForceSave
=
deobfuscationForceSave
;
}
public
void
setUseSourceNameAsClassAlias
(
boolean
useSourceNameAsAlias
)
{
this
.
deobfuscationUseSourceNameAsAlias
=
useSourceNameAsAlias
;
}
public
Font
getFont
()
{
if
(
fontStr
.
isEmpty
())
{
return
DEFAULT_FONT
;
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
View file @
bc8ad4df
...
...
@@ -141,11 +141,21 @@ public class JadxSettingsWindow extends JDialog {
}
});
JCheckBox
deobfSourceAlias
=
new
JCheckBox
();
deobfSourceAlias
.
setSelected
(
settings
.
useSourceNameAsClassAlias
());
deobfSourceAlias
.
addItemListener
(
new
ItemListener
()
{
public
void
itemStateChanged
(
ItemEvent
e
)
{
settings
.
setUseSourceNameAsClassAlias
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
}
});
SettingsGroup
deobfGroup
=
new
SettingsGroup
(
NLS
.
str
(
"preferences.deobfuscation"
));
deobfGroup
.
addRow
(
NLS
.
str
(
"preferences.deobfuscation_on"
),
deobfOn
);
deobfGroup
.
addRow
(
NLS
.
str
(
"preferences.deobfuscation_force"
),
deobfForce
);
deobfGroup
.
addRow
(
NLS
.
str
(
"preferences.deobfuscation_min_len"
),
minLen
);
deobfGroup
.
addRow
(
NLS
.
str
(
"preferences.deobfuscation_max_len"
),
maxLen
);
deobfGroup
.
addRow
(
NLS
.
str
(
"preferences.deobfuscation_source_alias"
),
deobfSourceAlias
);
deobfGroup
.
end
();
return
deobfGroup
;
}
...
...
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
View file @
bc8ad4df
...
...
@@ -62,6 +62,7 @@ preferences.deobfuscation_on=Enable deobfuscation
preferences.deobfuscation_force
=
Force rewrite deobfuscation map file
preferences.deobfuscation_min_len
=
Minimum name length
preferences.deobfuscation_max_len
=
Maximum name length
preferences.deobfuscation_source_alias
=
Use source file name as class name alias
preferences.save
=
Save
preferences.cancel
=
Cancel
...
...
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