-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanalyze_apk.py
More file actions
169 lines (143 loc) · 6.07 KB
/
analyze_apk.py
File metadata and controls
169 lines (143 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import subprocess
import os
import sys
import tempfile
import shutil
from datetime import datetime
# 定义文件路径
APK_FILE = 'Test/ovaa.apk'
SOURCES_SINKS_FILE = 'SourcesAndSinks.txt'
ANDROID_JAR = 'Tools/android.jar'
FLOWDROID_JAR = 'Tools/soot-infoflow-cmd-2.13.0-jar-with-dependencies.jar'
JADX_JAR = 'Tools/jadx-1.5.3-all.jar'
DECOMPILED_DIR = 'sootOutput/decompiled'
# 检查文件是否存在
for file in [APK_FILE, SOURCES_SINKS_FILE, ANDROID_JAR, FLOWDROID_JAR, JADX_JAR]:
if not os.path.exists(file):
print(f"错误: 文件 {file} 不存在")
sys.exit(1)
# 创建输出目录
OUTPUT_DIR = 'sootOutput'
os.makedirs(OUTPUT_DIR, exist_ok=True)
# 生成时间戳后缀
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
# 定义输出文件路径
OUTPUT_FILE = os.path.join(OUTPUT_DIR, f'analysis_result_{timestamp}.xml')
REPORT_FILE = os.path.join(OUTPUT_DIR, f'security_analysis_report_{timestamp}.md')
# 构建FlowDroid命令
# 注意:FlowDroid需要一个包含android.jar的目录结构,我们需要创建一个临时的platforms目录结构
temp_platforms = tempfile.mkdtemp()
try:
# 创建android-34目录
android_dir = os.path.join(temp_platforms, 'android-34')
os.makedirs(android_dir)
# 复制android.jar到临时目录
shutil.copy2(ANDROID_JAR, os.path.join(android_dir, 'android.jar'))
# 构建命令
cmd = [
'java', '-jar', FLOWDROID_JAR,
'-a', APK_FILE,
'-s', SOURCES_SINKS_FILE,
'-p', temp_platforms, # 使用临时platforms目录
'-o', OUTPUT_FILE,
'--paths', # 计算污点传播路径
'-ls', # 记录发现的源点和汇点
'-mc', '100', # 增加每个组件的最大回调数
'-md', '10', # 增加回调链的最大深度
'-d' # 合并所有dex文件
]
print("开始分析 ovaa.apk...")
print(f"执行命令: {' '.join(cmd)}")
# 执行命令
try:
# 执行命令并捕获输出
result = subprocess.run(
cmd,
capture_output=True,
text=True,
cwd=os.path.dirname(os.path.abspath(__file__))
)
# 打印标准输出
print("\n分析输出:")
print(result.stdout)
# 打印错误输出
if result.stderr:
print("\n错误输出:")
print(result.stderr)
# 检查返回码
if result.returncode == 0:
print("\n分析完成成功!")
print(f"分析结果已保存到: {OUTPUT_FILE}")
# 检查结果文件是否存在并显示大小
if os.path.exists(OUTPUT_FILE):
file_size = os.path.getsize(OUTPUT_FILE)
print(f"结果文件大小: {file_size} 字节")
# 构建 Jadx 命令
# -cp ... jadx.cli.JadxCLI 以避免 GUI
jadx_cmd = [
"java", "-Xmx4g", "-cp", JADX_JAR, "jadx.cli.JadxCLI",
"-d", DECOMPILED_DIR,
"--show-bad-code",
"--deobf",
"--threads-count", "4",
"--no-imports",
"--comments-level", "none",
APK_FILE
]
print(f"执行Jadx: {' '.join(jadx_cmd)}")
try:
subprocess.run(
jadx_cmd,
check=True,
stdout=subprocess.DEVNULL, # 抑制标准输出
stderr=subprocess.PIPE, # 捕获错误输出
text=True
)
print("APK反编译完成")
# 验证源码目录
sources_dir = os.path.join(DECOMPILED_DIR, "sources")
if os.path.exists(sources_dir):
print(f"[+] Source Root located at: {sources_dir}")
else:
print("[!] Warning: 'sources' subdirectory not found. Check structure.")
except subprocess.CalledProcessError as e:
print(f"反编译失败: {e.stderr}")
# 即使反编译失败,也继续生成报告(使用伪代码)
# 调用parse_result.py生成报告
print("\n开始生成安全分析报告...")
try:
# 构建parse_result.py命令
parse_cmd = [
sys.executable, # 使用当前Python解释器
'parse_result.py',
'-i', OUTPUT_FILE,
'-o', REPORT_FILE,
'-s', DECOMPILED_DIR
]
# 执行parse_result.py
parse_result = subprocess.run(
parse_cmd,
capture_output=True,
text=True,
cwd=os.path.dirname(os.path.abspath(__file__))
)
# 打印parse_result.py输出
print("\n报告生成输出:")
print(parse_result.stdout)
if parse_result.stderr:
print("\n报告生成错误:")
print(parse_result.stderr)
if parse_result.returncode == 0:
print(f"\n安全分析报告已生成: {REPORT_FILE}")
else:
print(f"\n报告生成失败,返回码: {parse_result.returncode}")
except Exception as e:
print(f"执行parse_result.py时出错: {str(e)}")
else:
print(f"\n分析失败,返回码: {result.returncode}")
except Exception as e:
print(f"执行命令时出错: {str(e)}")
sys.exit(1)
finally:
# 清理临时目录
shutil.rmtree(temp_platforms)