Files
magnus919_agent-skills/binary-analysis/scripts/binary_analysis/rules/capabilities.py
T

836 lines
27 KiB
Python

"""Capability mapping rules engine.
Produces functional area suggestions from backend data: imported APIs,
strings, and section patterns. Each capability entry is labeled as a
rule-derived indicator, not verified functional proof. Confidence values
replace unconditional certainty/verified fields.
Evidence items reference concrete sources:
- import: "<api_name>" — an imported API that suggests a capability
- string: "<text>" — a string that suggests a capability
- section: "<section_name>" — a section pattern that suggests a capability
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
from binary_analysis.adapters.base import BackendAdapter
from binary_analysis.domain.entities import Binary
from binary_analysis.domain.enums import Confidence
# ---------------------------------------------------------------------------
# Capability definition
# ---------------------------------------------------------------------------
@dataclass
class CapabilityRule:
"""A rule for detecting a functional capability.
Attributes:
name: Functional area name (e.g., "cryptography", "networking").
category: Broader grouping (e.g., "security", "communication").
description: Human-readable description of the capability.
import_indicators: API names that suggest this capability.
string_indicators: Substrings in strings that suggest this capability.
section_indicators: Section name patterns that suggest this capability.
"""
name: str
category: str = ""
description: str = ""
import_indicators: set[str] = field(default_factory=set)
string_indicators: list[str] = field(default_factory=list)
section_indicators: list[str] = field(default_factory=list)
def _default_capability_rules() -> list[CapabilityRule]:
"""Return the default set of capability mapping rules.
These rules are inspectable, versioned, and explainable per ADR-009.
Each rule produces rule-derived indicators, not definitive proofs.
"""
return [
CapabilityRule(
name="cryptography",
category="security",
description="Indicators of cryptographic operations (encryption, hashing, key management)",
import_indicators={
"CryptAcquireContextA",
"CryptAcquireContextW",
"CryptEncrypt",
"CryptDecrypt",
"CryptGenRandom",
"CryptHashData",
"CryptCreateHash",
"CryptDestroyHash",
"CryptExportKey",
"CryptImportKey",
"CryptDeriveKey",
"CryptStringToBinaryA",
"CryptBinaryToStringA",
"BCryptOpenAlgorithmProvider",
"BCryptGenerateSymmetricKey",
"BCryptEncrypt",
"BCryptDecrypt",
"NCryptOpenStorageProvider",
"EVP_EncryptInit",
"EVP_DecryptInit",
"EVP_CIPHER_CTX_new",
"AES_set_encrypt_key",
"AES_set_decrypt_key",
"AES_encrypt",
"AES_decrypt",
"SHA256_Init",
"SHA256_Update",
"SHA256_Final",
"MD5_Init",
"MD5_Update",
"MD5_Final",
"RSA_public_encrypt",
"RSA_private_decrypt",
"RSA_generate_key",
"BN_new",
"BN_bin2bn",
"BN_bn2bin",
"EVP_PKEY_new",
},
string_indicators=[
"AES",
"RSA",
"SHA",
"MD5",
"encrypt",
"decrypt",
"cipher",
"crypto",
"ssl",
"tls",
"certificate",
"public key",
"private key",
"BEGIN RSA",
"BEGIN CERTIFICATE",
],
section_indicators=[".crypto", ".ssl"],
),
CapabilityRule(
name="networking",
category="communication",
description="Indicators of network communication (HTTP, sockets, DNS)",
import_indicators={
"WinHttpOpen",
"WinHttpConnect",
"WinHttpOpenRequest",
"WinHttpSendRequest",
"WinHttpReceiveResponse",
"WinHttpReadData",
"WinHttpWriteData",
"WinHttpCrackUrl",
"InternetOpenA",
"InternetOpenW",
"InternetConnectA",
"InternetConnectW",
"HttpOpenRequestA",
"HttpOpenRequestW",
"HttpSendRequestA",
"HttpSendRequestW",
"URLDownloadToFileA",
"URLDownloadToFileW",
"socket",
"connect",
"send",
"recv",
"sendto",
"recvfrom",
"bind",
"listen",
"accept",
"WSAStartup",
"WSACleanup",
"WSASocketA",
"WSASocketW",
"getaddrinfo",
"freeaddrinfo",
"gethostbyname",
"inet_addr",
"inet_ntoa",
"htons",
"htonl",
"ntohs",
"ntohl",
"setsockopt",
"getsockopt",
"select",
"poll",
"epoll_create",
"epoll_ctl",
"DnsQuery_A",
"DnsQuery_W",
"getnameinfo",
"getservbyname",
},
string_indicators=[
"http://",
"https://",
"ftp://",
"ws://",
"wss://",
".com",
"www.",
"user-agent",
"content-type",
"GET ",
"POST ",
"Mozilla/",
"socket",
"port",
"proxy",
"dns",
"ip address",
],
section_indicators=[".net", ".socket"],
),
CapabilityRule(
name="file-system",
category="system",
description="Indicators of file system operations (read, write, delete, enumerate)",
import_indicators={
"CreateFileA",
"CreateFileW",
"OpenFile",
"ReadFile",
"WriteFile",
"DeleteFileA",
"DeleteFileW",
"MoveFileA",
"MoveFileW",
"CopyFileA",
"CopyFileW",
"FindFirstFileA",
"FindFirstFileW",
"FindNextFileA",
"FindNextFileW",
"FindClose",
"GetFileAttributesA",
"GetFileAttributesW",
"SetFileAttributesA",
"SetFileAttributesW",
"GetFileSize",
"GetFileSizeEx",
"SetFilePointer",
"SetEndOfFile",
"CreateDirectoryA",
"CreateDirectoryW",
"RemoveDirectoryA",
"RemoveDirectoryW",
"GetTempPathA",
"GetTempPathW",
"GetTempFileNameA",
"GetTempFileNameW",
"SHGetFolderPathA",
"SHGetFolderPathW",
"SHGetKnownFolderPath",
},
string_indicators=[
"C:\\",
"/home/",
"/etc/",
"/var/",
"/tmp/",
"/usr/",
"\\Windows\\",
"\\System32\\",
"Program Files",
"ProgramData",
"AppData",
".exe",
".dll",
".sys",
".dat",
".cfg",
".ini",
".xml",
".json",
"/etc/passwd",
"/etc/shadow",
],
section_indicators=[".fs", ".fileio"],
),
CapabilityRule(
name="process-injection",
category="security",
description="Indicators of code/process injection techniques",
import_indicators={
"VirtualAlloc",
"VirtualAllocEx",
"VirtualProtect",
"VirtualProtectEx",
"WriteProcessMemory",
"CreateRemoteThread",
"NtCreateThreadEx",
"RtlCreateUserThread",
"QueueUserAPC",
"NtQueueApcThread",
"SetThreadContext",
"MapViewOfFile",
"NtMapViewOfSection",
"UnmapViewOfFile",
"OpenProcess",
"NtOpenProcess",
"ZwOpenProcess",
"ReadProcessMemory",
"NtReadVirtualMemory",
},
string_indicators=[
"inject",
"suspend",
"resume thread",
"shellcode",
"payload",
"remote thread",
],
section_indicators=[".inject"],
),
CapabilityRule(
name="persistence",
category="security",
description="Indicators of persistence mechanisms (registry, services, startup)",
import_indicators={
"RegCreateKeyExA",
"RegCreateKeyExW",
"RegSetValueExA",
"RegSetValueExW",
"RegDeleteKeyA",
"RegDeleteKeyW",
"RegOpenKeyExA",
"RegOpenKeyExW",
"RegQueryValueExA",
"RegQueryValueExW",
"RegCloseKey",
"CreateServiceA",
"CreateServiceW",
"StartServiceA",
"StartServiceW",
"OpenSCManagerA",
"OpenSCManagerW",
"ChangeServiceConfigA",
"ChangeServiceConfigW",
"DeleteService",
"ControlService",
},
string_indicators=[
"HKEY_",
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
"\\Registry\\",
"HKLM\\",
"HKCU\\",
"HKCR\\",
"HKU\\",
"HKCC\\",
"HKPD\\",
"SERVICE_",
"sc start",
"sc create",
"schtasks",
"crontab",
"systemd",
"launchd",
"startup",
"autorun",
],
section_indicators=[".persist"],
),
CapabilityRule(
name="anti-analysis",
category="security",
description="Indicators of anti-debugging, anti-VM, and analysis evasion",
import_indicators={
"IsDebuggerPresent",
"CheckRemoteDebuggerPresent",
"NtQueryInformationProcess",
"NtSetInformationThread",
"DebugActiveProcess",
"DebugActiveProcessStop",
"OutputDebugStringA",
"OutputDebugStringW",
"GetTickCount",
"GetTickCount64",
"QueryPerformanceCounter",
"RDTSC",
"NtQuerySystemInformation",
"NtQueryObject",
"FindWindowA",
"FindWindowW",
"GetForegroundWindow",
"EnumWindows",
},
string_indicators=[
"debug",
"debugger",
"ollydbg",
"ida",
"x64dbg",
"x32dbg",
"immunity",
"windbg",
"vmware",
"virtualbox",
"vbox",
"qemu",
"xen",
"hyper-v",
"sandbox",
"syser",
"procmon",
"process monitor",
"wireshark",
"frida",
],
section_indicators=[".anti", ".obfuscated"],
),
CapabilityRule(
name="process-management",
category="system",
description="Indicators of process creation, termination, and management",
import_indicators={
"CreateProcessA",
"CreateProcessW",
"CreateProcessAsUserA",
"CreateProcessAsUserW",
"TerminateProcess",
"ExitProcess",
"GetExitCodeProcess",
"OpenProcess",
"CloseHandle",
"WaitForSingleObject",
"WaitForMultipleObjects",
"GetProcessId",
"GetCurrentProcessId",
"CreateToolhelp32Snapshot",
"Process32First",
"Process32Next",
"EnumProcesses",
"NtCreateProcess",
"NtTerminateProcess",
"ZwCreateProcess",
"ZwTerminateProcess",
"ShellExecuteA",
"ShellExecuteW",
"ShellExecuteExA",
"ShellExecuteExW",
"system",
"popen",
"execve",
"execvp",
"fork",
"clone",
"posix_spawn",
},
string_indicators=[
"cmd.exe",
"powershell",
"wscript",
"cscript",
"rundll32",
"regsvr32",
"mshta",
"certutil",
"bitsadmin",
"wmic",
"msiexec",
"/bin/sh",
"/bin/bash",
],
section_indicators=[".proc"],
),
CapabilityRule(
name="memory-management",
category="system",
description="Indicators of memory allocation, protection, and manipulation",
import_indicators={
"malloc",
"calloc",
"realloc",
"free",
"memset",
"memcpy",
"memmove",
"memcmp",
"VirtualAlloc",
"VirtualFree",
"VirtualProtect",
"HeapAlloc",
"HeapFree",
"HeapCreate",
"HeapDestroy",
"LocalAlloc",
"LocalFree",
"GlobalAlloc",
"GlobalFree",
"mmap",
"munmap",
"mprotect",
"brk",
"sbrk",
},
string_indicators=["heap", "stack", "memory", "alloc", "buffer"],
section_indicators=[],
),
CapabilityRule(
name="keylogging",
category="security",
description="Indicators of keyboard/mouse input monitoring",
import_indicators={
"SetWindowsHookExA",
"SetWindowsHookExW",
"UnhookWindowsHookEx",
"CallNextHookEx",
"GetAsyncKeyState",
"GetKeyState",
"GetKeyboardState",
"GetRawInputData",
"GetRawInputBuffer",
"RegisterRawInputDevices",
"SetWinEventHook",
"UnhookWinEvent",
},
string_indicators=["keylog", "keystroke", "keyboard", "hook", "input capture"],
section_indicators=[".hook"],
),
CapabilityRule(
name="privilege-escalation",
category="security",
description="Indicators of privilege escalation and token manipulation",
import_indicators={
"OpenProcessToken",
"AdjustTokenPrivileges",
"LookupPrivilegeValueA",
"LookupPrivilegeValueW",
"DuplicateToken",
"DuplicateTokenEx",
"ImpersonateLoggedOnUser",
"RevertToSelf",
"CreateProcessAsUserA",
"CreateProcessAsUserW",
"RtlAdjustPrivilege",
"SeDebugPrivilege",
"SeTakeOwnershipPrivilege",
"AllocateAndInitializeSid",
"CheckTokenMembership",
"setuid",
"setgid",
"seteuid",
"setegid",
},
string_indicators=[
"SeDebugPrivilege",
"SeTakeOwnershipPrivilege",
"SeBackupPrivilege",
"SeRestorePrivilege",
"SeTcbPrivilege",
"SeCreateTokenPrivilege",
"sudo",
"root",
"Administrator",
"SYSTEM",
"TokenElevation",
"admin",
"privilege",
],
section_indicators=[".priv"],
),
CapabilityRule(
name="data-exfiltration",
category="security",
description="Indicators of data collection and exfiltration",
import_indicators={
"WinHttpSendRequest",
"HttpSendRequestA",
"HttpSendRequestW",
"InternetWriteFile",
"send",
"sendto",
"WriteFile",
"WriteFileEx",
"FtpPutFileA",
"FtpPutFileW",
"FtpOpenFileA",
"FtpOpenFileW",
"URLDownloadToFileA",
"URLDownloadToFileW",
},
string_indicators=[
"upload",
"exfil",
"exfiltrate",
"steal",
"collect",
"archive",
"compress",
"zip",
"tar",
"gzip",
".7z",
".rar",
"base64",
"post /",
"multipart",
"content-disposition",
],
section_indicators=[".exfil"],
),
CapabilityRule(
name="service-management",
category="system",
description="Indicators of Windows service and driver management",
import_indicators={
"OpenSCManagerA",
"OpenSCManagerW",
"CreateServiceA",
"CreateServiceW",
"StartServiceA",
"StartServiceW",
"ControlService",
"DeleteService",
"CloseServiceHandle",
"ChangeServiceConfigA",
"ChangeServiceConfigW",
"QueryServiceStatus",
"QueryServiceConfigA",
"QueryServiceConfigW",
},
string_indicators=[
"sc.exe",
"net start",
"net stop",
"svchost",
"services.exe",
"\\.\\",
"\\Device\\",
"DRIVER_",
".sys",
"driver",
"kernel",
],
section_indicators=[".driver", ".service"],
),
CapabilityRule(
name="screenshot-capture",
category="surveillance",
description="Indicators of screen capture and desktop monitoring",
import_indicators={
"GetDC",
"GetWindowDC",
"CreateCompatibleDC",
"CreateCompatibleBitmap",
"BitBlt",
"StretchBlt",
"GetDIBits",
"SelectObject",
"DeleteDC",
"ReleaseDC",
"GdiplusStartup",
"GdipCreateBitmapFromHBITMAP",
"GdipSaveImageToStream",
},
string_indicators=["screenshot", "screen", "capture", "desktop", "gdi", "bitmap"],
section_indicators=[".capture"],
),
CapabilityRule(
name="audio-capture",
category="surveillance",
description="Indicators of audio/microphone capture",
import_indicators={
"waveInOpen",
"waveInPrepareHeader",
"waveInAddBuffer",
"waveInStart",
"waveInStop",
"waveInReset",
"waveInClose",
"waveInGetNumDevs",
"waveInGetDevCapsA",
"waveInGetDevCapsW",
"midiInOpen",
"midiInStart",
"DirectSoundCaptureCreate",
"DirectSoundCaptureEnumerateA",
"DirectSoundCaptureEnumerateW",
},
string_indicators=["microphone", "audio", "record", "wave", "pcm", "sound", "listen"],
section_indicators=[".audio"],
),
CapabilityRule(
name="clipboard-access",
category="surveillance",
description="Indicators of clipboard monitoring and manipulation",
import_indicators={
"OpenClipboard",
"CloseClipboard",
"GetClipboardData",
"SetClipboardData",
"EmptyClipboard",
"IsClipboardFormatAvailable",
"EnumClipboardFormats",
"RegisterClipboardFormatA",
"RegisterClipboardFormatW",
"GetClipboardSequenceNumber",
"AddClipboardFormatListener",
"RemoveClipboardFormatListener",
},
string_indicators=["clipboard", "paste", "copy", "cut"],
section_indicators=[".clipboard"],
),
]
# ---------------------------------------------------------------------------
# Capability map result
# ---------------------------------------------------------------------------
@dataclass
class CapabilityResult:
"""A single capability suggestion.
Attributes:
name: Functional area name (e.g., "cryptography", "networking").
confidence: Confidence level from the Confidence enum (never unconditional certainty).
evidence: List of concrete evidence items, each referencing a source
(e.g., import: "CreateFileW", string: "/etc/passwd", section: ".text").
"""
name: str
confidence: Confidence
evidence: list[dict[str, Any]]
# ---------------------------------------------------------------------------
# Capability map engine
# ---------------------------------------------------------------------------
class CapabilityMapEngine:
"""Evaluates capability mapping rules against backend data.
Scans the binary's imports, strings, and sections for patterns
matching known functional capability rules. Each result is a
rule-derived indicator, not verified functional proof.
Evidence items reference concrete sources (imported APIs, strings,
section names/patterns). Confidence values are used rather than
unconditional certainty/verified fields.
"""
def __init__(self, adapter: BackendAdapter, binary: Binary) -> None:
self._adapter = adapter
self._binary = binary
self._rules: list[CapabilityRule] = []
def run(self, limit: int = 100) -> tuple[list[CapabilityResult], int]:
"""Evaluate all capability rules against binary data.
Args:
limit: Maximum number of capability results to return.
Returns:
Tuple of (capabilities, total_capabilities) where capabilities is the
list of CapabilityResult entries (bounded by limit) and
total_capabilities is the original total count before slicing
(used for accurate truncation warnings).
"""
self._load_rules()
# Collect backend data
try:
imports = self._adapter.get_imports(self._binary)
except Exception:
imports = []
try:
strings = self._adapter.get_strings(self._binary)
except Exception:
strings = []
try:
sections = self._adapter.get_sections(self._binary)
except Exception:
sections = []
# Build lookup sets
imported_symbols: set[str] = {imp.symbol for imp in imports}
string_texts: list[str] = [s.text for s in strings]
section_names: set[str] = {s.name for s in sections}
results: list[CapabilityResult] = []
for rule in self._rules:
evidence: list[dict[str, Any]] = []
# Check import indicators
for api in sorted(rule.import_indicators):
if api in imported_symbols:
evidence.append({"import": api})
# Check string indicators
for pattern in rule.string_indicators:
pattern_lower = pattern.lower()
for text in string_texts:
if pattern_lower in text.lower():
evidence.append({"string": text})
break # one match per pattern is enough
# Check section indicators
for section_pattern in rule.section_indicators:
for section_name in section_names:
if section_pattern.lower() in section_name.lower():
evidence.append({"section": section_name})
break
if not evidence:
continue
# Compute confidence based on evidence diversity and count
evidence_count = len(evidence)
import_count = sum(1 for e in evidence if "import" in e)
string_count = sum(1 for e in evidence if "string" in e)
section_count = sum(1 for e in evidence if "section" in e)
# Diverse evidence across sources = higher confidence
sources_used = bool(import_count) + bool(string_count) + bool(section_count)
if evidence_count >= 10 and sources_used >= 2:
confidence = Confidence.HIGH
elif evidence_count >= 5:
confidence = Confidence.MEDIUM
elif evidence_count >= 1:
confidence = Confidence.LOW
else:
confidence = Confidence.UNKNOWN
results.append(
CapabilityResult(
name=rule.name,
confidence=confidence,
evidence=evidence[:50], # Cap evidence to keep output bounded
)
)
total_capabilities = len(results)
return results[:limit], total_capabilities
def _load_rules(self) -> None:
"""Load all capability rule definitions."""
self._rules = _default_capability_rules()
@property
def total_rules(self) -> int:
"""Total number of capability rules."""
if not self._rules:
self._load_rules()
return len(self._rules)