Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
keyescgm
jadx
提交
b5720bd1
J
jadx
项目概览
keyescgm
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b5720bd1
编写于
7月 02, 2021
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(gui): improve Quark tasks scheduling and report viewer (#1119)
上级
cc99409a
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
921 addition
and
521 deletion
+921
-521
jadx-core/src/main/java/jadx/api/JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+9
-0
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
+5
-1
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkDialog.java
...gui/src/main/java/jadx/gui/plugins/quark/QuarkDialog.java
+114
-0
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java
...ui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java
+221
-0
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportData.java
...src/main/java/jadx/gui/plugins/quark/QuarkReportData.java
+48
-0
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportNode.java
...src/main/java/jadx/gui/plugins/quark/QuarkReportNode.java
+79
-0
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java
...rc/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java
+318
-0
jadx-gui/src/main/java/jadx/gui/treemodel/ApkSignature.java
jadx-gui/src/main/java/jadx/gui/treemodel/ApkSignature.java
+10
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
+8
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
+8
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
+7
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java
jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java
+15
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java
jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java
+22
-5
jadx-gui/src/main/java/jadx/gui/ui/CertificatePanel.java
jadx-gui/src/main/java/jadx/gui/ui/CertificatePanel.java
+0
-30
jadx-gui/src/main/java/jadx/gui/ui/ContentPanel.java
jadx-gui/src/main/java/jadx/gui/ui/ContentPanel.java
+0
-2
jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java
jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java
+1
-1
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+46
-37
jadx-gui/src/main/java/jadx/gui/ui/QuarkDialog.java
jadx-gui/src/main/java/jadx/gui/ui/QuarkDialog.java
+0
-401
jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java
jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java
+2
-4
jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java
jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java
+8
-40
未找到文件。
jadx-core/src/main/java/jadx/api/JavaClass.java
浏览文件 @
b5720bd1
...
...
@@ -223,6 +223,15 @@ public final class JavaClass implements JavaNode {
return
methods
;
}
@Nullable
public
JavaMethod
searchMethodByShortId
(
String
shortId
)
{
MethodNode
methodNode
=
cls
.
searchMethodByShortId
(
shortId
);
if
(
methodNode
==
null
)
{
return
null
;
}
return
new
JavaMethod
(
this
,
methodNode
);
}
@Override
public
int
getDecompiledLine
()
{
return
cls
.
getDecompiledLine
();
...
...
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
浏览文件 @
b5720bd1
...
...
@@ -66,6 +66,10 @@ public class BackgroundExecutor {
execute
(
new
SimpleTask
(
title
,
Collections
.
singletonList
(
backgroundRunnable
),
onFinishUiRunnable
));
}
public
void
execute
(
String
title
,
Runnable
backgroundRunnable
)
{
execute
(
new
SimpleTask
(
title
,
Collections
.
singletonList
(
backgroundRunnable
),
null
));
}
private
ThreadPoolExecutor
makeTaskQueueExecutor
()
{
return
(
ThreadPoolExecutor
)
Executors
.
newFixedThreadPool
(
1
);
}
...
...
@@ -125,7 +129,7 @@ public class BackgroundExecutor {
return
cancelStatus
;
}
setProgress
(
calcProgress
(
executor
.
getCompletedTaskCount
()));
Thread
.
sleep
(
10
00
);
Thread
.
sleep
(
5
00
);
}
}
catch
(
InterruptedException
e
)
{
LOG
.
debug
(
"Task wait interrupted"
);
...
...
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkDialog.java
0 → 100644
浏览文件 @
b5720bd1
package
jadx.gui.plugins.quark
;
import
java.awt.BorderLayout
;
import
java.awt.Container
;
import
java.nio.file.FileSystems
;
import
java.nio.file.Path
;
import
java.nio.file.PathMatcher
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
javax.swing.JButton
;
import
javax.swing.JComboBox
;
import
javax.swing.JDialog
;
import
javax.swing.JLabel
;
import
javax.swing.JPanel
;
import
javax.swing.WindowConstants
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.UiUtils
;
public
class
QuarkDialog
extends
JDialog
{
private
static
final
long
serialVersionUID
=
4855753773520368215L
;
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
QuarkDialog
.
class
);
private
final
transient
JadxSettings
settings
;
private
final
transient
MainWindow
mainWindow
;
private
final
List
<
Path
>
files
;
private
JComboBox
<
Path
>
fileSelectCombo
;
public
QuarkDialog
(
MainWindow
mainWindow
)
{
this
.
mainWindow
=
mainWindow
;
this
.
settings
=
mainWindow
.
getSettings
();
this
.
files
=
filterOpenFiles
(
mainWindow
);
if
(
files
.
isEmpty
())
{
UiUtils
.
errorMessage
(
mainWindow
,
"Quark is unable to analyze loaded files"
);
LOG
.
error
(
"Quark: The files cannot be analyzed: {}"
,
mainWindow
.
getWrapper
().
getOpenPaths
());
return
;
}
initUI
();
}
private
List
<
Path
>
filterOpenFiles
(
MainWindow
mainWindow
)
{
PathMatcher
matcher
=
FileSystems
.
getDefault
().
getPathMatcher
(
"glob:**.{apk,dex}"
);
return
mainWindow
.
getWrapper
().
getOpenPaths
()
.
stream
()
.
filter
(
matcher:
:
matches
)
.
collect
(
Collectors
.
toList
());
}
private
void
initUI
()
{
JLabel
description
=
new
JLabel
(
"Analyzing apk using Quark-Engine"
);
JLabel
selectApkText
=
new
JLabel
(
"Select Apk/Dex"
);
description
.
setAlignmentX
(
0.5f
);
fileSelectCombo
=
new
JComboBox
<>(
files
.
toArray
(
new
Path
[
0
]));
fileSelectCombo
.
setRenderer
((
list
,
value
,
index
,
isSelected
,
cellHasFocus
)
->
new
JLabel
(
value
.
getFileName
().
toString
()));
JPanel
textPane
=
new
JPanel
();
textPane
.
add
(
description
);
JPanel
selectApkPanel
=
new
JPanel
();
selectApkPanel
.
add
(
selectApkText
);
selectApkPanel
.
add
(
fileSelectCombo
);
JPanel
buttonPane
=
new
JPanel
();
JButton
start
=
new
JButton
(
"Start"
);
JButton
close
=
new
JButton
(
"Close"
);
close
.
addActionListener
(
event
->
close
());
start
.
addActionListener
(
event
->
startQuarkTasks
());
buttonPane
.
add
(
start
);
buttonPane
.
add
(
close
);
getRootPane
().
setDefaultButton
(
close
);
JPanel
centerPane
=
new
JPanel
();
centerPane
.
add
(
selectApkPanel
);
Container
contentPane
=
getContentPane
();
contentPane
.
add
(
textPane
,
BorderLayout
.
PAGE_START
);
contentPane
.
add
(
centerPane
);
contentPane
.
add
(
buttonPane
,
BorderLayout
.
PAGE_END
);
setTitle
(
"Quark Engine"
);
pack
();
if
(!
mainWindow
.
getSettings
().
loadWindowPos
(
this
))
{
setSize
(
300
,
140
);
}
setLocationRelativeTo
(
null
);
setDefaultCloseOperation
(
WindowConstants
.
DISPOSE_ON_CLOSE
);
setModalityType
(
ModalityType
.
APPLICATION_MODAL
);
UiUtils
.
addEscapeShortCutToDispose
(
this
);
}
private
void
startQuarkTasks
()
{
Path
apkFile
=
(
Path
)
fileSelectCombo
.
getSelectedItem
();
new
QuarkManager
(
mainWindow
,
apkFile
).
start
();
close
();
}
private
void
close
()
{
dispose
();
}
@Override
public
void
dispose
()
{
settings
.
saveWindowPos
(
this
);
super
.
dispose
();
}
}
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkManager.java
0 → 100644
浏览文件 @
b5720bd1
package
jadx.gui.plugins.quark
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.InputStreamReader
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.List
;
import
javax.swing.JOptionPane
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.gui.jobs.BackgroundExecutor
;
import
jadx.gui.treemodel.JRoot
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.SystemInfo
;
import
jadx.gui.utils.UiUtils
;
public
class
QuarkManager
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
QuarkManager
.
class
);
private
static
final
Path
QUARK_DIR_PATH
=
Paths
.
get
(
System
.
getProperty
(
"user.home"
),
".quark-engine"
);
private
static
final
Path
VENV_PATH
=
QUARK_DIR_PATH
.
resolve
(
"quark_venv"
);
private
static
final
int
LARGE_APK_SIZE
=
30
;
private
final
MainWindow
mainWindow
;
private
final
Path
apkPath
;
private
boolean
useVEnv
;
private
boolean
installComplete
;
private
Path
reportFile
;
public
QuarkManager
(
MainWindow
mainWindow
,
Path
apkPath
)
{
this
.
mainWindow
=
mainWindow
;
this
.
apkPath
=
apkPath
;
}
public
void
start
()
{
if
(!
checkFileSize
(
LARGE_APK_SIZE
))
{
int
result
=
JOptionPane
.
showConfirmDialog
(
mainWindow
,
"The selected file size is too large (over 30M) that may take a long time to analyze, do you want to continue"
,
"Quark: Warning"
,
JOptionPane
.
YES_NO_OPTION
);
if
(
result
==
JOptionPane
.
NO_OPTION
)
{
return
;
}
}
BackgroundExecutor
executor
=
mainWindow
.
getBackgroundExecutor
();
executor
.
execute
(
"Quark install"
,
this
::
checkInstall
,
installStatus
->
executor
.
execute
(
"Quark analysis"
,
this
::
startAnalysis
,
analysisStatus
->
loadReport
()));
}
private
void
checkInstall
()
{
try
{
if
(
checkCommand
(
"quark"
))
{
useVEnv
=
false
;
installComplete
=
true
;
return
;
}
useVEnv
=
true
;
if
(
checkVEnvCommand
(
"quark"
))
{
installComplete
=
true
;
installQuark
();
// upgrade quark
return
;
}
int
result
=
JOptionPane
.
showConfirmDialog
(
mainWindow
,
"Quark is not installed, do you want to install it from PyPI?"
,
"Warning"
,
JOptionPane
.
YES_NO_OPTION
);
if
(
result
==
JOptionPane
.
NO_OPTION
)
{
installComplete
=
false
;
return
;
}
createVirtualEnv
();
installQuark
();
installComplete
=
true
;
}
catch
(
Exception
e
)
{
UiUtils
.
errorMessage
(
mainWindow
,
e
.
getMessage
());
LOG
.
error
(
"Failed to install quark"
,
e
);
installComplete
=
false
;
}
}
private
void
startAnalysis
()
{
if
(!
installComplete
)
{
return
;
}
try
{
updateQuarkRules
();
reportFile
=
Files
.
createTempFile
(
"QuarkReport-"
,
".json"
).
toAbsolutePath
();
List
<
String
>
cmd
=
new
ArrayList
<>();
cmd
.
add
(
getCommand
(
"quark"
));
cmd
.
add
(
"-a"
);
cmd
.
add
(
apkPath
.
toString
());
cmd
.
add
(
"-o"
);
cmd
.
add
(
reportFile
.
toString
());
runCommand
(
cmd
);
}
catch
(
Exception
e
)
{
UiUtils
.
errorMessage
(
mainWindow
,
"Failed to execute Quark"
);
LOG
.
error
(
"Failed to execute Quark"
,
e
);
}
}
private
void
loadReport
()
{
try
{
QuarkReportNode
quarkNode
=
new
QuarkReportNode
(
reportFile
);
JRoot
root
=
mainWindow
.
getCacheObject
().
getJRoot
();
root
.
replaceCustomNode
(
quarkNode
);
root
.
update
();
mainWindow
.
reloadTree
();
mainWindow
.
getTabbedPane
().
showNode
(
quarkNode
);
}
catch
(
Exception
e
)
{
UiUtils
.
errorMessage
(
mainWindow
,
"Failed to load Quark report."
);
LOG
.
error
(
"Failed to load Quark report."
,
e
);
}
}
private
void
createVirtualEnv
()
{
if
(
Files
.
exists
(
getVenvPath
(
"activate"
)))
{
return
;
}
File
directory
=
QUARK_DIR_PATH
.
toFile
();
if
(!
directory
.
isDirectory
())
{
if
(!
directory
.
mkdirs
())
{
throw
new
JadxRuntimeException
(
"Failed create directory: "
+
directory
);
}
}
List
<
String
>
cmd
=
new
ArrayList
<>();
if
(
SystemInfo
.
IS_WINDOWS
)
{
cmd
.
add
(
"python"
);
cmd
.
add
(
"-m"
);
cmd
.
add
(
"venv"
);
}
else
{
cmd
.
add
(
"virtualenv"
);
}
cmd
.
add
(
VENV_PATH
.
toString
());
try
{
runCommand
(
cmd
);
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to create virtual environment"
,
e
);
}
}
private
void
installQuark
()
{
List
<
String
>
cmd
=
new
ArrayList
<>();
cmd
.
add
(
getCommand
(
"pip3"
));
cmd
.
add
(
"install"
);
cmd
.
add
(
"quark-engine"
);
cmd
.
add
(
"--upgrade"
);
try
{
runCommand
(
cmd
);
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to install quark-engine"
,
e
);
}
}
private
void
updateQuarkRules
()
{
List
<
String
>
cmd
=
new
ArrayList
<>();
cmd
.
add
(
getCommand
(
"freshquark"
));
try
{
runCommand
(
cmd
);
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to update quark rules"
,
e
);
}
}
public
boolean
checkFileSize
(
int
sizeThreshold
)
{
try
{
int
fileSize
=
(
int
)
Files
.
size
(
apkPath
)
/
1024
/
1024
;
if
(
fileSize
>
sizeThreshold
)
{
return
false
;
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to calculate file: {}"
,
e
.
getMessage
(),
e
);
return
false
;
}
return
true
;
}
private
String
getCommand
(
String
cmd
)
{
if
(
useVEnv
)
{
return
getVenvPath
(
cmd
).
toAbsolutePath
().
toString
();
}
return
cmd
;
}
private
boolean
checkVEnvCommand
(
String
cmd
)
{
Path
venvPath
=
getVenvPath
(
cmd
);
return
checkCommand
(
venvPath
.
toAbsolutePath
().
toString
());
}
private
Path
getVenvPath
(
String
cmd
)
{
if
(
SystemInfo
.
IS_WINDOWS
)
{
return
VENV_PATH
.
resolve
(
"Scripts"
).
resolve
(
cmd
+
".exe"
);
}
return
VENV_PATH
.
resolve
(
"bin"
).
resolve
(
cmd
);
}
private
void
runCommand
(
List
<
String
>
cmd
)
throws
Exception
{
LOG
.
debug
(
"Running command: {}"
,
String
.
join
(
" "
,
cmd
));
Process
process
=
Runtime
.
getRuntime
().
exec
(
cmd
.
toArray
(
new
String
[
0
]));
try
(
BufferedReader
buf
=
new
BufferedReader
(
new
InputStreamReader
(
process
.
getInputStream
())))
{
buf
.
lines
().
forEach
(
msg
->
LOG
.
debug
(
"# {}"
,
msg
));
}
finally
{
process
.
waitFor
();
}
}
private
boolean
checkCommand
(
String
...
cmd
)
{
try
{
Process
process
=
Runtime
.
getRuntime
().
exec
(
cmd
);
process
.
waitFor
();
}
catch
(
Exception
e
)
{
return
false
;
}
return
true
;
}
}
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportData.java
0 → 100644
浏览文件 @
b5720bd1
package
jadx.gui.plugins.quark
;
import
java.util.List
;
import
java.util.Map
;
import
com.google.gson.annotations.SerializedName
;
import
jadx.core.utils.Utils
;
@SuppressWarnings
(
"MemberName"
)
public
class
QuarkReportData
{
public
static
class
Crime
{
public
String
crime
;
public
String
confidence
;
public
List
<
String
>
permissions
;
List
<
Method
>
native_api
;
List
<
Method
>
combination
;
List
<
Map
<
String
,
InvokePlace
>>
register
;
}
public
static
class
Method
{
@SerializedName
(
"class"
)
String
cls
;
String
method
;
String
descriptor
;
@Override
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
Utils
.
cleanObjectName
(
cls
)).
append
(
"."
).
append
(
method
);
if
(
descriptor
!=
null
)
{
sb
.
append
(
descriptor
);
}
return
sb
.
toString
();
}
}
public
static
class
InvokePlace
{
List
<
String
>
first
;
List
<
String
>
second
;
}
String
apk_filename
;
String
threat_level
;
int
total_score
;
List
<
Crime
>
crimes
;
}
jadx-gui/src/main/java/jadx/gui/
ui/QuarkReport
.java
→
jadx-gui/src/main/java/jadx/gui/
plugins/quark/QuarkReportNode
.java
浏览文件 @
b5720bd1
package
jadx.gui.ui
;
package
jadx.gui.plugins.quark
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
...
...
@@ -8,33 +11,31 @@ import org.apache.commons.text.StringEscapeUtils;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.google.gson.
JsonArray
;
import
com.google.gson.
JsonObject
;
import
com.google.gson.
Gson
;
import
com.google.gson.
GsonBuilder
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.HtmlPanel
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.utils.UiUtils
;
public
class
QuarkReport
extends
JNode
{
public
class
QuarkReport
Node
extends
JNode
{
private
static
final
long
serialVersionUID
=
-
766800957202637021L
;
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
QuarkReport
.
class
);
private
static
final
ImageIcon
REPORT_ICON
=
UiUtils
.
openIcon
(
"report"
);
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
QuarkReportNode
.
class
);
private
String
content
;
private
String
apkFileName
;
private
static
final
Gson
GSON
=
new
GsonBuilder
().
create
();
private
JsonObject
reportData
;
private
static
final
ImageIcon
ICON
=
UiUtils
.
openIcon
(
"icon_quark"
);
private
final
Path
apkFile
;
public
static
QuarkReport
analysisAPK
(
JsonObject
data
)
{
return
new
QuarkReport
(
data
);
}
private
String
errorContent
;
public
QuarkReport
(
JsonObject
data
)
{
this
.
reportData
=
data
;
this
.
apkFileName
=
data
.
get
(
"apk_filename"
).
getAsString
();
public
QuarkReportNode
(
Path
apkFile
)
{
this
.
apkFile
=
apkFile
;
}
@Override
...
...
@@ -44,7 +45,7 @@ public class QuarkReport extends JNode {
@Override
public
Icon
getIcon
()
{
return
REPORT_
ICON
;
return
ICON
;
}
@Override
...
...
@@ -53,53 +54,26 @@ public class QuarkReport extends JNode {
}
@Override
public
String
getContent
()
{
if
(
content
!=
null
)
{
return
this
.
content
;
}
public
ContentPanel
getContentPanel
(
TabbedPane
tabbedPane
)
{
QuarkReportData
data
;
try
{
JsonArray
crimes
=
(
JsonArray
)
this
.
reportData
.
get
(
"crimes"
);
StringEscapeUtils
.
Builder
builder
=
StringEscapeUtils
.
builder
(
StringEscapeUtils
.
ESCAPE_HTML4
);
builder
.
append
(
"<h1>Quark Analysis Report</h1>"
);
builder
.
append
(
"<h3>"
);
builder
.
append
(
"File name: "
);
builder
.
append
(
apkFileName
);
builder
.
append
(
"</h3>"
);
builder
.
append
(
"<table><thead><tr>"
);
builder
.
append
(
"<th>Potential Malicious Activities</th>"
);
builder
.
append
(
"<th>Confidence</th>"
);
builder
.
append
(
"</tr></thead><tbody>"
);
for
(
Object
obj
:
crimes
)
{
JsonObject
crime
=
(
JsonObject
)
obj
;
String
crimeDes
=
crime
.
get
(
"crime"
).
getAsString
();
String
confidence
=
crime
.
get
(
"confidence"
).
getAsString
();
builder
.
append
(
"<tr><td>"
);
builder
.
append
(
crimeDes
);
builder
.
append
(
"</td><td>"
);
builder
.
append
(
confidence
);
builder
.
append
(
"</td></tr>"
);
}
builder
.
append
(
"</tbody></table>"
);
this
.
content
=
builder
.
toString
();
data
=
GSON
.
fromJson
(
Files
.
newBufferedReader
(
apkFile
),
QuarkReportData
.
class
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
e
.
getMessage
()
,
e
);
LOG
.
error
(
"Quark report parse error"
,
e
);
StringEscapeUtils
.
Builder
builder
=
StringEscapeUtils
.
builder
(
StringEscapeUtils
.
ESCAPE_HTML4
);
builder
.
append
(
"<h
1
>"
);
builder
.
append
(
"<h
2
>"
);
builder
.
escape
(
"Quark analysis failed!"
);
builder
.
append
(
"</h
1
><pre>"
);
builder
.
append
(
"</h
2
><pre>"
);
builder
.
escape
(
ExceptionUtils
.
getStackTrace
(
e
));
builder
.
append
(
"</pre>"
);
return
builder
.
toString
();
errorContent
=
builder
.
toString
();
return
new
HtmlPanel
(
tabbedPane
,
this
);
}
return
this
.
content
;
return
new
QuarkReportPanel
(
tabbedPane
,
this
,
data
);
}
@Override
public
String
getContent
()
{
return
this
.
errorContent
;
}
}
jadx-gui/src/main/java/jadx/gui/plugins/quark/QuarkReportPanel.java
0 → 100644
浏览文件 @
b5720bd1
package
jadx.gui.plugins.quark
;
import
java.awt.BorderLayout
;
import
java.awt.Component
;
import
java.awt.Font
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
java.util.Comparator
;
import
java.util.Enumeration
;
import
java.util.IdentityHashMap
;
import
java.util.Map
;
import
javax.swing.BorderFactory
;
import
javax.swing.JEditorPane
;
import
javax.swing.JLabel
;
import
javax.swing.JPanel
;
import
javax.swing.JScrollPane
;
import
javax.swing.JTree
;
import
javax.swing.ScrollPaneConstants
;
import
javax.swing.SwingUtilities
;
import
javax.swing.event.TreeExpansionEvent
;
import
javax.swing.event.TreeExpansionListener
;
import
javax.swing.tree.DefaultMutableTreeNode
;
import
javax.swing.tree.MutableTreeNode
;
import
javax.swing.tree.TreeCellRenderer
;
import
javax.swing.tree.TreeNode
;
import
javax.swing.tree.TreePath
;
import
org.apache.commons.text.StringEscapeUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.beust.jcommander.Strings
;
import
jadx.api.JavaClass
;
import
jadx.api.JavaMethod
;
import
jadx.core.utils.Utils
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.jobs.BackgroundExecutor
;
import
jadx.gui.treemodel.JMethod
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.utils.JNodeCache
;
public
class
QuarkReportPanel
extends
ContentPanel
{
private
static
final
long
serialVersionUID
=
-
242266836695889206L
;
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
QuarkReportPanel
.
class
);
private
final
QuarkReportData
data
;
private
final
JNodeCache
nodeCache
;
private
JEditorPane
header
;
private
JTree
tree
;
private
DefaultMutableTreeNode
treeRoot
;
private
Font
font
;
private
Font
boldFont
;
private
CachingTreeCellRenderer
cellRenderer
;
protected
QuarkReportPanel
(
TabbedPane
panel
,
QuarkReportNode
node
,
QuarkReportData
data
)
{
super
(
panel
,
node
);
this
.
data
=
data
;
this
.
nodeCache
=
panel
.
getMainWindow
().
getCacheObject
().
getNodeCache
();
prepareData
();
initUI
();
loadSettings
();
}
private
void
prepareData
()
{
data
.
crimes
.
sort
(
Comparator
.
comparingInt
(
c
->
-
Integer
.
parseInt
(
c
.
confidence
.
replace
(
"%"
,
""
))));
}
private
void
initUI
()
{
setLayout
(
new
BorderLayout
());
header
=
new
JEditorPane
();
header
.
setContentType
(
"text/html"
);
header
.
setEditable
(
false
);
header
.
setText
(
buildHeader
());
cellRenderer
=
new
CachingTreeCellRenderer
();
treeRoot
=
new
TextTreeNode
(
"Potential Malicious Activities:"
).
bold
();
tree
=
buildTree
();
for
(
QuarkReportData
.
Crime
crime
:
data
.
crimes
)
{
treeRoot
.
add
(
new
CrimeTreeNode
(
crime
));
}
tree
.
expandRow
(
0
);
tree
.
expandRow
(
1
);
JScrollPane
tableScroll
=
new
JScrollPane
(
tree
);
tableScroll
.
setVerticalScrollBarPolicy
(
ScrollPaneConstants
.
VERTICAL_SCROLLBAR_AS_NEEDED
);
JPanel
mainPanel
=
new
JPanel
();
mainPanel
.
setLayout
(
new
BorderLayout
());
mainPanel
.
add
(
header
,
BorderLayout
.
PAGE_START
);
mainPanel
.
add
(
tableScroll
,
BorderLayout
.
CENTER
);
add
(
mainPanel
);
}
private
JTree
buildTree
()
{
JTree
tree
=
new
JTree
(
treeRoot
);
tree
.
setLayout
(
new
BorderLayout
());
tree
.
setBorder
(
BorderFactory
.
createEmptyBorder
());
tree
.
setShowsRootHandles
(
false
);
tree
.
setScrollsOnExpand
(
false
);
tree
.
setSelectionModel
(
null
);
tree
.
setCellRenderer
(
cellRenderer
);
tree
.
addMouseListener
(
new
MouseAdapter
()
{
@Override
public
void
mouseClicked
(
MouseEvent
event
)
{
if
(
SwingUtilities
.
isLeftMouseButton
(
event
))
{
Object
node
=
getNodeUnderMouse
(
tree
,
event
);
if
(
node
instanceof
MethodTreeNode
)
{
JMethod
method
=
((
MethodTreeNode
)
node
).
getJMethod
();
BackgroundExecutor
executor
=
tabbedPane
.
getMainWindow
().
getBackgroundExecutor
();
executor
.
execute
(
"Decompiling class"
,
()
->
tabbedPane
.
codeJump
(
method
),
status
->
tabbedPane
.
codeJump
(
method
)
// TODO: fix bug with incorrect jump on just decompiled code
);
}
}
}
});
tree
.
addTreeExpansionListener
(
new
TreeExpansionListener
()
{
@Override
public
void
treeExpanded
(
TreeExpansionEvent
event
)
{
TreePath
path
=
event
.
getPath
();
Object
leaf
=
path
.
getLastPathComponent
();
if
(
leaf
instanceof
CrimeTreeNode
)
{
CrimeTreeNode
node
=
(
CrimeTreeNode
)
leaf
;
Enumeration
<
TreeNode
>
children
=
node
.
children
();
while
(
children
.
hasMoreElements
())
{
TreeNode
child
=
children
.
nextElement
();
tree
.
expandPath
(
path
.
pathByAddingChild
(
child
));
}
}
}
@Override
public
void
treeCollapsed
(
TreeExpansionEvent
event
)
{
}
});
return
tree
;
}
private
String
buildHeader
()
{
StringEscapeUtils
.
Builder
builder
=
StringEscapeUtils
.
builder
(
StringEscapeUtils
.
ESCAPE_HTML4
);
builder
.
append
(
"<h1>Quark Analysis Report</h1>"
);
builder
.
append
(
"<h3>"
);
builder
.
append
(
"File: "
).
append
(
data
.
apk_filename
);
builder
.
append
(
"<br>"
);
builder
.
append
(
"Treat level: "
).
append
(
data
.
threat_level
);
builder
.
append
(
"<br>"
);
builder
.
append
(
"Total score: "
).
append
(
Integer
.
toString
(
data
.
total_score
));
builder
.
append
(
"</h3>"
);
return
builder
.
toString
();
}
@Override
public
void
loadSettings
()
{
Font
settingsFont
=
getTabbedPane
().
getMainWindow
().
getSettings
().
getFont
();
this
.
font
=
settingsFont
.
deriveFont
(
settingsFont
.
getSize2D
()
+
1
.
f
);
this
.
boldFont
=
font
.
deriveFont
(
Font
.
BOLD
);
header
.
setFont
(
font
);
tree
.
setFont
(
font
);
cellRenderer
.
clearCache
();
}
private
static
Object
getNodeUnderMouse
(
JTree
tree
,
MouseEvent
mouseEvent
)
{
TreePath
path
=
tree
.
getPathForLocation
(
mouseEvent
.
getX
(),
mouseEvent
.
getY
());
return
path
!=
null
?
path
.
getLastPathComponent
()
:
null
;
}
private
static
class
CachingTreeCellRenderer
implements
TreeCellRenderer
{
private
final
Map
<
BaseTreeNode
,
Component
>
cache
=
new
IdentityHashMap
<>();
@Override
public
Component
getTreeCellRendererComponent
(
JTree
tr
,
Object
value
,
boolean
selected
,
boolean
expanded
,
boolean
leaf
,
int
row
,
boolean
focus
)
{
return
cache
.
computeIfAbsent
((
BaseTreeNode
)
value
,
BaseTreeNode:
:
render
);
}
public
void
clearCache
()
{
cache
.
clear
();
}
}
private
abstract
static
class
BaseTreeNode
extends
DefaultMutableTreeNode
{
private
static
final
long
serialVersionUID
=
7197501219150495889L
;
public
BaseTreeNode
(
Object
userObject
)
{
super
(
userObject
);
}
public
abstract
Component
render
();
}
private
class
TextTreeNode
extends
BaseTreeNode
{
private
static
final
long
serialVersionUID
=
6763410122501083453L
;
private
boolean
bold
;
public
TextTreeNode
(
String
text
)
{
super
(
text
);
}
public
TextTreeNode
bold
()
{
bold
=
true
;
return
this
;
}
@Override
public
Component
render
()
{
JLabel
label
=
new
JLabel
(((
String
)
getUserObject
()));
label
.
setFont
(
bold
?
boldFont
:
font
);
label
.
setIcon
(
null
);
label
.
setBorder
(
BorderFactory
.
createEmptyBorder
(
5
,
5
,
5
,
5
));
return
label
;
}
}
private
class
CrimeTreeNode
extends
TextTreeNode
{
private
static
final
long
serialVersionUID
=
-
1464310215237483911L
;
private
final
QuarkReportData
.
Crime
crime
;
public
CrimeTreeNode
(
QuarkReportData
.
Crime
crime
)
{
super
(
crime
.
crime
);
this
.
crime
=
crime
;
bold
();
addDetails
();
}
private
void
addDetails
()
{
add
(
new
TextTreeNode
(
"Confidence: "
+
crime
.
confidence
));
if
(
Utils
.
notEmpty
(
crime
.
permissions
))
{
add
(
new
TextTreeNode
(
"Permissions: "
+
Strings
.
join
(
", "
,
crime
.
permissions
)));
}
if
(
Utils
.
notEmpty
(
crime
.
combination
))
{
TextTreeNode
node
=
new
TextTreeNode
(
"Native API"
);
for
(
QuarkReportData
.
Method
method
:
crime
.
combination
)
{
node
.
add
(
new
TextTreeNode
(
method
.
toString
()));
}
add
(
node
);
}
else
{
if
(
Utils
.
notEmpty
(
crime
.
native_api
))
{
TextTreeNode
node
=
new
TextTreeNode
(
"Native API"
);
for
(
QuarkReportData
.
Method
method
:
crime
.
native_api
)
{
node
.
add
(
new
TextTreeNode
(
method
.
toString
()));
}
add
(
node
);
}
}
if
(
Utils
.
notEmpty
(
crime
.
register
))
{
TextTreeNode
node
=
new
TextTreeNode
(
"Invocations"
);
for
(
Map
<
String
,
QuarkReportData
.
InvokePlace
>
invokeMap
:
crime
.
register
)
{
invokeMap
.
forEach
((
key
,
value
)
->
node
.
add
(
resolveMethod
(
key
)));
}
add
(
node
);
}
}
@Override
public
String
toString
()
{
return
crime
.
crime
;
}
}
public
MutableTreeNode
resolveMethod
(
String
descr
)
{
try
{
String
[]
parts
=
descr
.
split
(
" "
,
3
);
String
cls
=
Utils
.
cleanObjectName
(
parts
[
0
].
replace
(
'$'
,
'.'
));
String
mth
=
parts
[
1
]
+
parts
[
2
].
replace
(
" "
,
""
);
MainWindow
mainWindow
=
getTabbedPane
().
getMainWindow
();
JadxWrapper
wrapper
=
mainWindow
.
getWrapper
();
JavaClass
javaClass
=
wrapper
.
searchJavaClassByRawName
(
cls
);
if
(
javaClass
==
null
)
{
return
new
TextTreeNode
(
cls
+
"."
+
mth
);
}
JavaMethod
javaMethod
=
javaClass
.
searchMethodByShortId
(
mth
);
if
(
javaMethod
==
null
)
{
return
new
TextTreeNode
(
javaClass
.
getFullName
()
+
"."
+
mth
);
}
return
new
MethodTreeNode
(
javaMethod
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to parse method descriptor string"
,
e
);
return
new
TextTreeNode
(
descr
);
}
}
private
class
MethodTreeNode
extends
BaseTreeNode
{
private
static
final
long
serialVersionUID
=
4350343915220068508L
;
private
final
JavaMethod
mth
;
private
final
JMethod
jnode
;
public
MethodTreeNode
(
JavaMethod
mth
)
{
super
(
mth
);
this
.
mth
=
mth
;
this
.
jnode
=
(
JMethod
)
nodeCache
.
makeFrom
(
mth
);
}
public
JMethod
getJMethod
()
{
return
jnode
;
}
@Override
public
Component
render
()
{
JLabel
label
=
new
JLabel
(
mth
.
toString
());
label
.
setFont
(
font
);
label
.
setIcon
(
jnode
.
getIcon
());
label
.
setBorder
(
BorderFactory
.
createEmptyBorder
(
5
,
5
,
5
,
5
));
return
label
;
}
}
}
jadx-gui/src/main/java/jadx/gui/treemodel/ApkSignature.java
浏览文件 @
b5720bd1
...
...
@@ -10,6 +10,7 @@ import javax.swing.ImageIcon;
import
org.apache.commons.lang3.exception.ExceptionUtils
;
import
org.apache.commons.text.StringEscapeUtils
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -18,6 +19,9 @@ import com.android.apksig.ApkVerifier;
import
jadx.api.ResourceFile
;
import
jadx.api.ResourceType
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.HtmlPanel
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.utils.CertificateManager
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
...
...
@@ -32,6 +36,7 @@ public class ApkSignature extends JNode {
private
final
transient
File
openFile
;
private
String
content
;
@Nullable
public
static
ApkSignature
getApkSignature
(
JadxWrapper
wrapper
)
{
// Only show the ApkSignature node if an AndroidManifest.xml is present.
// Without a manifest the Google ApkVerifier refuses to work.
...
...
@@ -70,6 +75,11 @@ public class ApkSignature extends JNode {
return
"APK signature"
;
}
@Override
public
ContentPanel
getContentPanel
(
TabbedPane
tabbedPane
)
{
return
new
HtmlPanel
(
tabbedPane
,
this
);
}
@Override
public
String
getContent
()
{
if
(
content
!=
null
)
{
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
浏览文件 @
b5720bd1
...
...
@@ -12,6 +12,9 @@ import jadx.api.JavaMethod;
import
jadx.api.JavaNode
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.ui.codearea.ClassCodeContentPanel
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
...
...
@@ -100,6 +103,11 @@ public class JClass extends JLoadableNode {
return
cls
.
getCode
();
}
@Override
public
ContentPanel
getContentPanel
(
TabbedPane
tabbedPane
)
{
return
new
ClassCodeContentPanel
(
tabbedPane
,
this
);
}
@Override
public
String
getSmali
()
{
return
cls
.
getSmali
();
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
浏览文件 @
b5720bd1
...
...
@@ -12,6 +12,9 @@ import jadx.api.JavaNode;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.ui.codearea.ClassCodeContentPanel
;
import
jadx.gui.utils.OverlayIcon
;
import
jadx.gui.utils.UiUtils
;
...
...
@@ -62,6 +65,11 @@ public class JMethod extends JNode {
return
mth
.
getDecompiledLine
();
}
@Override
public
ContentPanel
getContentPanel
(
TabbedPane
tabbedPane
)
{
return
new
ClassCodeContentPanel
(
tabbedPane
,
this
);
}
@Override
public
Icon
getIcon
()
{
AccessInfo
accessFlags
=
mth
.
getAccessFlags
();
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
浏览文件 @
b5720bd1
...
...
@@ -9,6 +9,8 @@ import org.jetbrains.annotations.Nullable;
import
jadx.api.ICodeInfo
;
import
jadx.api.JadxDecompiler
;
import
jadx.api.JavaNode
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.TabbedPane
;
public
abstract
class
JNode
extends
DefaultMutableTreeNode
{
...
...
@@ -31,6 +33,11 @@ public abstract class JNode extends DefaultMutableTreeNode {
return
null
;
}
@Nullable
public
ContentPanel
getContentPanel
(
TabbedPane
tabbedPane
)
{
return
null
;
}
public
String
getSmali
()
{
return
null
;
}
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java
浏览文件 @
b5720bd1
...
...
@@ -21,6 +21,10 @@ import jadx.api.ResourcesLoader;
import
jadx.api.impl.SimpleCodeInfo
;
import
jadx.core.utils.Utils
;
import
jadx.core.xmlgen.ResContainer
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.ImagePanel
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.ui.codearea.CodeContentPanel
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.OverlayIcon
;
import
jadx.gui.utils.UiUtils
;
...
...
@@ -106,6 +110,17 @@ public class JResource extends JLoadableNode implements Comparable<JResource> {
return
content
;
}
@Override
public
@Nullable
ContentPanel
getContentPanel
(
TabbedPane
tabbedPane
)
{
if
(
resFile
==
null
)
{
return
null
;
}
if
(
resFile
.
getType
()
==
ResourceType
.
IMG
)
{
return
new
ImagePanel
(
tabbedPane
,
this
);
}
return
new
CodeContentPanel
(
tabbedPane
,
this
);
}
@Override
public
synchronized
String
getContent
()
{
if
(
loaded
)
{
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java
浏览文件 @
b5720bd1
...
...
@@ -2,12 +2,16 @@ package jadx.gui.treemodel;
import
java.io.File
;
import
java.nio.file.Path
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.List
;
import
java.util.regex.Pattern
;
import
javax.swing.*
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
import
org.jetbrains.annotations.Nullable
;
import
jadx.api.ResourceFile
;
import
jadx.gui.JadxWrapper
;
...
...
@@ -24,6 +28,8 @@ public class JRoot extends JNode {
private
transient
boolean
flatPackages
=
false
;
private
final
List
<
JNode
>
customNodes
=
new
ArrayList
<>();
public
JRoot
(
JadxWrapper
wrapper
)
{
this
.
wrapper
=
wrapper
;
}
...
...
@@ -37,10 +43,8 @@ public class JRoot extends JNode {
jRes
.
update
();
add
(
jRes
);
}
ApkSignature
signature
=
ApkSignature
.
getApkSignature
(
wrapper
);
if
(
signature
!=
null
)
{
add
(
signature
);
for
(
JNode
customNode
:
customNodes
)
{
add
(
customNode
);
}
}
...
...
@@ -108,6 +112,19 @@ public class JRoot extends JNode {
}
}
public
void
replaceCustomNode
(
@Nullable
JNode
node
)
{
if
(
node
==
null
)
{
return
;
}
Class
<?>
nodeCls
=
node
.
getClass
();
customNodes
.
removeIf
(
n
->
n
.
getClass
().
equals
(
nodeCls
));
customNodes
.
add
(
node
);
}
public
List
<
JNode
>
getCustomNodes
()
{
return
customNodes
;
}
@Override
public
Icon
getIcon
()
{
return
ROOT_ICON
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/CertificatePanel.java
已删除
100644 → 0
浏览文件 @
cc99409a
package
jadx.gui.ui
;
import
java.awt.*
;
import
javax.swing.*
;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.codearea.CodeArea
;
public
final
class
CertificatePanel
extends
ContentPanel
{
private
static
final
long
serialVersionUID
=
8566591625905036877L
;
private
final
RSyntaxTextArea
textArea
;
CertificatePanel
(
TabbedPane
panel
,
JNode
jnode
)
{
super
(
panel
,
jnode
);
setLayout
(
new
BorderLayout
());
textArea
=
new
RSyntaxTextArea
(
jnode
.
getContent
());
loadSettings
();
JScrollPane
sp
=
new
JScrollPane
(
textArea
);
add
(
sp
);
}
@Override
public
void
loadSettings
()
{
CodeArea
.
loadCommonSettings
(
getTabbedPane
().
getMainWindow
(),
textArea
);
}
}
jadx-gui/src/main/java/jadx/gui/ui/ContentPanel.java
浏览文件 @
b5720bd1
...
...
@@ -34,8 +34,6 @@ public abstract class ContentPanel extends JPanel {
* selected entry inside the APK file.
*
* If <code>null</code> is returned no tool tip will be displayed.
*
* @return
*/
@Nullable
public
String
getTabTooltip
()
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java
浏览文件 @
b5720bd1
...
...
@@ -22,7 +22,7 @@ import jadx.gui.ui.codearea.AbstractCodeArea;
public
class
ImagePanel
extends
ContentPanel
{
private
static
final
long
serialVersionUID
=
4071356367073142688L
;
ImagePanel
(
TabbedPane
panel
,
JResource
res
)
{
public
ImagePanel
(
TabbedPane
panel
,
JResource
res
)
{
super
(
panel
,
res
);
setLayout
(
new
BorderLayout
());
try
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
浏览文件 @
b5720bd1
...
...
@@ -93,6 +93,7 @@ import jadx.gui.jobs.DecompileTask;
import
jadx.gui.jobs.ExportTask
;
import
jadx.gui.jobs.IndexService
;
import
jadx.gui.jobs.TaskStatus
;
import
jadx.gui.plugins.quark.QuarkDialog
;
import
jadx.gui.settings.JadxProject
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.settings.JadxSettingsWindow
;
...
...
@@ -125,7 +126,6 @@ import static jadx.gui.utils.FileUtils.fileNamesToPaths;
import
static
jadx
.
gui
.
utils
.
FileUtils
.
toPaths
;
import
static
javax
.
swing
.
KeyStroke
.
getKeyStroke
;
@SuppressWarnings
(
"serial"
)
public
class
MainWindow
extends
JFrame
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
MainWindow
.
class
);
...
...
@@ -379,33 +379,43 @@ public class MainWindow extends JFrame {
}
void
open
(
List
<
Path
>
paths
,
Runnable
onFinish
)
{
if
(
paths
.
size
()
==
1
&&
paths
.
get
(
0
).
getFileName
().
toString
().
toLowerCase
(
Locale
.
ROOT
).
endsWith
(
JadxProject
.
PROJECT_EXTENSION
))
{
openProject
(
paths
.
get
(
0
));
onFinish
.
run
();
}
else
{
project
.
setFilePath
(
paths
);
clearTree
();
BreakpointManager
.
saveAndExit
();
if
(
paths
.
isEmpty
())
{
if
(
paths
.
size
()
==
1
)
{
Path
singleFile
=
paths
.
get
(
0
);
if
(
singleFile
.
getFileName
().
toString
().
toLowerCase
(
Locale
.
ROOT
).
endsWith
(
JadxProject
.
PROJECT_EXTENSION
))
{
openProject
(
singleFile
);
onFinish
.
run
();
return
;
}
backgroundExecutor
.
execute
(
NLS
.
str
(
"progress.load"
),
()
->
wrapper
.
openFile
(
paths
),
(
status
)
->
{
if
(
status
==
TaskStatus
.
CANCEL_BY_MEMORY
)
{
showHeapUsageBar
();
UiUtils
.
errorMessage
(
this
,
NLS
.
str
(
"message.memoryLow"
));
return
;
}
deobfToggleBtn
.
setSelected
(
settings
.
isDeobfuscationOn
());
initTree
();
update
();
runInitialBackgroundJobs
();
BreakpointManager
.
init
(
paths
.
get
(
0
).
getParent
());
onFinish
.
run
();
});
}
project
.
setFilePath
(
paths
);
clearTree
();
BreakpointManager
.
saveAndExit
();
if
(
paths
.
isEmpty
())
{
return
;
}
backgroundExecutor
.
execute
(
NLS
.
str
(
"progress.load"
),
()
->
wrapper
.
openFile
(
paths
),
status
->
{
if
(
status
==
TaskStatus
.
CANCEL_BY_MEMORY
)
{
showHeapUsageBar
();
UiUtils
.
errorMessage
(
this
,
NLS
.
str
(
"message.memoryLow"
));
return
;
}
onOpen
(
paths
);
onFinish
.
run
();
});
}
private
void
onOpen
(
List
<
Path
>
paths
)
{
deobfToggleBtn
.
setSelected
(
settings
.
isDeobfuscationOn
());
initTree
();
update
();
runInitialBackgroundJobs
();
BreakpointManager
.
init
(
paths
.
get
(
0
).
getParent
());
}
private
void
addTreeCustomNodes
()
{
treeRoot
.
replaceCustomNode
(
ApkSignature
.
getApkSignature
(
wrapper
));
}
private
boolean
ensureProjectIsSaved
()
{
...
...
@@ -592,11 +602,12 @@ public class MainWindow extends JFrame {
public
void
initTree
()
{
treeRoot
=
new
JRoot
(
wrapper
);
cacheObject
.
setJRoot
(
treeRoot
);
treeRoot
.
setFlatPackages
(
isFlattenPackage
);
treeModel
.
setRoot
(
treeRoot
);
addTreeCustomNodes
();
treeRoot
.
update
();
reloadTree
();
cacheObject
.
setJRoot
(
treeRoot
);
cacheObject
.
setJadxSettings
(
settings
);
}
...
...
@@ -677,16 +688,14 @@ public class MainWindow extends JFrame {
JResource
res
=
(
JResource
)
obj
;
ResourceFile
resFile
=
res
.
getResFile
();
if
(
resFile
!=
null
&&
JResource
.
isSupportedForView
(
resFile
.
getType
()))
{
tabbedPane
.
show
Resourc
e
(
res
);
tabbedPane
.
show
Nod
e
(
res
);
}
}
else
if
(
obj
instanceof
ApkSignature
)
{
tabbedPane
.
showSimpleNode
((
JNode
)
obj
);
}
else
if
(
obj
instanceof
QuarkReport
)
{
tabbedPane
.
showSimpleNode
((
JNode
)
obj
);
}
else
if
(
obj
instanceof
JNode
)
{
JNode
node
=
(
JNode
)
obj
;
if
(
node
.
getRootClass
()
!=
null
)
{
tabbedPane
.
codeJump
(
new
JumpPosition
(
node
));
}
else
{
tabbedPane
.
showNode
(
node
);
}
}
}
catch
(
Exception
e
)
{
...
...
@@ -991,10 +1000,12 @@ public class MainWindow extends JFrame {
JMenu
tools
=
new
JMenu
(
NLS
.
str
(
"menu.tools"
));
tools
.
setMnemonic
(
KeyEvent
.
VK_T
);
tools
.
add
(
deobfMenuItem
);
tools
.
add
(
logAction
);
tools
.
add
(
quarkAction
);
tools
.
add
(
openDeviceAction
);
JMenu
help
=
new
JMenu
(
NLS
.
str
(
"menu.help"
));
help
.
setMnemonic
(
KeyEvent
.
VK_H
);
help
.
add
(
logAction
);
help
.
add
(
aboutAction
);
JMenuBar
menuBar
=
new
JMenuBar
();
...
...
@@ -1034,15 +1045,13 @@ public class MainWindow extends JFrame {
toolbar
.
add
(
forwardAction
);
toolbar
.
addSeparator
();
toolbar
.
add
(
deobfToggleBtn
);
toolbar
.
add
(
quarkAction
);
toolbar
.
add
(
openDeviceAction
);
toolbar
.
addSeparator
();
toolbar
.
add
(
logAction
);
toolbar
.
addSeparator
();
toolbar
.
add
(
prefsAction
);
toolbar
.
addSeparator
();
toolbar
.
add
(
quarkAction
);
toolbar
.
addSeparator
();
toolbar
.
add
(
openDeviceAction
);
toolbar
.
addSeparator
();
toolbar
.
add
(
Box
.
createHorizontalGlue
());
toolbar
.
add
(
updateLink
);
...
...
@@ -1193,7 +1202,7 @@ public class MainWindow extends JFrame {
pathList
.
add
(
name
);
path
=
path
.
getParentPath
();
}
return
pathList
.
toArray
(
new
String
[
pathList
.
size
()
]);
return
pathList
.
toArray
(
new
String
[
0
]);
}
public
static
void
getExpandedPaths
(
JTree
tree
,
TreePath
path
,
List
<
TreePath
>
list
)
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/QuarkDialog.java
已删除
100644 → 0
浏览文件 @
cc99409a
package
jadx.gui.ui
;
import
java.awt.BorderLayout
;
import
java.awt.Container
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.InputStreamReader
;
import
java.io.Reader
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
javax.swing.JButton
;
import
javax.swing.JComboBox
;
import
javax.swing.JDialog
;
import
javax.swing.JLabel
;
import
javax.swing.JOptionPane
;
import
javax.swing.JPanel
;
import
javax.swing.WindowConstants
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.google.gson.JsonObject
;
import
com.google.gson.JsonParser
;
import
jadx.gui.jobs.IBackgroundTask
;
import
jadx.gui.jobs.TaskStatus
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.treemodel.JRoot
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
class
QuarkDialog
extends
JDialog
{
private
static
final
long
serialVersionUID
=
4855753773520368215L
;
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
QuarkDialog
.
class
);
private
static
final
String
QUARK_CMD_LOG_MESSAGE
=
"Running Quark cmd: {}"
;
private
static
final
String
QUARK_INTERRUPT_MESSAGE
=
"Quark process interrupted: {}"
;
private
static
final
String
QUARK_FAILED_MESSAGE
=
"Failed to execute Quark."
;
private
static
final
String
QUARK_CMD
=
"quark"
;
private
static
final
int
LARGE_APK_SIZE
=
30
;
private
static
final
Path
QUARK_DIR_PATH
=
Paths
.
get
(
System
.
getProperty
(
"user.home"
),
".quark-engine"
);
private
Path
venvPath
=
Paths
.
get
(
QUARK_DIR_PATH
.
toString
(),
"quark_venv"
);
private
File
quarkReportFile
;
private
final
transient
JadxSettings
settings
;
private
final
transient
MainWindow
mainWindow
;
private
JComboBox
<
String
>
fileSelectCombo
;
private
final
List
<
Path
>
files
;
private
Map
<
String
,
Path
>
choosableFiles
=
new
HashMap
<>();
public
QuarkDialog
(
MainWindow
mainWindow
)
{
this
.
mainWindow
=
mainWindow
;
this
.
settings
=
mainWindow
.
getSettings
();
this
.
files
=
mainWindow
.
getWrapper
().
getOpenPaths
();
fileNameExtensionFilter
();
if
(
choosableFiles
.
isEmpty
())
{
UiUtils
.
errorMessage
(
mainWindow
,
"Quark is unable to analyze the selected file."
);
LOG
.
error
(
"Quark: The files cannot be analyze. {}"
,
files
);
return
;
}
initUI
();
}
private
void
fileNameExtensionFilter
()
{
String
[]
extensions
=
new
String
[]
{
"apk"
,
"dex"
};
for
(
Path
filePath
:
this
.
files
)
{
String
fileName
=
filePath
.
toString
();
int
dotIndex
=
fileName
.
lastIndexOf
(
'.'
);
String
extension
=
(
dotIndex
==
-
1
)
?
""
:
fileName
.
substring
(
dotIndex
+
1
);
if
(
Arrays
.
stream
(
extensions
).
noneMatch
(
extension:
:
equals
))
{
LOG
.
debug
(
"Quark: {} is not apk nor dex"
,
fileName
);
continue
;
}
choosableFiles
.
put
(
fileName
,
filePath
);
}
}
public
final
void
initUI
()
{
JLabel
description
=
new
JLabel
(
"Analyzing apk using Quark-Engine"
);
JLabel
selectApkText
=
new
JLabel
(
"Select Apk/Dex"
);
description
.
setAlignmentX
(
0.5f
);
String
[]
comboFiles
=
choosableFiles
.
keySet
().
toArray
(
new
String
[
choosableFiles
.
size
()]);
fileSelectCombo
=
new
JComboBox
<>(
comboFiles
);
JPanel
textPane
=
new
JPanel
();
textPane
.
add
(
description
);
JPanel
selectApkPanel
=
new
JPanel
();
selectApkPanel
.
add
(
selectApkText
);
selectApkPanel
.
add
(
fileSelectCombo
);
JPanel
buttonPane
=
new
JPanel
();
JButton
start
=
new
JButton
(
"Start"
);
JButton
close
=
new
JButton
(
NLS
.
str
(
"tabs.close"
));
close
.
addActionListener
(
event
->
close
());
start
.
addActionListener
(
event
->
mainWindow
.
getBackgroundExecutor
().
execute
(
new
QuarkTask
()));
buttonPane
.
add
(
start
);
buttonPane
.
add
(
close
);
getRootPane
().
setDefaultButton
(
close
);
JPanel
centerPane
=
new
JPanel
();
centerPane
.
add
(
selectApkPanel
);
Container
contentPane
=
getContentPane
();
contentPane
.
add
(
textPane
,
BorderLayout
.
PAGE_START
);
contentPane
.
add
(
centerPane
);
contentPane
.
add
(
buttonPane
,
BorderLayout
.
PAGE_END
);
setTitle
(
"Quark Engine"
);
pack
();
if
(!
mainWindow
.
getSettings
().
loadWindowPos
(
this
))
{
setSize
(
300
,
140
);
}
setLocationRelativeTo
(
null
);
setDefaultCloseOperation
(
WindowConstants
.
DISPOSE_ON_CLOSE
);
setModalityType
(
ModalityType
.
MODELESS
);
UiUtils
.
addEscapeShortCutToDispose
(
this
);
}
private
void
close
()
{
dispose
();
}
@Override
public
void
dispose
()
{
settings
.
saveWindowPos
(
this
);
super
.
dispose
();
}
private
class
QuarkTask
implements
IBackgroundTask
{
private
Process
quarkProcess
;
private
boolean
isVenv
=
false
;
public
QuarkTask
()
{
dispose
();
}
private
boolean
isPipInstalled
()
{
List
<
String
>
cmdList
=
new
ArrayList
<>();
cmdList
.
add
(
"pip3"
);
return
executeCommand
(
cmdList
);
}
private
boolean
isQuarkInstalled
()
{
List
<
String
>
cmdList
=
new
ArrayList
<>();
cmdList
.
add
(
QUARK_CMD
);
if
(
executeCommand
(
cmdList
))
{
return
true
;
}
isVenv
=
true
;
cmdList
=
new
ArrayList
<>();
cmdList
.
add
(
getVenvPath
(
QUARK_CMD
).
toString
());
return
executeCommand
(
cmdList
);
}
private
void
createVirtualenv
()
{
// Check if venv exist
if
(
Files
.
exists
(
getVenvPath
(
"activate"
)))
{
return
;
}
List
<
String
>
cmdList
=
new
ArrayList
<>();
if
(
System
.
getProperty
(
"os.name"
).
toLowerCase
().
indexOf
(
"win"
)
>=
0
)
{
cmdList
.
add
(
"python"
);
cmdList
.
add
(
"-m"
);
cmdList
.
add
(
"venv"
);
}
else
{
cmdList
.
add
(
"virtualenv"
);
}
cmdList
.
add
(
venvPath
.
toString
());
try
{
LOG
.
debug
(
QUARK_CMD_LOG_MESSAGE
,
cmdList
);
Process
process
=
Runtime
.
getRuntime
().
exec
(
cmdList
.
toArray
(
new
String
[
0
]));
process
.
waitFor
();
}
catch
(
InterruptedException
e
)
{
LOG
.
error
(
QUARK_INTERRUPT_MESSAGE
,
e
.
getMessage
(),
e
);
Thread
.
currentThread
().
interrupt
();
}
catch
(
Exception
e
)
{
UiUtils
.
errorMessage
(
mainWindow
,
"Failed to create virtual environment."
);
LOG
.
error
(
"Failed to create virtual environment: {}"
,
e
.
getMessage
(),
e
);
}
}
private
boolean
installQuark
()
{
List
<
String
>
cmdList
=
new
ArrayList
<>();
String
command
=
(
isVenv
)
?
getVenvPath
(
"pip3"
).
toString
()
:
"pip3"
;
cmdList
.
add
(
command
);
cmdList
.
add
(
"install"
);
cmdList
.
add
(
"quark-engine"
);
cmdList
.
add
(
"--upgrade"
);
try
{
LOG
.
debug
(
QUARK_CMD_LOG_MESSAGE
,
cmdList
);
Process
process
=
Runtime
.
getRuntime
().
exec
(
cmdList
.
toArray
(
new
String
[
0
]));
process
.
waitFor
();
if
(!
isQuarkInstalled
())
{
return
false
;
}
}
catch
(
InterruptedException
e
)
{
LOG
.
error
(
QUARK_INTERRUPT_MESSAGE
,
e
.
getMessage
(),
e
);
Thread
.
currentThread
().
interrupt
();
}
catch
(
Exception
e
)
{
UiUtils
.
errorMessage
(
mainWindow
,
"Failed to install quark-engine."
);
LOG
.
error
(
"Failed to execute pip install command: {}"
,
String
.
join
(
" "
,
cmdList
),
e
);
return
false
;
}
return
true
;
}
private
void
updateQuarkRules
()
{
List
<
String
>
cmdList
=
new
ArrayList
<>();
String
command
=
(
isVenv
)
?
getVenvPath
(
"freshquark"
).
toString
()
:
"freshquark"
;
cmdList
.
add
(
command
);
executeCommand
(
cmdList
);
}
private
boolean
analyzeAPK
()
{
try
{
updateQuarkRules
();
quarkReportFile
=
File
.
createTempFile
(
"QuarkReport-"
,
".json"
);
String
apkName
=
(
String
)
fileSelectCombo
.
getSelectedItem
();
String
apkPath
=
choosableFiles
.
get
(
apkName
).
toString
();
List
<
String
>
cmdList
=
new
ArrayList
<>();
String
command
=
(
isVenv
)
?
getVenvPath
(
QUARK_CMD
).
toString
()
:
QUARK_CMD
;
cmdList
.
add
(
command
);
cmdList
.
add
(
"-a"
);
cmdList
.
add
(
apkPath
);
cmdList
.
add
(
"-o"
);
cmdList
.
add
(
quarkReportFile
.
getAbsolutePath
());
LOG
.
debug
(
QUARK_CMD_LOG_MESSAGE
,
cmdList
);
quarkProcess
=
Runtime
.
getRuntime
().
exec
(
cmdList
.
toArray
(
new
String
[
0
]));
try
(
BufferedReader
buf
=
new
BufferedReader
(
new
InputStreamReader
(
quarkProcess
.
getInputStream
())))
{
String
output
=
null
;
while
((
output
=
buf
.
readLine
())
!=
null
)
{
LOG
.
debug
(
output
);
}
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to execute Quark: {}"
,
e
.
getMessage
(),
e
);
return
false
;
}
return
true
;
}
private
boolean
executeCommand
(
List
<
String
>
cmdList
)
{
try
{
LOG
.
debug
(
QUARK_CMD_LOG_MESSAGE
,
cmdList
);
Process
process
=
Runtime
.
getRuntime
().
exec
(
cmdList
.
toArray
(
new
String
[
0
]));
process
.
waitFor
();
}
catch
(
InterruptedException
e
)
{
LOG
.
error
(
QUARK_INTERRUPT_MESSAGE
,
e
.
getMessage
(),
e
);
Thread
.
currentThread
().
interrupt
();
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to execute command: {}"
,
String
.
join
(
" "
,
cmdList
),
e
);
return
false
;
}
return
true
;
}
public
boolean
checkFileSize
(
int
sizeThreshold
)
{
String
apkName
=
(
String
)
fileSelectCombo
.
getSelectedItem
();
try
{
int
fileSize
=
(
int
)
Files
.
size
(
choosableFiles
.
get
(
apkName
))
/
1024
/
1024
;
if
(
fileSize
>
sizeThreshold
)
{
return
false
;
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to calculate file: {}"
,
e
.
getMessage
(),
e
);
return
false
;
}
return
true
;
}
private
void
loadReportFile
()
{
try
(
Reader
reader
=
new
FileReader
(
quarkReportFile
))
{
JsonObject
quarkReport
=
(
JsonObject
)
JsonParser
.
parseReader
(
reader
);
QuarkReport
quarkNode
=
QuarkReport
.
analysisAPK
(
quarkReport
);
JRoot
root
=
mainWindow
.
getCacheObject
().
getJRoot
();
root
.
update
();
root
.
add
(
quarkNode
);
mainWindow
.
reloadTree
();
}
catch
(
Exception
e
)
{
UiUtils
.
errorMessage
(
mainWindow
,
"Failed to load Quark report."
);
LOG
.
error
(
"Failed to load Quark report."
,
e
);
}
}
private
Path
getVenvPath
(
String
cmd
)
{
String
os
=
System
.
getProperty
(
"os.name"
).
toLowerCase
();
if
(
os
.
indexOf
(
"win"
)
>=
0
)
{
return
Paths
.
get
(
venvPath
.
toString
(),
"Scripts"
,
String
.
format
(
"%s.exe"
,
cmd
));
}
else
{
return
Paths
.
get
(
venvPath
.
toString
(),
"bin"
,
cmd
);
}
}
@Override
public
String
getTitle
()
{
return
"Quark:"
;
}
@Override
public
boolean
canBeCanceled
()
{
return
true
;
}
@Override
public
List
<
Runnable
>
scheduleJobs
()
{
List
<
Runnable
>
jobs
=
new
ArrayList
<>();
// mkdir `$HOME/.quark-engine/`
File
directory
=
new
File
(
QUARK_DIR_PATH
.
toString
());
if
(!
directory
.
isDirectory
())
{
directory
.
mkdirs
();
}
if
(!
checkFileSize
(
LARGE_APK_SIZE
))
{
int
result
=
JOptionPane
.
showConfirmDialog
(
mainWindow
,
"The selected file size is too large (over 30M) that may take a long time to analyze, do you want to continue"
,
"Quark: Warning"
,
JOptionPane
.
YES_NO_OPTION
);
if
(
result
==
JOptionPane
.
NO_OPTION
)
{
return
jobs
;
}
}
jobs
.
add
(()
->
{
if
(!
isPipInstalled
())
{
UiUtils
.
errorMessage
(
mainWindow
,
"Pip is not installed."
);
LOG
.
error
(
"Pip is not installed"
);
mainWindow
.
cancelBackgroundJobs
();
}
});
jobs
.
add
(()
->
{
mainWindow
.
getProgressPane
().
setLabel
(
"Check Quark installed"
);
if
(!
isQuarkInstalled
())
{
LOG
.
warn
(
"Quark is not installed, do you want to install it from PyPI?"
);
int
result
=
JOptionPane
.
showConfirmDialog
(
mainWindow
,
"Quark is not installed, do you want to install it from PyPI?"
,
"Warning"
,
JOptionPane
.
YES_NO_OPTION
);
if
(
result
==
JOptionPane
.
YES_OPTION
)
{
mainWindow
.
getProgressPane
().
setLabel
(
"Installing Quark"
);
createVirtualenv
();
if
(!
installQuark
())
{
UiUtils
.
errorMessage
(
mainWindow
,
"Failed to install quark-engine."
);
mainWindow
.
cancelBackgroundJobs
();
}
}
if
(
result
==
JOptionPane
.
NO_OPTION
)
{
mainWindow
.
cancelBackgroundJobs
();
}
}
});
jobs
.
add
(()
->
{
mainWindow
.
getProgressPane
().
setLabel
(
"Analyzing"
);
if
(!
analyzeAPK
())
{
UiUtils
.
errorMessage
(
mainWindow
,
"Quark: Failed to analyze apk."
);
mainWindow
.
cancelBackgroundJobs
();
}
});
return
jobs
;
}
@Override
public
void
onFinish
(
TaskStatus
status
,
long
skipped
)
{
if
(
quarkProcess
.
exitValue
()
!=
0
)
{
LOG
.
error
(
QUARK_FAILED_MESSAGE
);
return
;
}
loadReportFile
();
}
}
}
jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java
浏览文件 @
b5720bd1
...
...
@@ -222,11 +222,9 @@ public class RenameDialog extends JDialog {
UiUtils
.
errorMessage
(
this
,
NLS
.
str
(
"message.memoryLow"
));
}
if
(
node
instanceof
JPackage
)
{
// reinit tree
mainWindow
.
initTree
();
}
else
{
mainWindow
.
reloadTree
();
mainWindow
.
getTreeRoot
().
update
();
}
mainWindow
.
reloadTree
();
});
}
}
...
...
jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java
浏览文件 @
b5720bd1
...
...
@@ -20,19 +20,14 @@ import org.jetbrains.annotations.Nullable;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.ResourceFile
;
import
jadx.api.ResourceType
;
import
jadx.core.utils.StringUtils
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.gui.treemodel.ApkSignature
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.treemodel.JResource
;
import
jadx.gui.ui.codearea.*
;
import
jadx.gui.ui.codearea.AbstractCodeArea
;
import
jadx.gui.ui.codearea.AbstractCodeContentPanel
;
import
jadx.gui.ui.codearea.ClassCodeContentPanel
;
import
jadx.gui.ui.codearea.
CodeContentPanel
;
import
jadx.gui.ui.codearea.
SmaliArea
;
import
jadx.gui.utils.JumpManager
;
import
jadx.gui.utils.JumpPosition
;
...
...
@@ -203,20 +198,16 @@ public class TabbedPane extends JTabbedPane {
});
}
public
void
show
Resource
(
JResource
res
)
{
final
ContentPanel
contentPanel
=
getContentPanel
(
res
);
public
void
show
Node
(
JNode
node
)
{
final
ContentPanel
contentPanel
=
getContentPanel
(
node
);
if
(
contentPanel
==
null
)
{
return
;
}
SwingUtilities
.
invokeLater
(()
->
setSelectedComponent
(
contentPanel
));
}
public
void
showSimpleNode
(
JNode
node
)
{
final
ContentPanel
contentPanel
=
getContentPanel
(
node
);
if
(
contentPanel
==
null
)
{
return
;
}
SwingUtilities
.
invokeLater
(()
->
setSelectedComponent
(
contentPanel
));
public
void
codeJump
(
JNode
node
)
{
codeJump
(
new
JumpPosition
(
node
));
}
public
void
codeJump
(
JumpPosition
pos
)
{
...
...
@@ -292,7 +283,7 @@ public class TabbedPane extends JTabbedPane {
private
ContentPanel
getContentPanel
(
JNode
node
)
{
ContentPanel
panel
=
openTabs
.
get
(
node
);
if
(
panel
==
null
)
{
panel
=
makeContentPanel
(
node
);
panel
=
node
.
getContentPanel
(
this
);
if
(
panel
==
null
)
{
return
null
;
}
...
...
@@ -311,29 +302,6 @@ public class TabbedPane extends JTabbedPane {
}
}
@Nullable
private
ContentPanel
makeContentPanel
(
JNode
node
)
{
if
(
node
instanceof
JResource
)
{
JResource
res
=
(
JResource
)
node
;
ResourceFile
resFile
=
res
.
getResFile
();
if
(
resFile
!=
null
)
{
if
(
resFile
.
getType
()
==
ResourceType
.
IMG
)
{
return
new
ImagePanel
(
this
,
res
);
}
return
new
CodeContentPanel
(
this
,
node
);
}
else
{
return
null
;
}
}
if
(
node
instanceof
ApkSignature
)
{
return
new
HtmlPanel
(
this
,
node
);
}
if
(
node
instanceof
QuarkReport
)
{
return
new
HtmlPanel
(
this
,
node
);
}
return
new
ClassCodeContentPanel
(
this
,
node
);
}
@Nullable
ContentPanel
getSelectedCodePanel
()
{
return
(
ContentPanel
)
getSelectedComponent
();
...
...
@@ -418,7 +386,7 @@ public class TabbedPane extends JTabbedPane {
pane
.
addFocusListener
(
listener
);
return
;
}
throw
new
JadxRuntimeException
(
"Add the new ContentPanel to TabbedPane.FocusManager: "
+
pane
);
//
throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane);
}
static
void
focusOnCodePanel
(
ContentPanel
pane
)
{
...
...
@@ -444,7 +412,7 @@ public class TabbedPane extends JTabbedPane {
SwingUtilities
.
invokeLater
(((
ImagePanel
)
pane
)::
requestFocusInWindow
);
return
;
}
throw
new
JadxRuntimeException
(
"Add the new ContentPanel to TabbedPane.FocusManager: "
+
pane
);
//
throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录