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
716db8b9
Commit
716db8b9
authored
Dec 24, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
manifest: restore application references and Android values (enums, flags)
parent
b55975a3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1913 additions
and
56 deletions
+1913
-56
JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+3
-2
CodeWriter.java
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
+4
-0
RootNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+4
-0
BinaryXMLParser.java
...-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
+78
-54
ManifestAttributes.java
...re/src/main/java/jadx/core/xmlgen/ManifestAttributes.java
+159
-0
attrs_manifest.xml
jadx-core/src/main/resources/attrs_manifest.xml
+1665
-0
No files found.
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
View file @
716db8b9
...
@@ -203,20 +203,21 @@ public final class JadxDecompiler {
...
@@ -203,20 +203,21 @@ public final class JadxDecompiler {
reset
();
reset
();
root
=
new
RootNode
();
root
=
new
RootNode
();
LOG
.
info
(
"loading ..."
);
LOG
.
info
(
"loading ..."
);
root
.
load
(
inputFiles
);
if
(
this
.
args
.
isXMLTest
())
{
if
(
this
.
args
.
isXMLTest
())
{
InputFile
inf
=
inputFiles
.
get
(
0
);
InputFile
inf
=
inputFiles
.
get
(
0
);
try
{
try
{
byte
[]
buffer
=
InputFile
.
loadXMLBuffer
(
inf
.
getFile
());
byte
[]
buffer
=
InputFile
.
loadXMLBuffer
(
inf
.
getFile
());
if
(
buffer
!=
null
)
{
if
(
buffer
!=
null
)
{
File
out
=
new
File
(
args
.
getOutDir
(),
"AndroidManifest.xml"
);
File
out
=
new
File
(
args
.
getOutDir
(),
"AndroidManifest.xml"
);
BinaryXMLParser
bxp
=
new
BinaryXMLParser
();
BinaryXMLParser
bxp
=
new
BinaryXMLParser
(
root
);
bxp
.
parse
(
buffer
,
out
);
bxp
.
parse
(
buffer
,
out
);
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
info
(
"Decompiling AndroidManifest.xml failed!"
,
e
);
LOG
.
info
(
"Decompiling AndroidManifest.xml failed!"
,
e
);
}
}
}
}
root
.
load
(
inputFiles
);
}
}
void
processClass
(
ClassNode
cls
)
{
void
processClass
(
ClassNode
cls
)
{
...
...
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
View file @
716db8b9
...
@@ -174,6 +174,10 @@ public class CodeWriter {
...
@@ -174,6 +174,10 @@ public class CodeWriter {
updateIndent
();
updateIndent
();
}
}
public
int
getIndent
()
{
return
indent
;
}
public
int
getLine
()
{
public
int
getLine
()
{
return
line
;
return
line
;
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
View file @
716db8b9
...
@@ -104,6 +104,10 @@ public class RootNode {
...
@@ -104,6 +104,10 @@ public class RootNode {
return
searchClassByName
(
fullName
);
return
searchClassByName
(
fullName
);
}
}
public
List
<
DexNode
>
getDexNodes
()
{
return
dexNodes
;
}
public
ErrorsCounter
getErrorsCounter
()
{
public
ErrorsCounter
getErrorsCounter
()
{
return
errorsCounter
;
return
errorsCounter
;
}
}
...
...
jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
View file @
716db8b9
package
jadx
.
core
.
xmlgen
;
package
jadx
.
core
.
xmlgen
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.io.File
;
import
java.io.File
;
...
@@ -40,16 +44,28 @@ public class BinaryXMLParser {
...
@@ -40,16 +44,28 @@ public class BinaryXMLParser {
private
boolean
wasOneLiner
=
false
;
private
boolean
wasOneLiner
=
false
;
private
CodeWriter
writer
;
private
CodeWriter
writer
;
private
Map
<
Integer
,
String
>
styleMap
=
null
;
private
Map
<
Integer
,
String
>
styleMap
=
new
HashMap
<
Integer
,
String
>();
private
Map
<
Integer
,
FieldNode
>
localStyleMap
=
new
HashMap
<
Integer
,
FieldNode
>();
private
final
ManifestAttributes
attributes
;
public
BinaryXMLParser
()
{
public
BinaryXMLParser
(
RootNode
root
)
{
styleMap
=
new
HashMap
<
Integer
,
String
>();
try
{
try
{
for
(
Field
f
:
AndroidR
.
style
.
class
.
getFields
())
{
for
(
Field
f
:
AndroidR
.
style
.
class
.
getFields
())
{
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
styleMap
.
put
(
f
.
getInt
(
f
.
getType
()),
f
.
getName
());
}
}
//TODO: also add application constant fields
// add application constants
}
catch
(
IllegalAccessException
e
)
{
for
(
DexNode
dexNode
:
root
.
getDexNodes
())
{
for
(
Map
.
Entry
<
Object
,
FieldNode
>
entry
:
dexNode
.
getConstFields
().
entrySet
())
{
Object
key
=
entry
.
getKey
();
FieldNode
field
=
entry
.
getValue
();
if
(
field
.
getType
().
equals
(
ArgType
.
INT
)
&&
key
instanceof
Integer
)
{
localStyleMap
.
put
((
Integer
)
key
,
field
);
}
}
}
attributes
=
new
ManifestAttributes
();
attributes
.
parse
();
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"BinaryXMLParser init error"
,
e
);
throw
new
JadxRuntimeException
(
"BinaryXMLParser init error"
,
e
);
}
}
}
}
...
@@ -194,7 +210,7 @@ public class BinaryXMLParser {
...
@@ -194,7 +210,7 @@ public class BinaryXMLParser {
}
}
wasOneLiner
=
false
;
wasOneLiner
=
false
;
currentTag
=
strings
[
startNSName
];
currentTag
=
strings
[
startNSName
];
writer
.
startLine
(
"<"
+
strings
[
startNSName
]);
writer
.
startLine
(
"<"
).
add
(
strings
[
startNSName
]);
int
attributeStart
=
cInt16
(
bytes
,
count
);
int
attributeStart
=
cInt16
(
bytes
,
count
);
if
(
attributeStart
!=
0x14
)
{
if
(
attributeStart
!=
0x14
)
{
die
(
"startNS's attributeStart is not 0x14"
);
die
(
"startNS's attributeStart is not 0x14"
);
...
@@ -208,7 +224,7 @@ public class BinaryXMLParser {
...
@@ -208,7 +224,7 @@ public class BinaryXMLParser {
int
classIndex
=
cInt16
(
bytes
,
count
);
int
classIndex
=
cInt16
(
bytes
,
count
);
int
styleIndex
=
cInt16
(
bytes
,
count
);
int
styleIndex
=
cInt16
(
bytes
,
count
);
if
(
"manifest"
.
equals
(
strings
[
startNSName
]))
{
if
(
"manifest"
.
equals
(
strings
[
startNSName
]))
{
writer
.
add
(
" xmlns:\""
+
nsURI
+
"\""
);
writer
.
add
(
" xmlns:\""
).
add
(
nsURI
).
add
(
"\""
);
}
}
if
(
attributeCount
>
0
)
{
if
(
attributeCount
>
0
)
{
writer
.
add
(
" "
);
writer
.
add
(
" "
);
...
@@ -227,53 +243,59 @@ public class BinaryXMLParser {
...
@@ -227,53 +243,59 @@ public class BinaryXMLParser {
int
attrValDataType
=
cInt8
(
bytes
,
count
);
int
attrValDataType
=
cInt8
(
bytes
,
count
);
int
attrValData
=
cInt32
(
bytes
,
count
);
int
attrValData
=
cInt32
(
bytes
,
count
);
if
(
attributeNS
!=
-
1
)
{
if
(
attributeNS
!=
-
1
)
{
writer
.
add
(
nsPrefix
+
":"
);
writer
.
add
(
nsPrefix
).
add
(
':'
);
}
}
writer
.
add
(
strings
[
attributeName
]
+
"=\""
);
String
attrName
=
strings
[
attributeName
];
if
(
attrValDataType
==
0x3
)
{
writer
.
add
(
attrName
).
add
(
"=\""
);
writer
.
add
(
strings
[
attrValData
]);
String
decodedAttr
=
attributes
.
decode
(
attrName
,
attrValData
);
}
else
if
(
attrValDataType
==
0x10
)
{
if
(
decodedAttr
!=
null
)
{
writer
.
add
(
String
.
valueOf
(
attrValData
));
writer
.
add
(
decodedAttr
);
}
else
if
(
attrValDataType
==
0x12
)
{
// FIXME: What to do, when data is always -1?
if
(
attrValData
==
0
)
{
writer
.
add
(
"false"
);
}
else
if
(
attrValData
==
1
||
attrValData
==
-
1
)
{
writer
.
add
(
"true"
);
}
else
{
writer
.
add
(
"UNKNOWN_BOOLEAN_TYPE"
);
}
}
else
if
(
attrValDataType
==
0x1
)
{
String
name
=
styleMap
.
get
(
attrValData
);
if
(
name
!=
null
)
{
writer
.
add
(
"@*"
);
if
(
attributeNS
!=
-
1
)
{
writer
.
add
(
nsPrefix
+
":"
);
}
writer
.
add
(
"style/"
+
name
.
replaceAll
(
"_"
,
"."
));
}
else
{
writer
.
add
(
"0x"
+
Integer
.
toHexString
(
attrValData
));
}
}
else
{
}
else
{
// TODO: extract values names from here:
switch
(
attrValDataType
)
{
// https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/attrs_manifest.xml
case
0x3
:
if
(
"configChanges"
.
equals
(
strings
[
attributeName
]))
{
writer
.
add
(
strings
[
attrValData
]);
if
(
attrValData
==
1152
)
{
break
;
writer
.
add
(
"orientation"
);
}
else
if
(
attrValData
==
4016
)
{
case
0x10
:
writer
.
add
(
"keyboard|keyboardHidden|orientation|screenLayout|uiMode"
);
writer
.
add
(
String
.
valueOf
(
attrValData
));
}
else
if
(
attrValData
==
176
)
{
break
;
writer
.
add
(
"keyboard|keyboardHidden|orientation"
);
}
else
if
(
attrValData
==
160
)
{
case
0x12
:
writer
.
add
(
"keyboardHidden|orientation"
);
// FIXME: What to do, when data is always -1?
}
else
{
if
(
attrValData
==
0
)
{
writer
.
add
(
"UNKNOWN_DATA_"
+
Integer
.
toHexString
(
attrValData
));
writer
.
add
(
"false"
);
}
}
else
if
(
attrValData
==
1
||
attrValData
==
-
1
)
{
}
else
{
writer
.
add
(
"true"
);
writer
.
add
(
"UNKNOWN_DATA_TYPE_"
+
attrValDataType
);
}
else
{
writer
.
add
(
"UNKNOWN_BOOLEAN_TYPE"
);
}
break
;
case
0x1
:
String
name
=
styleMap
.
get
(
attrValData
);
if
(
name
!=
null
)
{
writer
.
add
(
"@*"
);
if
(
attributeNS
!=
-
1
)
{
writer
.
add
(
nsPrefix
).
add
(
':'
);
}
writer
.
add
(
"style/"
).
add
(
name
.
replaceAll
(
"_"
,
"."
));
}
else
{
FieldNode
field
=
localStyleMap
.
get
(
attrValData
);
if
(
field
!=
null
)
{
String
cls
=
field
.
getParentClass
().
getShortName
().
toLowerCase
();
writer
.
add
(
"@"
).
add
(
cls
).
add
(
"/"
).
add
(
field
.
getName
());
}
else
{
writer
.
add
(
"0x"
).
add
(
Integer
.
toHexString
(
attrValData
));
}
}
break
;
default
:
writer
.
add
(
"UNKNOWN_DATA_TYPE_"
+
attrValDataType
);
break
;
}
}
}
}
writer
.
add
(
"\""
);
writer
.
add
(
'"'
);
if
((
i
+
1
)
<
attributeCount
)
{
if
((
i
+
1
)
<
attributeCount
)
{
writer
.
add
(
" "
);
writer
.
add
(
" "
);
}
}
...
@@ -292,16 +314,18 @@ public class BinaryXMLParser {
...
@@ -292,16 +314,18 @@ public class BinaryXMLParser {
int
elementNS
=
cInt32
(
bytes
,
count
);
int
elementNS
=
cInt32
(
bytes
,
count
);
int
elementName
=
cInt32
(
bytes
,
count
);
int
elementName
=
cInt32
(
bytes
,
count
);
if
(
currentTag
.
equals
(
strings
[
elementName
]))
{
if
(
currentTag
.
equals
(
strings
[
elementName
]))
{
writer
.
add
(
"/>"
);
writer
.
add
(
"
/>"
);
wasOneLiner
=
true
;
wasOneLiner
=
true
;
}
else
{
}
else
{
writer
.
startLine
(
"</"
);
writer
.
startLine
(
"</"
);
if
(
elementNS
!=
-
1
)
{
if
(
elementNS
!=
-
1
)
{
writer
.
add
(
strings
[
elementNS
]
+
":"
);
writer
.
add
(
strings
[
elementNS
]
).
add
(
':'
);
}
}
writer
.
add
(
strings
[
elementName
]
+
">"
);
writer
.
add
(
strings
[
elementName
]).
add
(
">"
);
}
if
(
writer
.
getIndent
()
!=
0
)
{
writer
.
decIndent
();
}
}
writer
.
decIndent
();
}
}
private
int
cInt8
(
byte
[]
bytes
,
int
offset
)
{
private
int
cInt8
(
byte
[]
bytes
,
int
offset
)
{
...
...
jadx-core/src/main/java/jadx/core/xmlgen/ManifestAttributes.java
0 → 100644
View file @
716db8b9
package
jadx
.
core
.
xmlgen
;
import
javax.xml.parsers.DocumentBuilder
;
import
javax.xml.parsers.DocumentBuilderFactory
;
import
java.io.InputStream
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.w3c.dom.Document
;
import
org.w3c.dom.NamedNodeMap
;
import
org.w3c.dom.Node
;
import
org.w3c.dom.NodeList
;
public
class
ManifestAttributes
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ManifestAttributes
.
class
);
private
static
final
String
MANIFEST_ATTR_XML
=
"/attrs_manifest.xml"
;
private
enum
MAttrType
{
ENUM
,
FLAG
}
private
static
class
MAttr
{
private
final
MAttrType
type
;
private
final
Map
<
Integer
,
String
>
values
=
new
LinkedHashMap
<
Integer
,
String
>();
public
MAttr
(
MAttrType
type
)
{
this
.
type
=
type
;
}
public
MAttrType
getType
()
{
return
type
;
}
public
Map
<
Integer
,
String
>
getValues
()
{
return
values
;
}
@Override
public
String
toString
()
{
return
"["
+
type
+
", "
+
values
+
"]"
;
}
}
private
final
Document
doc
;
private
final
Map
<
String
,
MAttr
>
attrMap
=
new
HashMap
<
String
,
MAttr
>();
public
ManifestAttributes
()
throws
Exception
{
InputStream
xmlStream
=
ManifestAttributes
.
class
.
getResourceAsStream
(
MANIFEST_ATTR_XML
);
DocumentBuilder
dBuilder
=
DocumentBuilderFactory
.
newInstance
().
newDocumentBuilder
();
doc
=
dBuilder
.
parse
(
xmlStream
);
}
public
void
parse
()
{
NodeList
nodeList
=
doc
.
getChildNodes
();
for
(
int
count
=
0
;
count
<
nodeList
.
getLength
();
count
++)
{
Node
node
=
nodeList
.
item
(
count
);
if
(
node
.
getNodeType
()
==
Node
.
ELEMENT_NODE
)
{
if
(
node
.
hasChildNodes
())
{
parseAttrList
(
node
.
getChildNodes
());
}
}
}
}
private
void
parseAttrList
(
NodeList
nodeList
)
{
for
(
int
count
=
0
;
count
<
nodeList
.
getLength
();
count
++)
{
Node
tempNode
=
nodeList
.
item
(
count
);
if
(
tempNode
.
getNodeType
()
==
Node
.
ELEMENT_NODE
&&
tempNode
.
hasAttributes
()
&&
tempNode
.
hasChildNodes
())
{
String
name
=
null
;
NamedNodeMap
nodeMap
=
tempNode
.
getAttributes
();
for
(
int
i
=
0
;
i
<
nodeMap
.
getLength
();
i
++)
{
Node
node
=
nodeMap
.
item
(
i
);
if
(
node
.
getNodeName
().
equals
(
"name"
))
{
name
=
node
.
getNodeValue
();
break
;
}
}
if
(
name
!=
null
&&
tempNode
.
getNodeName
().
equals
(
"attr"
))
{
parseValues
(
name
,
tempNode
.
getChildNodes
());
}
else
{
parseAttrList
(
tempNode
.
getChildNodes
());
}
}
}
}
private
void
parseValues
(
String
name
,
NodeList
nodeList
)
{
MAttr
attr
=
null
;
for
(
int
count
=
0
;
count
<
nodeList
.
getLength
();
count
++)
{
Node
tempNode
=
nodeList
.
item
(
count
);
if
(
tempNode
.
getNodeType
()
==
Node
.
ELEMENT_NODE
&&
tempNode
.
hasAttributes
())
{
if
(
attr
==
null
)
{
if
(
tempNode
.
getNodeName
().
equals
(
"enum"
))
{
attr
=
new
MAttr
(
MAttrType
.
ENUM
);
}
else
if
(
tempNode
.
getNodeName
().
equals
(
"flag"
))
{
attr
=
new
MAttr
(
MAttrType
.
FLAG
);
}
if
(
attr
==
null
)
{
return
;
}
attrMap
.
put
(
name
,
attr
);
}
NamedNodeMap
attributes
=
tempNode
.
getAttributes
();
Node
nameNode
=
attributes
.
getNamedItem
(
"name"
);
if
(
nameNode
!=
null
)
{
Node
valueNode
=
attributes
.
getNamedItem
(
"value"
);
if
(
valueNode
!=
null
)
{
try
{
int
key
;
String
nodeValue
=
valueNode
.
getNodeValue
();
if
(
attr
.
getType
()
==
MAttrType
.
ENUM
)
{
key
=
Integer
.
parseInt
(
nodeValue
);
}
else
{
nodeValue
=
nodeValue
.
replace
(
"0x"
,
""
);
key
=
Integer
.
parseInt
(
nodeValue
,
16
);
}
attr
.
getValues
().
put
(
key
,
nameNode
.
getNodeValue
());
}
catch
(
NumberFormatException
e
)
{
LOG
.
debug
(
"Failed parse manifest number"
,
e
);
}
}
}
}
}
}
public
String
decode
(
String
attrName
,
int
value
)
{
MAttr
attr
=
attrMap
.
get
(
attrName
);
if
(
attr
==
null
)
{
return
null
;
}
if
(
attr
.
getType
()
==
MAttrType
.
ENUM
)
{
String
name
=
attr
.
getValues
().
get
(
value
);
if
(
name
!=
null
)
{
return
name
;
}
}
else
if
(
attr
.
getType
()
==
MAttrType
.
FLAG
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
Map
.
Entry
<
Integer
,
String
>
entry
:
attr
.
getValues
().
entrySet
())
{
if
((
value
&
entry
.
getKey
())
!=
0
)
{
sb
.
append
(
entry
.
getValue
()).
append
(
'|'
);
}
}
if
(
sb
.
length
()
!=
0
)
{
return
sb
.
deleteCharAt
(
sb
.
length
()
-
1
).
toString
();
}
}
return
"UNKNOWN_DATA_"
+
Integer
.
toHexString
(
value
);
}
}
jadx-core/src/main/resources/attrs_manifest.xml
0 → 100644
View file @
716db8b9
This diff is collapsed.
Click to expand it.
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