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
|
#
# 快速Python筛选脚本
# 将匹配YARA规则的文件复制到另一个目录
#
import yara
import os
import shutil
import zipfile
import io
# YARA规则
yara_rule = """
rule case_xxxxxx_search_1
{
strings:
$s1 = "string1" nocase wide ascii
$s2 = "string2" nocase wide ascii
$s3 = "string3" nocase wide ascii
$s4 = "string4" nocase wide ascii
$s5 = "string5" nocase wide ascii
condition:
any of ($s*)
}
"""
source_dir = "Triage"
dest_dir = "MatchedFiles"
os.makedirs(dest_dir, exist_ok=True)
rules = yara.compile(source=yara_rule)
def is_zip_file(filepath):
"""
检查ZIP压缩包魔数。
"""
try:
with open(filepath, "rb") as f:
sig = f.read(4)
return sig in (b"PK\x03\x04", b"PK\x05\x06", b"PK\x07\x08")
except Exception:
return False
def safe_extract_path(member_name):
"""
返回目标文件夹内的安全相对路径(防止路径中出现..)。
"""
return os.path.normpath(member_name).replace("..", "_")
def scan_file(filepath, file_bytes=None, inside_zip=False, zip_name=None, member_name=None):
"""
使用YARA扫描文件。
"""
try:
if file_bytes is not None:
matches = rules.match(data=file_bytes)
else:
matches = rules.match(filepath)
if matches:
if inside_zip:
print("[MATCH] {member_name} (inside {zip_name})")
rel_path = os.path.relpath(zip_name, source_dir)
filepath = os.path.join(source_dir, rel_path)
dest_path = os.path.join(dest_dir, rel_path)
else:
print("[MATCH] {filepath}")
rel_path = os.path.relpath(filepath, source_dir)
dest_path = os.path.join(dest_dir, rel_path)
# 保存副本
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
shutil.copy2(filepath, dest_path)
except Exception as e:
print(e)
pass
# 主程序
for root, dirs, files in os.walk(source_dir):
for name in files:
filepath = os.path.join(root, name)
if is_zip_file(filepath):
try:
with zipfile.ZipFile(filepath, 'r') as z:
for member in z.namelist():
if member.endswith("/"): # 跳过目录
continue
try:
file_data = z.read(member)
scan_file(member, file_bytes=file_data, inside_zip=True, zip_name=filepath, member_name=member)
except Exception:
pass
except zipfile.BadZipFile:
pass
else:
scan_file(filepath)
|