根据自身使用GDA的经历,进行梳理归纳,方便初学者学习使用,因自身技术水平有限,若有不当之处,盼望指正。 注:根据自身理解与时间安排,会不定时对此篇文章内容进行更新与完善 当前更新日期:2023年5月17日 GDA版本:4.0.6
https://bbs.kanxue.com/thread-278222.htm
GGJoy Dex Analysizer(GDA),中国第一款也是唯一一款全交互式的现代反编译器,同时也是世界上最早实现的dalvik字节码反编译器。 GDA不仅只是反编译器,同时也是一款轻便且功能强大的综合性逆向分析利器,其不依赖java且支持apk、dex、odex、oat、jar、aar、class文件的反编译, 支持python,java脚本自动化分析。
此操作方便分析使用 在“运行”窗口或“文件管理器”的地址栏中输入如下命令,可快速定位到发送到目录
此操作方便分析使用,快捷键 示例:使用快捷键Esc返回到恶意行为分析页面
载入分析文件时,会显示分析主界面,若加固会有提示,或在BaseInfo模块查看 示例:
通过BaseInfo模块查看被分析文件基本情况 示例:
常用于判断被分析目标是否合规与查询其作者或开发商
查询此文件可查看Manifest架构情况与权限属性值定义情况,并可查看allowBackup、debuggable属性判断是否存在安全风险 示例: 动态图演示 存在漏洞的演示图片 allowBackup属性值为true或未配置allowBackup=“false”,则表示存在漏洞 漏洞成因解析
可在AllAPI模块查看所调用的API,可用于分析是否存在危险行为 示例:
根据文字判断是否存在恶意描述,进而根据这些字符串深入分析后判断是否存在恶意行为 AllStrings与AppStrings可查询字符串信息,其中AllStrings会获取该APK所有的字符串,而AppStrings只会获取APK有效类会用到的字符串
使用此功能模块可简单的判断被分析文件(如.apk文件)是否存在可被攻击者恶意利用的风险项 示例: 扫描出了一些存在威胁的行为,并可查看引用此行为的对象,方便进一步进行深入分析,如看看读取了那些敏感文件: 数据流分析发现使用了android.util.log(比较敏感的方法会用特殊颜色标注方便查找)方法,简单分析为读取了错误日志文件(深入分析步骤在其它分段展示)
此功能方便了解被分析应用是否存在获取敏感权限的行为,与点击要分析的模块查看具体那个模块使用,跟踪这些内容可进行简单的行为判定 示例:
方便直接获取一般取证时所用的信息 功能模块:工具-APK取证分析
功能支持说明: 节选于GDA GitHub说明 准备: 因此功能依赖于dx工具,故需dx可正常使用。
注意:有些.jar文件dx是无法解析的(如其目录下的core-lambda-stubs.jar、apktool_2.4.1.jar等等##dx版本问题,可使用更新的版本试试)
初始使用GDA反编译.jar文件会弹出提示,选择dx路径即可。 使用演示:
使用可实时更新文本状态的文件打开配置文件,如:HBuilder x 故障:当载入dx无法解析的.jar文件,在此载入会弹出选择dx路径窗口(GDA已成功解析.jar文件,会在配置文件中保存dx目录) 通过监控配置文件,会发现载入无法解析的.jar文件会引起GDA清除之前dx的路径信息,如下图对比演示: 成功解析.jar文件: 无法解析.jar文件:
若Google翻译有问题,切换到有道即可 视图-环境配置 目前无分割语句会导致翻译无变化,需手动修改 示例: EditTextPreferenceDialogFragment 注意:因编辑字符串限制无法超出原字符串字节长度故需妥善删减修改
此知识方便结合GDA进行分析使用
获取 debuggable 值的API接口
shell:sendto
android:allowBackup 是否允许应用参与备份和恢复基础架构。如果将此属性设为 false,则永远不会为该应用执行备份或恢复,即使是采用全系统备份方法也不例外(这种备份方法通常会通过 adb 保存所有应用数据)。此属性的默认值为 true。
当allowBackup标志为true时,用户即可通过adb backup和adb restore来进行对应用数据的备份和恢复,这可能会带来一定的安全风险例如:通过此技术窃取敏感数据。
android:allowBackup 是否允许应用参与备份和恢复基础架构。如果将此属性设为 false,则永远不会为该应用执行备份或恢复,即使是采用全系统备份方法也不例外(这种备份方法通常会通过 adb 保存所有应用数据)。此属性的默认值为 true。
当allowBackup标志为true时,用户即可通过adb backup和adb restore来进行对应用数据的备份和恢复,这可能会带来一定的安全风险例如:通过此技术窃取敏感数据。
默认情况若系统安装Android Studio则就拥有dx工具,其默认保存路径为
Windows系统:
C:\Users\用户名\AppData\Local\Android\Sdk\build
-
tools\版本文件夹
名称:dx.bat
方便使用,可将其添加到系统环境变量
JDK支持:我这里使用了jdk
16
dx运行报错解决:
1.
查看java是否可正常使用
2.
修改dx源文件
dx.bat 最后一行
原始数据:call
"%java_exe%"
%
javaOpts
%
-
Djava.ext.dirs
=
"%frameworkdir%"
-
jar
"%jarpath%"
%
params
%
修改数据:call
"%java_exe%"
%
javaOpts
%
-
classpath
"%frameworkdir%"
-
jar
"%jarpath%"
%
params
%
默认情况若系统安装Android Studio则就拥有dx工具,其默认保存路径为
Windows系统:
C:\Users\用户名\AppData\Local\Android\Sdk\build
-
tools\版本文件夹
名称:dx.bat
方便使用,可将其添加到系统环境变量
JDK支持:我这里使用了jdk
16
dx运行报错解决:
1.
查看java是否可正常使用
2.
修改dx源文件
dx.bat 最后一行
原始数据:call
"%java_exe%"
%
javaOpts
%
-
Djava.ext.dirs
=
"%frameworkdir%"
-
jar
"%jarpath%"
%
params
%
修改数据:call
"%java_exe%"
%
javaOpts
%
-
classpath
"%frameworkdir%"
-
jar
"%jarpath%"
%
params
%
路径:C:\Users\用户名\AppData\Roaming\GDA
名称:config.dat
路径:C:\Users\用户名\AppData\Roaming\GDA
名称:config.dat
原:EditTextPreferenceDialogFragment
45
64
69
74
54
65
78
74
50
72
65
66
65
72
65
6e
63
65
44
69
61
6c
6f
67
46
72
61
67
6d
65
6e
74
2e
74
65
78
74
00
翻译:编辑文本首选项对话框片段
e7 bc
96
e8 be
91
e6
96
87
e6
9c
ac e9 a6
96
e9
80
89
e9 a1 b9 e5 af b9 e8 af
9d
e6 a1
86
e7
89
87
e6 ae b5
2e
74
65
78
74
00
/
/
字节超出
修改:编辑首选项对话框片段
e7 bc
96
e8 be
91
e9 a6
96
e9
80
89
e9 a1 b9 e5 af b9 e8 af
9d
e6 a1
86
e7
89
87
e6 ae b5
2e
74
65
78
74
00
原:EditTextPreferenceDialogFragment
45
64
69
74
54
65
78
74
50
72
65
66
65
72
65
6e
63
65
44
69
61
6c
6f
67
46
72
61
67
6d
65
6e
74
2e
74
65
78
74
00
翻译:编辑文本首选项对话框片段
e7 bc
96
e8 be
91
e6
96
87
e6
9c
ac e9 a6
96
e9
80
89
e9 a1 b9 e5 af b9 e8 af
9d
e6 a1
86
e7
89
87
e6 ae b5
2e
74
65
78
74
00
/
/
字节超出
修改:编辑首选项对话框片段
e7 bc
96
e8 be
91
e9 a6
96
e9
80
89
e9 a1 b9 e5 af b9 e8 af
9d
e6 a1
86
e7
89
87
e6 ae b5
2e
74
65
78
74
00
Uri uri
=
Uri.parse(
"https://bbs.pediy.com/"
);
Intent it
=
new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);
Uri uri
=
Uri.parse(
"https://bbs.pediy.com/"
);
Intent it
=
new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);
<uses
-
permission android:name
=
"android.permission.CALL_PHONE"
/
>
<uses
-
permission android:name
=
"android.permission.CALL_PHONE"
/
>
调用拨号程序 Uri
uri
=
Uri.parse(
"tel:号码"
);
Intent it
=
new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);
调用拨号程序 Uri
uri
=
Uri.parse(
"tel:号码"
);
Intent it
=
new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);
/
*
*
*
执行 timeout()
*
注意:如果处于程序调试状态和CC.DEBUG是true,
*
两个都满足情况下,不执行超时 timeout()
*
@param cc
*
/
private void executeTimeout(CC cc) {
if
(!CC.DEBUG) {
cc.timeout();
return
;
}
if
(!Debug.isDebuggerConnected()) {
cc.timeout();
}
}
/
*
*
*
执行 timeout()
*
注意:如果处于程序调试状态和CC.DEBUG是true,
*
两个都满足情况下,不执行超时 timeout()
*
@param cc
*
/
private void executeTimeout(CC cc) {
if
(!CC.DEBUG) {
cc.timeout();
return
;
}
if
(!Debug.isDebuggerConnected()) {
cc.timeout();
}
}
void detectOsDebug(){
boolean connected
=
android.os.Debug.isDebuggerConnected();
Log.d(TAG,
"debugger connect status:"
+
connected);
}
void detectOsDebug(){
boolean connected
=
android.os.Debug.isDebuggerConnected();
Log.d(TAG,
"debugger connect status:"
+
connected);
}
public
class
PreciseCallState implements Parcelable {
public static final
int
PRECISE_CALL_STATE_IDLE
=
0
;
/
/
通话空闲
public static final
int
PRECISE_CALL_STATE_ACTIVE
=
1
;
/
/
正在通话
public static final
int
PRECISE_CALL_STATE_HOLDING
=
2
;
/
/
通话挂起
public static final
int
PRECISE_CALL_STATE_DIALING
=
3
;
/
/
拨号开始
public static final
int
PRECISE_CALL_STATE_ALERTING
=
4
;
/
/
正在呼出
public static final
int
PRECISE_CALL_STATE_INCOMING
=
5
;
/
/
对方来电
public static final
int
PRECISE_CALL_STATE_WAITING
=
6
;
/
/
第三方来电等待
public static final
int
PRECISE_CALL_STATE_DISCONNECTED
=
7
;
/
/
挂断完成
public static final
int
PRECISE_CALL_STATE_DISCONNECTING
=
8
;
/
/
正在挂断
public
class
PreciseCallState implements Parcelable {
public static final
int
PRECISE_CALL_STATE_IDLE
=
0
;
/
/
通话空闲
public static final
int
PRECISE_CALL_STATE_ACTIVE
=
1
;
/
/
正在通话
public static final
int
PRECISE_CALL_STATE_HOLDING
=
2
;
/
/
通话挂起
public static final
int
PRECISE_CALL_STATE_DIALING
=
3
;
/
/
拨号开始
public static final
int
PRECISE_CALL_STATE_ALERTING
=
4
;
/
/
正在呼出
public static final
int
PRECISE_CALL_STATE_INCOMING
=
5
;
/
/
对方来电
public static final
int
PRECISE_CALL_STATE_WAITING
=
6
;
/
/
第三方来电等待
public static final
int
PRECISE_CALL_STATE_DISCONNECTED
=
7
;
/
/
挂断完成
public static final
int
PRECISE_CALL_STATE_DISCONNECTING
=
8
;
/
/
正在挂断
static public String getPhone(Context p0){
String
str
=
"";
try
{
return
p0.getSystemService(
"phone"
).getLine1Number().replace(
"+86"
,
str
).replaceAll(
" "
,
str
);
}catch(java.lang.Exception e
-
1
){
return
str
;
}
}
static public String getPhone(Context p0){
String
str
=
"";
try
{
return
p0.getSystemService(
"phone"
).getLine1Number().replace(
"+86"
,
str
).replaceAll(
" "
,
str
);
}catch(java.lang.Exception e
-
1
){
return
str
;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-8-25 11:22
被梦幻的彼岸编辑
,原因: