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
19c57258
Commit
19c57258
authored
May 09, 2019
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: improve rename checks and show rename reason (#584)
parent
fef3e55c
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
250 additions
and
126 deletions
+250
-126
JadxCLIArgs.java
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+19
-43
RenameConverterTest.java
jadx-cli/src/test/java/jadx/cli/RenameConverterTest.java
+2
-2
ResourcesLoader.java
jadx-core/src/main/java/jadx/api/ResourcesLoader.java
+1
-1
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+7
-6
MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+2
-1
NameGen.java
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
+1
-1
Deobfuscator.java
jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
+18
-23
NameMapper.java
jadx-core/src/main/java/jadx/core/deobf/NameMapper.java
+4
-0
AType.java
jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
+2
-0
RenameReasonAttr.java
...java/jadx/core/dex/attributes/nodes/RenameReasonAttr.java
+68
-0
RootNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+1
-1
ClassModifier.java
...e/src/main/java/jadx/core/dex/visitors/ClassModifier.java
+12
-10
EnumVisitor.java
...ore/src/main/java/jadx/core/dex/visitors/EnumVisitor.java
+2
-2
RenameVisitor.java
...e/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
+41
-23
DebugInfoApplyVisitor.java
...dx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java
+1
-1
CodeGenUtils.java
jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java
+32
-0
AndroidResourcesUtils.java
...n/java/jadx/core/utils/android/AndroidResourcesUtils.java
+2
-1
BinaryXMLParser.java
...-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
+1
-1
ResTableParser.java
jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java
+17
-3
ValuesParser.java
...re/src/main/java/jadx/core/xmlgen/entry/ValuesParser.java
+5
-4
JadxSettings.java
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+8
-0
JadxSettingsWindow.java
...i/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
+4
-3
No files found.
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
View file @
19c57258
package
jadx
.
cli
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.EnumSet
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Set
;
...
...
@@ -106,7 +106,7 @@ public class JadxCLIArgs {
+
" 'case' for system case sensitivity,"
+
" 'valid' for java identifiers,"
+
" 'printable' characters,"
+
" 'none' or 'all'"
,
+
" 'none' or 'all'
(default)
"
,
converter
=
RenameConverter
.
class
)
protected
Set
<
RenameEnum
>
renameFlags
=
EnumSet
.
allOf
(
RenameEnum
.
class
);
...
...
@@ -181,7 +181,7 @@ public class JadxCLIArgs {
args
.
setThreadsCount
(
threadsCount
);
args
.
setSkipSources
(
skipSources
);
if
(
singleClass
!=
null
)
{
args
.
setClassFilter
(
(
className
)
->
singleClass
.
equals
(
className
));
args
.
setClassFilter
(
className
->
singleClass
.
equals
(
className
));
}
args
.
setSkipResources
(
skipResources
);
args
.
setFallbackMode
(
fallbackMode
);
...
...
@@ -303,38 +303,14 @@ public class JadxCLIArgs {
return
renameFlags
.
contains
(
RenameEnum
.
CASE
);
}
public
void
setRenameCaseSensitive
(
boolean
renameCase
)
{
if
(
renameCase
&&
!
isRenameCaseSensitive
())
{
renameFlags
.
add
(
RenameEnum
.
CASE
);
}
else
if
(!
renameCase
&&
isRenameCaseSensitive
())
{
renameFlags
.
remove
(
RenameEnum
.
CASE
);
}
}
public
boolean
isRenameValid
()
{
return
renameFlags
.
contains
(
RenameEnum
.
VALID
);
}
public
void
setRenameValid
(
boolean
renameValid
)
{
if
(
renameValid
&&
!
isRenameValid
())
{
renameFlags
.
add
(
RenameEnum
.
VALID
);
}
else
if
(!
renameValid
&&
isRenameValid
())
{
renameFlags
.
remove
(
RenameEnum
.
VALID
);
}
}
public
boolean
isRenamePrintable
()
{
return
renameFlags
.
contains
(
RenameEnum
.
PRINTABLE
);
}
public
void
setRenamePrintable
(
boolean
renamePrintable
)
{
if
(
renamePrintable
&&
!
isRenamePrintable
())
{
renameFlags
.
add
(
RenameEnum
.
PRINTABLE
);
}
else
if
(!
renamePrintable
&&
isRenamePrintable
())
{
renameFlags
.
remove
(
RenameEnum
.
PRINTABLE
);
}
}
public
boolean
isFsCaseSensitive
()
{
return
fsCaseSensitive
;
}
...
...
@@ -348,23 +324,23 @@ public class JadxCLIArgs {
@Override
public
Set
<
RenameEnum
>
convert
(
String
value
)
{
Set
<
RenameEnum
>
set
=
new
HashSet
<>();
if
(
value
.
equalsIgnoreCase
(
"NONE"
))
{
return
EnumSet
.
noneOf
(
RenameEnum
.
class
);
}
if
(
value
.
equalsIgnoreCase
(
"ALL"
))
{
set
.
add
(
RenameEnum
.
CASE
);
set
.
add
(
RenameEnum
.
VALID
);
set
.
add
(
RenameEnum
.
PRINTABLE
);
}
else
if
(!
value
.
equalsIgnoreCase
(
"NONE"
))
{
for
(
String
s
:
value
.
split
(
","
))
{
try
{
set
.
add
(
RenameEnum
.
valueOf
(
s
.
toUpperCase
(
Locale
.
ROOT
)));
}
catch
(
IllegalArgumentException
e
)
{
String
values
=
"'"
+
RenameEnum
.
CASE
+
"', '"
+
RenameEnum
.
VALID
+
"' and '"
+
RenameEnum
.
PRINTABLE
+
'\''
;
throw
new
IllegalArgumentException
(
s
+
" is unknown for parameter "
+
paramName
+
", possible values are "
+
values
.
toLowerCase
(
Locale
.
ROOT
));
}
return
EnumSet
.
allOf
(
RenameEnum
.
class
);
}
Set
<
RenameEnum
>
set
=
EnumSet
.
noneOf
(
RenameEnum
.
class
);
for
(
String
s
:
value
.
split
(
","
))
{
try
{
set
.
add
(
RenameEnum
.
valueOf
(
s
.
toUpperCase
(
Locale
.
ROOT
)));
}
catch
(
IllegalArgumentException
e
)
{
String
values
=
Arrays
.
stream
(
RenameEnum
.
values
())
.
map
(
v
->
'\''
+
v
.
name
().
toLowerCase
(
Locale
.
ROOT
)
+
'\''
)
.
collect
(
Collectors
.
joining
(
", "
));
throw
new
IllegalArgumentException
(
'\''
+
s
+
"' is unknown for parameter "
+
paramName
+
", possible values are "
+
values
);
}
}
return
set
;
...
...
jadx-cli/src/test/java/jadx/cli/RenameConverterTest.java
View file @
19c57258
...
...
@@ -42,8 +42,8 @@ public class RenameConverterTest {
()
->
converter
.
convert
(
"wrong"
),
"Expected convert() to throw, but it didn't"
);
assertEquals
(
"
wrong
is unknown for parameter someParam, "
+
"possible values are 'case', 'valid'
and
'printable'"
,
assertEquals
(
"
'wrong'
is unknown for parameter someParam, "
+
"possible values are 'case', 'valid'
,
'printable'"
,
thrown
.
getMessage
());
}
}
jadx-core/src/main/java/jadx/api/ResourcesLoader.java
View file @
19c57258
...
...
@@ -98,7 +98,7 @@ public final class ResourcesLoader {
return
ResContainer
.
textResource
(
rf
.
getName
(),
content
);
case
ARSC:
return
new
ResTableParser
().
decodeFiles
(
inputStream
);
return
new
ResTableParser
(
jadxRef
.
getRoot
()
).
decodeFiles
(
inputStream
);
case
IMG:
return
decodeImage
(
rf
,
inputStream
);
...
...
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
19c57258
...
...
@@ -32,7 +32,7 @@ import jadx.core.dex.nodes.InsnNode;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
jadx.core.dex.nodes.parser.FieldInitAttr.InitType
;
import
jadx.core.utils.Code
g
enUtils
;
import
jadx.core.utils.Code
G
enUtils
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.CodegenException
;
...
...
@@ -104,7 +104,7 @@ public class ClassGen {
if
(
cls
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
;
}
Code
g
enUtils
.
addComments
(
code
,
cls
);
Code
G
enUtils
.
addComments
(
code
,
cls
);
insertDecompilationProblems
(
code
,
cls
);
addClassDeclaration
(
code
);
addClassBody
(
code
);
...
...
@@ -299,7 +299,7 @@ public class ClassGen {
}
code
.
add
(
';'
);
}
else
{
Code
g
enUtils
.
addComments
(
code
,
mth
);
Code
G
enUtils
.
addComments
(
code
,
mth
);
insertDecompilationProblems
(
code
,
mth
);
boolean
badCode
=
mth
.
contains
(
AFlag
.
INCONSISTENT_CODE
);
if
(
badCode
&&
showInconsistentCode
)
{
...
...
@@ -356,11 +356,12 @@ public class ClassGen {
if
(
f
.
contains
(
AFlag
.
DONT_GENERATE
))
{
continue
;
}
Code
g
enUtils
.
addComments
(
code
,
f
);
Code
G
enUtils
.
addComments
(
code
,
f
);
annotationGen
.
addForField
(
code
,
f
);
if
(
f
.
getFieldInfo
().
isRenamed
())
{
code
.
startLine
(
"/* renamed from: "
).
add
(
f
.
getName
()).
add
(
" */"
);
code
.
newLine
();
CodeGenUtils
.
addRenamedComment
(
code
,
f
,
f
.
getName
());
}
code
.
startLine
(
f
.
getAccessFlags
().
makeString
());
useType
(
code
,
f
.
getType
());
...
...
@@ -620,7 +621,7 @@ public class ClassGen {
private
void
insertRenameInfo
(
CodeWriter
code
,
ClassNode
cls
)
{
ClassInfo
classInfo
=
cls
.
getClassInfo
();
if
(
classInfo
.
hasAlias
())
{
code
.
startLine
(
"/* renamed from: "
).
add
(
classInfo
.
getType
().
getObject
()).
add
(
" */"
);
CodeGenUtils
.
addRenamedComment
(
code
,
cls
,
classInfo
.
getType
().
getObject
()
);
}
}
...
...
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
View file @
19c57258
...
...
@@ -25,6 +25,7 @@ import jadx.core.dex.nodes.MethodNode;
import
jadx.core.dex.trycatch.CatchAttr
;
import
jadx.core.dex.visitors.DepthTraversal
;
import
jadx.core.dex.visitors.FallbackModeVisitor
;
import
jadx.core.utils.CodeGenUtils
;
import
jadx.core.utils.InsnUtils
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.CodegenException
;
...
...
@@ -84,7 +85,7 @@ public class MethodGen {
}
if
(
mth
.
getMethodInfo
().
isRenamed
()
&&
!
ai
.
isConstructor
())
{
code
.
startLine
(
"/* renamed from: "
).
add
(
mth
.
getName
()).
add
(
" */"
);
CodeGenUtils
.
addRenamedComment
(
code
,
mth
,
mth
.
getName
()
);
}
code
.
startLineWithNum
(
mth
.
getSourceLine
());
code
.
add
(
ai
.
makeString
());
...
...
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
View file @
19c57258
...
...
@@ -129,7 +129,7 @@ public class NameGen {
if
(
NameMapper
.
isReserved
(
varName
))
{
varName
=
varName
+
'R'
;
}
if
(!
NameMapper
.
isValid
Identifier
(
varName
))
{
if
(!
NameMapper
.
isValid
AndPrintable
(
varName
))
{
varName
=
getFallbackName
(
var
);
}
return
varName
;
...
...
jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java
View file @
19c57258
package
jadx
.
core
.
deobf
;
import
java.io.File
;
import
java.nio.file.Path
;
import
java.util.ArrayList
;
import
java.util.Collections
;
...
...
@@ -64,11 +63,6 @@ public class Deobfuscator {
private
int
fldIndex
=
0
;
private
int
mthIndex
=
0
;
@Deprecated
public
Deobfuscator
(
JadxArgs
args
,
@NotNull
List
<
DexNode
>
dexNodes
,
File
deobfMapFile
)
{
this
(
args
,
dexNodes
,
deobfMapFile
.
toPath
());
}
public
Deobfuscator
(
JadxArgs
args
,
@NotNull
List
<
DexNode
>
dexNodes
,
Path
deobfMapFile
)
{
this
.
args
=
args
;
this
.
dexNodes
=
dexNodes
;
...
...
@@ -86,8 +80,20 @@ public class Deobfuscator {
initIndexes
();
}
process
();
}
public
void
savePresets
()
{
deobfPresets
.
save
(
args
.
isDeobfuscationForceSave
());
clear
();
}
public
void
clear
()
{
deobfPresets
.
clear
();
clsMap
.
clear
();
fldMap
.
clear
();
mthMap
.
clear
();
ovrd
.
clear
();
ovrdMap
.
clear
();
}
private
void
initIndexes
()
{
...
...
@@ -148,16 +154,6 @@ public class Deobfuscator {
}
}
void
clear
()
{
deobfPresets
.
clear
();
clsMap
.
clear
();
fldMap
.
clear
();
mthMap
.
clear
();
ovrd
.
clear
();
ovrdMap
.
clear
();
}
private
void
resolveOverriding
(
MethodNode
mth
)
{
Set
<
ClassNode
>
clsParents
=
new
LinkedHashSet
<>();
collectClassHierarchy
(
mth
.
getParentClass
(),
clsParents
);
...
...
@@ -241,7 +237,7 @@ public class Deobfuscator {
}
else
if
(!
clsInfo
.
isInner
())
{
// check if package renamed
PackageNode
pkgNode
=
getPackageNode
(
clsInfo
.
getPackage
(),
false
);
if
(
pkgNode
.
hasAnyAlias
())
{
if
(
pkgNode
!=
null
&&
pkgNode
.
hasAnyAlias
())
{
clsInfo
.
changePkg
(
pkgNode
.
getFullAlias
());
}
}
...
...
@@ -259,7 +255,7 @@ public class Deobfuscator {
}
}
p
ublic
void
renameField
(
FieldNode
field
)
{
p
rivate
void
renameField
(
FieldNode
field
)
{
FieldInfo
fieldInfo
=
field
.
getFieldInfo
();
String
alias
=
getFieldAlias
(
field
);
if
(
alias
!=
null
)
{
...
...
@@ -271,7 +267,7 @@ public class Deobfuscator {
field
.
getFieldInfo
().
setAlias
(
makeFieldAlias
(
field
));
}
p
ublic
void
renameMethod
(
MethodNode
mth
)
{
p
rivate
void
renameMethod
(
MethodNode
mth
)
{
String
alias
=
getMethodAlias
(
mth
);
if
(
alias
!=
null
)
{
mth
.
getMethodInfo
().
setAlias
(
alias
);
...
...
@@ -408,7 +404,7 @@ public class Deobfuscator {
}
else
if
(
name
.
endsWith
(
".kt"
))
{
name
=
name
.
substring
(
0
,
name
.
length
()
-
".kt"
.
length
());
}
if
(!
NameMapper
.
isValid
Identifier
(
name
)
||
!
NameMapper
.
isAllChars
Printable
(
name
))
{
if
(!
NameMapper
.
isValid
And
Printable
(
name
))
{
return
null
;
}
for
(
DeobfClsInfo
deobfClsInfo
:
clsMap
.
values
())
{
...
...
@@ -500,8 +496,7 @@ public class Deobfuscator {
private
boolean
shouldRename
(
String
s
)
{
int
len
=
s
.
length
();
return
len
<
minLength
||
len
>
maxLength
||
!
NameMapper
.
isValidIdentifier
(
s
);
return
len
<
minLength
||
len
>
maxLength
;
}
private
String
prepareNamePart
(
String
name
)
{
...
...
jadx-core/src/main/java/jadx/core/deobf/NameMapper.java
View file @
19c57258
...
...
@@ -87,6 +87,10 @@ public class NameMapper {
&&
VALID_JAVA_FULL_IDENTIFIER
.
matcher
(
str
).
matches
();
}
public
static
boolean
isValidAndPrintable
(
String
str
)
{
return
isValidIdentifier
(
str
)
&&
isAllCharsPrintable
(
str
);
}
public
static
boolean
isValidIdentifierStart
(
int
codePoint
)
{
return
Character
.
isJavaIdentifierStart
(
codePoint
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
View file @
19c57258
...
...
@@ -17,6 +17,7 @@ import jadx.core.dex.attributes.nodes.LoopLabelAttr;
import
jadx.core.dex.attributes.nodes.MethodInlineAttr
;
import
jadx.core.dex.attributes.nodes.PhiListAttr
;
import
jadx.core.dex.attributes.nodes.RegDebugInfoAttr
;
import
jadx.core.dex.attributes.nodes.RenameReasonAttr
;
import
jadx.core.dex.attributes.nodes.SourceFileAttr
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
jadx.core.dex.trycatch.CatchAttr
;
...
...
@@ -55,6 +56,7 @@ public class AType<T extends IAttribute> {
public
static
final
AType
<
DeclareVariablesAttr
>
DECLARE_VARIABLES
=
new
AType
<>();
public
static
final
AType
<
LoopLabelAttr
>
LOOP_LABEL
=
new
AType
<>();
public
static
final
AType
<
IgnoreEdgeAttr
>
IGNORE_EDGE
=
new
AType
<>();
public
static
final
AType
<
RenameReasonAttr
>
RENAME_REASON
=
new
AType
<>();
// method
public
static
final
AType
<
LocalVarsDebugInfoAttr
>
LOCAL_VARS_DEBUG_INFO
=
new
AType
<>();
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/nodes/RenameReasonAttr.java
0 → 100644
View file @
19c57258
package
jadx
.
core
.
dex
.
attributes
.
nodes
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AttrNode
;
import
jadx.core.dex.attributes.IAttribute
;
public
class
RenameReasonAttr
implements
IAttribute
{
private
String
description
;
public
RenameReasonAttr
()
{
this
.
description
=
""
;
}
public
RenameReasonAttr
(
String
description
)
{
this
.
description
=
description
;
}
public
RenameReasonAttr
(
AttrNode
node
)
{
RenameReasonAttr
renameReasonAttr
=
node
.
get
(
AType
.
RENAME_REASON
);
if
(
renameReasonAttr
!=
null
)
{
this
.
description
=
renameReasonAttr
.
description
;
}
else
{
this
.
description
=
""
;
}
}
public
RenameReasonAttr
(
AttrNode
node
,
boolean
notValid
,
boolean
notPrintable
)
{
this
(
node
);
if
(
notValid
)
{
notValid
();
}
if
(
notPrintable
)
{
notPrintable
();
}
}
private
RenameReasonAttr
notValid
()
{
return
append
(
"not valid java name"
);
}
private
RenameReasonAttr
notPrintable
()
{
return
append
(
"contains not printable characters"
);
}
public
RenameReasonAttr
append
(
String
reason
)
{
if
(
description
.
isEmpty
())
{
description
+=
reason
;
}
else
{
description
+=
" and "
+
reason
;
}
return
this
;
}
public
String
getDescription
()
{
return
description
;
}
@Override
public
AType
<
RenameReasonAttr
>
getType
()
{
return
AType
.
RENAME_REASON
;
}
@Override
public
String
toString
()
{
return
"RENAME_REASON:"
+
description
;
}
}
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
View file @
19c57258
...
...
@@ -87,7 +87,7 @@ public class RootNode {
}
try
{
ResourceStorage
resStorage
=
ResourcesLoader
.
decodeStream
(
arsc
,
(
size
,
is
)
->
{
ResTableParser
parser
=
new
ResTableParser
();
ResTableParser
parser
=
new
ResTableParser
(
this
);
parser
.
decode
(
is
);
return
parser
.
getResStorage
();
});
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
View file @
19c57258
...
...
@@ -212,17 +212,19 @@ public class ClassModifier extends AbstractVisitor {
}
private
static
boolean
removeBridgeMethod
(
ClassNode
cls
,
MethodNode
mth
)
{
List
<
InsnNode
>
allInsns
=
BlockUtils
.
collectAllInsns
(
mth
.
getBasicBlocks
());
if
(
allInsns
.
size
()
==
1
)
{
InsnNode
wrappedInsn
=
allInsns
.
get
(
0
);
if
(
wrappedInsn
.
getType
()
==
InsnType
.
RETURN
)
{
InsnArg
arg
=
wrappedInsn
.
getArg
(
0
);
if
(
arg
.
isInsnWrap
())
{
wrappedInsn
=
((
InsnWrapArg
)
arg
).
getWrapInsn
();
if
(
cls
.
root
().
getArgs
().
isRenameValid
())
{
List
<
InsnNode
>
allInsns
=
BlockUtils
.
collectAllInsns
(
mth
.
getBasicBlocks
());
if
(
allInsns
.
size
()
==
1
)
{
InsnNode
wrappedInsn
=
allInsns
.
get
(
0
);
if
(
wrappedInsn
.
getType
()
==
InsnType
.
RETURN
)
{
InsnArg
arg
=
wrappedInsn
.
getArg
(
0
);
if
(
arg
.
isInsnWrap
())
{
wrappedInsn
=
((
InsnWrapArg
)
arg
).
getWrapInsn
();
}
}
if
(
checkSyntheticWrapper
(
mth
,
wrappedInsn
))
{
return
true
;
}
}
if
(
checkSyntheticWrapper
(
mth
,
wrappedInsn
))
{
return
true
;
}
}
return
!
isMethodUnique
(
cls
,
mth
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java
View file @
19c57258
...
...
@@ -152,8 +152,8 @@ public class EnumVisitor extends AbstractVisitor {
String
name
=
getConstString
(
cls
.
dex
(),
co
.
getArg
(
0
));
if
(
name
!=
null
&&
!
fieldInfo
.
getAlias
().
equals
(
name
)
&&
NameMapper
.
isValid
Identifier
(
name
))
{
// LOG.debug("Rename enum field: '{}' to '{}' in {}", fieldInfo.getName(), name, cls);
&&
NameMapper
.
isValid
AndPrintable
(
name
)
&&
cls
.
root
().
getArgs
().
isRenameValid
())
{
fieldInfo
.
setAlias
(
name
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
View file @
19c57258
...
...
@@ -12,6 +12,7 @@ import jadx.core.Consts;
import
jadx.core.deobf.Deobfuscator
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.nodes.RenameReasonAttr
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.info.FieldInfo
;
...
...
@@ -24,8 +25,6 @@ import jadx.core.utils.files.InputFile;
public
class
RenameVisitor
extends
AbstractVisitor
{
private
Deobfuscator
deobfuscator
;
@Override
public
void
init
(
RootNode
root
)
{
List
<
DexNode
>
dexNodes
=
root
.
getDexNodes
();
...
...
@@ -36,24 +35,29 @@ public class RenameVisitor extends AbstractVisitor {
Path
inputFilePath
=
firstInputFile
.
getFile
().
toPath
();
String
inputName
=
inputFilePath
.
getFileName
().
toString
();
inputName
=
inputName
.
substring
(
0
,
inputName
.
lastIndexOf
(
'.'
));
String
baseName
=
inputName
.
substring
(
0
,
inputName
.
lastIndexOf
(
'.'
));
Path
deobfMapPath
=
inputFilePath
.
getParent
().
resolve
(
baseName
+
".jobf"
);
Path
deobfMapPath
=
inputFilePath
.
getParent
().
resolve
(
inputName
+
".jobf"
);
JadxArgs
args
=
root
.
getArgs
();
deobfuscator
=
new
Deobfuscator
(
args
,
dexNodes
,
deobfMapPath
);
boolean
deobfuscationOn
=
args
.
isDeobfuscationOn
();
if
(
deobfuscationOn
)
{
Deobfuscator
deobfuscator
=
new
Deobfuscator
(
args
,
dexNodes
,
deobfMapPath
);
if
(
args
.
isDeobfuscationOn
())
{
deobfuscator
.
execute
();
}
checkClasses
(
root
,
args
);
checkClasses
(
deobfuscator
,
root
,
args
);
if
(
args
.
isDeobfuscationOn
())
{
deobfuscator
.
savePresets
();
deobfuscator
.
clear
();
}
}
private
void
checkClasses
(
RootNode
root
,
JadxArgs
args
)
{
private
static
void
checkClasses
(
Deobfuscator
deobfuscator
,
RootNode
root
,
JadxArgs
args
)
{
List
<
ClassNode
>
classes
=
root
.
getClasses
(
true
);
for
(
ClassNode
cls
:
classes
)
{
checkClassName
(
cls
,
args
);
checkFields
(
cls
,
args
);
checkMethods
(
cls
,
args
);
checkClassName
(
deobfuscator
,
cls
,
args
);
checkFields
(
deobfuscator
,
cls
,
args
);
checkMethods
(
deobfuscator
,
cls
,
args
);
}
if
(!
args
.
isFsCaseSensitive
()
&&
args
.
isRenameCaseSensitive
())
{
Set
<
String
>
clsFullPaths
=
new
HashSet
<>(
classes
.
size
());
...
...
@@ -62,20 +66,22 @@ public class RenameVisitor extends AbstractVisitor {
if
(!
clsFullPaths
.
add
(
clsInfo
.
getAliasFullPath
().
toLowerCase
()))
{
String
newShortName
=
deobfuscator
.
getClsAlias
(
cls
);
clsInfo
.
changeShortName
(
newShortName
);
cls
.
addAttr
(
new
RenameReasonAttr
(
cls
).
append
(
"case insensitive filesystem"
));
clsFullPaths
.
add
(
clsInfo
.
getAliasFullPath
().
toLowerCase
());
}
}
}
processRootPackages
(
root
,
classes
);
processRootPackages
(
deobfuscator
,
root
,
classes
);
}
private
void
checkClassName
(
ClassNode
cls
,
JadxArgs
args
)
{
private
static
void
checkClassName
(
Deobfuscator
deobfuscator
,
ClassNode
cls
,
JadxArgs
args
)
{
ClassInfo
classInfo
=
cls
.
getClassInfo
();
String
clsName
=
classInfo
.
getAliasShortName
();
String
newShortName
=
fixClsShortName
(
args
,
clsName
);
if
(!
newShortName
.
equals
(
clsName
))
{
classInfo
.
changeShortName
(
newShortName
);
cls
.
addAttr
(
new
RenameReasonAttr
(
cls
).
append
(
"invalid class name"
));
}
if
(
args
.
isRenameValid
())
{
if
(
classInfo
.
isInner
())
{
...
...
@@ -84,6 +90,7 @@ public class RenameVisitor extends AbstractVisitor {
if
(
parentClass
.
getAliasShortName
().
equals
(
clsName
))
{
String
clsAlias
=
deobfuscator
.
getClsAlias
(
cls
);
classInfo
.
changeShortName
(
clsAlias
);
cls
.
addAttr
(
new
RenameReasonAttr
(
cls
).
append
(
"collision with other inner class name"
));
break
;
}
parentClass
=
parentClass
.
getParentClass
();
...
...
@@ -91,12 +98,13 @@ public class RenameVisitor extends AbstractVisitor {
}
else
{
if
(
classInfo
.
getAliasPkg
().
isEmpty
())
{
classInfo
.
changePkg
(
Consts
.
DEFAULT_PACKAGE_NAME
);
cls
.
addAttr
(
new
RenameReasonAttr
(
cls
).
append
(
"default package"
));
}
}
}
}
private
String
fixClsShortName
(
JadxArgs
args
,
String
clsName
)
{
private
static
String
fixClsShortName
(
JadxArgs
args
,
String
clsName
)
{
char
firstChar
=
clsName
.
charAt
(
0
);
boolean
renameValid
=
args
.
isRenameValid
();
if
(
Character
.
isDigit
(
firstChar
)
&&
renameValid
)
{
...
...
@@ -114,25 +122,33 @@ public class RenameVisitor extends AbstractVisitor {
return
cleanClsName
;
}
private
void
checkFields
(
ClassNode
cls
,
JadxArgs
args
)
{
private
static
void
checkFields
(
Deobfuscator
deobfuscator
,
ClassNode
cls
,
JadxArgs
args
)
{
Set
<
String
>
names
=
new
HashSet
<>();
for
(
FieldNode
field
:
cls
.
getFields
())
{
FieldInfo
fieldInfo
=
field
.
getFieldInfo
();
String
fieldName
=
fieldInfo
.
getAlias
();
if
(!
names
.
add
(
fieldName
)
||
(
args
.
isRenameValid
()
&&
!
NameMapper
.
isValidIdentifier
(
fieldName
))
||
(
args
.
isRenamePrintable
()
&&
!
NameMapper
.
isAllCharsPrintable
(
fieldName
)))
{
boolean
notUnique
=
!
names
.
add
(
fieldName
);
boolean
notValid
=
args
.
isRenameValid
()
&&
!
NameMapper
.
isValidIdentifier
(
fieldName
);
boolean
notPrintable
=
args
.
isRenamePrintable
()
&&
!
NameMapper
.
isAllCharsPrintable
(
fieldName
);
if
(
notUnique
||
notValid
||
notPrintable
)
{
deobfuscator
.
forceRenameField
(
field
);
field
.
addAttr
(
new
RenameReasonAttr
(
field
,
notValid
,
notPrintable
));
if
(
notUnique
)
{
field
.
addAttr
(
new
RenameReasonAttr
(
field
).
append
(
"collision with other field name"
));
}
}
}
}
private
void
checkMethods
(
ClassNode
cls
,
JadxArgs
args
)
{
private
static
void
checkMethods
(
Deobfuscator
deobfuscator
,
ClassNode
cls
,
JadxArgs
args
)
{
for
(
MethodNode
mth
:
cls
.
getMethods
())
{
String
alias
=
mth
.
getAlias
();
if
(
args
.
isRenameValid
()
&&
!
NameMapper
.
isValidIdentifier
(
alias
)
||
(
args
.
isRenamePrintable
()
&&
!
NameMapper
.
isAllCharsPrintable
(
alias
)))
{
boolean
notValid
=
args
.
isRenameValid
()
&&
!
NameMapper
.
isValidIdentifier
(
alias
);
boolean
notPrintable
=
args
.
isRenamePrintable
()
&&
!
NameMapper
.
isAllCharsPrintable
(
alias
);
if
(
notValid
||
notPrintable
)
{
deobfuscator
.
forceRenameMethod
(
mth
);
mth
.
addAttr
(
new
RenameReasonAttr
(
mth
,
notValid
,
notPrintable
));
}
}
Set
<
String
>
names
=
new
HashSet
<>();
...
...
@@ -147,11 +163,12 @@ public class RenameVisitor extends AbstractVisitor {
String
signature
=
mth
.
getMethodInfo
().
makeSignature
(
true
,
false
);
if
(!
names
.
add
(
signature
))
{
deobfuscator
.
forceRenameMethod
(
mth
);
mth
.
addAttr
(
new
RenameReasonAttr
(
"collision with other method in class"
));
}
}
}
private
void
processRootPackages
(
RootNode
root
,
List
<
ClassNode
>
classes
)
{
private
static
void
processRootPackages
(
Deobfuscator
deobfuscator
,
RootNode
root
,
List
<
ClassNode
>
classes
)
{
Set
<
String
>
rootPkgs
=
collectRootPkgs
(
classes
);
root
.
getCacheStorage
().
setRootPkgs
(
rootPkgs
);
...
...
@@ -161,6 +178,7 @@ public class RenameVisitor extends AbstractVisitor {
for
(
FieldNode
field
:
cls
.
getFields
())
{
if
(
rootPkgs
.
contains
(
field
.
getAlias
()))
{
deobfuscator
.
forceRenameField
(
field
);
field
.
addAttr
(
new
RenameReasonAttr
(
"collision with root package name"
));
}
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java
View file @
19c57258
...
...
@@ -147,7 +147,7 @@ public class DebugInfoApplyVisitor extends AbstractVisitor {
LOG
.
debug
(
"Reject debug info of type: {} and name: '{}' for {}, mth: {}"
,
type
,
varName
,
ssaVar
,
mth
);
}
}
else
{
if
(
NameMapper
.
isValid
Identifier
(
varName
))
{
if
(
NameMapper
.
isValid
AndPrintable
(
varName
))
{
ssaVar
.
setName
(
varName
);
}
detachDebugInfo
(
ssaVar
.
getAssign
());
...
...
jadx-core/src/main/java/jadx/core/utils/Code
g
enUtils.java
→
jadx-core/src/main/java/jadx/core/utils/Code
G
enUtils.java
View file @
19c57258
...
...
@@ -5,8 +5,9 @@ import java.util.List;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AttrNode
;
import
jadx.core.dex.attributes.nodes.RenameReasonAttr
;
public
class
Code
g
enUtils
{
public
class
Code
G
enUtils
{
public
static
void
addComments
(
CodeWriter
code
,
AttrNode
node
)
{
List
<
String
>
comments
=
node
.
getAll
(
AType
.
COMMENTS
);
...
...
@@ -15,4 +16,17 @@ public class CodegenUtils {
.
forEach
(
comment
->
code
.
startLine
(
"/* "
).
addMultiLine
(
comment
).
add
(
" */"
));
}
}
public
static
void
addRenamedComment
(
CodeWriter
code
,
AttrNode
node
,
String
origName
)
{
code
.
startLine
(
"/* renamed from: "
).
add
(
origName
);
RenameReasonAttr
renameReasonAttr
=
node
.
get
(
AType
.
RENAME_REASON
);
if
(
renameReasonAttr
!=
null
)
{
code
.
add
(
" reason: "
);
code
.
add
(
renameReasonAttr
.
getDescription
());
}
code
.
add
(
" */"
);
}
private
CodeGenUtils
()
{
}
}
jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java
View file @
19c57258
...
...
@@ -124,7 +124,8 @@ public class AndroidResourcesUtils {
FieldNode
fieldNode
=
resFieldsMap
.
get
(
resource
.
getId
());
if
(
fieldNode
!=
null
&&
!
fieldNode
.
getName
().
equals
(
resName
)
&&
NameMapper
.
isValidIdentifier
(
resName
))
{
&&
NameMapper
.
isValidAndPrintable
(
resName
)
&&
resCls
.
root
().
getArgs
().
isRenameValid
())
{
fieldNode
.
add
(
AFlag
.
DONT_RENAME
);
fieldNode
.
getFieldInfo
().
setAlias
(
resName
);
}
...
...
jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
View file @
19c57258
...
...
@@ -115,7 +115,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
break
;
case
RES_STRING_POOL_TYPE:
strings
=
parseStringPoolNoType
();
valuesParser
=
new
ValuesParser
(
strings
,
resNames
);
valuesParser
=
new
ValuesParser
(
rootNode
,
strings
,
resNames
);
break
;
case
RES_XML_RESOURCE_MAP_TYPE:
parseResourceMap
();
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java
View file @
19c57258
...
...
@@ -11,6 +11,9 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.xmlgen.entry.EntryConfig
;
import
jadx.core.xmlgen.entry.RawNamedValue
;
import
jadx.core.xmlgen.entry.RawValue
;
...
...
@@ -50,8 +53,13 @@ public class ResTableParser extends CommonBinaryParser {
}
}
private
String
[]
strings
;
private
final
RootNode
root
;
private
final
ResourceStorage
resStorage
=
new
ResourceStorage
();
private
String
[]
strings
;
public
ResTableParser
(
RootNode
root
)
{
this
.
root
=
root
;
}
public
void
decode
(
InputStream
inputStream
)
throws
IOException
{
is
=
new
ParserStream
(
inputStream
);
...
...
@@ -62,7 +70,7 @@ public class ResTableParser extends CommonBinaryParser {
public
ResContainer
decodeFiles
(
InputStream
inputStream
)
throws
IOException
{
decode
(
inputStream
);
ValuesParser
vp
=
new
ValuesParser
(
strings
,
resStorage
.
getResourcesNames
());
ValuesParser
vp
=
new
ValuesParser
(
root
,
strings
,
resStorage
.
getResourcesNames
());
ResXmlGen
resGen
=
new
ResXmlGen
(
resStorage
,
vp
);
CodeWriter
content
=
makeXmlDump
();
...
...
@@ -222,7 +230,13 @@ public class ResTableParser extends CommonBinaryParser {
String
typeName
=
pkg
.
getTypeStrings
()[
typeId
-
1
];
String
keyName
=
pkg
.
getKeyStrings
()[
key
];
if
(
keyName
.
isEmpty
())
{
keyName
=
"RES_"
+
resRef
;
// autogenerate key name
FieldNode
constField
=
root
.
getConstValues
().
getGlobalConstFields
().
get
(
resRef
);
if
(
constField
!=
null
)
{
keyName
=
constField
.
getName
();
constField
.
add
(
AFlag
.
DONT_RENAME
);
}
else
{
keyName
=
"RES_"
+
resRef
;
// autogenerate key name
}
}
ResourceEntry
ri
=
new
ResourceEntry
(
resRef
,
pkg
.
getName
(),
typeName
,
keyName
);
ri
.
setConfig
(
config
);
...
...
jadx-core/src/main/java/jadx/core/xmlgen/entry/ValuesParser.java
View file @
19c57258
...
...
@@ -13,6 +13,7 @@ import org.jetbrains.annotations.Nullable;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.xmlgen.ParserConstants
;
import
jadx.core.xmlgen.ResTableParser
;
...
...
@@ -25,22 +26,22 @@ public class ValuesParser extends ParserConstants {
private
final
String
[]
strings
;
private
final
Map
<
Integer
,
String
>
resMap
;
public
ValuesParser
(
String
[]
strings
,
Map
<
Integer
,
String
>
resMap
)
{
public
ValuesParser
(
RootNode
root
,
String
[]
strings
,
Map
<
Integer
,
String
>
resMap
)
{
this
.
strings
=
strings
;
this
.
resMap
=
resMap
;
if
(
androidStrings
==
null
&&
androidResMap
==
null
)
{
try
{
decodeAndroid
();
decodeAndroid
(
root
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to decode Android Resource file"
,
e
);
}
}
}
private
static
void
decodeAndroid
()
throws
IOException
{
private
static
void
decodeAndroid
(
RootNode
root
)
throws
IOException
{
InputStream
inputStream
=
new
BufferedInputStream
(
ValuesParser
.
class
.
getResourceAsStream
(
"/resources.arsc"
));
ResTableParser
androidParser
=
new
ResTableParser
();
ResTableParser
androidParser
=
new
ResTableParser
(
root
);
androidParser
.
decode
(
inputStream
);
androidStrings
=
androidParser
.
getStrings
();
androidResMap
=
androidParser
.
getResStorage
().
getResourcesNames
();
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
View file @
19c57258
...
...
@@ -278,6 +278,14 @@ public class JadxSettings extends JadxCLIArgs {
this
.
deobfuscationUseSourceNameAsAlias
=
deobfuscationUseSourceNameAsAlias
;
}
public
void
updateRenameFlag
(
JadxArgs
.
RenameEnum
flag
,
boolean
enabled
)
{
if
(
enabled
)
{
renameFlags
.
add
(
flag
);
}
else
{
renameFlags
.
remove
(
flag
);
}
}
public
void
setEscapeUnicode
(
boolean
escapeUnicode
)
{
this
.
escapeUnicode
=
escapeUnicode
;
}
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
View file @
19c57258
...
...
@@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory;
import
say.swing.JFontChooser
;
import
jadx.api.JadxArgs
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.codearea.EditorTheme
;
import
jadx.gui.utils.FontUtils
;
...
...
@@ -184,21 +185,21 @@ public class JadxSettingsWindow extends JDialog {
JCheckBox
renameCaseSensitive
=
new
JCheckBox
();
renameCaseSensitive
.
setSelected
(
settings
.
isRenameCaseSensitive
());
renameCaseSensitive
.
addItemListener
(
e
->
{
settings
.
setRenameCaseSensitive
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
updateRenameFlag
(
JadxArgs
.
RenameEnum
.
CASE
,
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
});
JCheckBox
renameValid
=
new
JCheckBox
();
renameValid
.
setSelected
(
settings
.
isRenameValid
());
renameValid
.
addItemListener
(
e
->
{
settings
.
setRenameValid
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
updateRenameFlag
(
JadxArgs
.
RenameEnum
.
VALID
,
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
});
JCheckBox
renamePrintable
=
new
JCheckBox
();
renamePrintable
.
setSelected
(
settings
.
isRenamePrintable
());
renamePrintable
.
addItemListener
(
e
->
{
settings
.
setRenamePrintable
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
settings
.
updateRenameFlag
(
JadxArgs
.
RenameEnum
.
PRINTABLE
,
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
});
...
...
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