mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-19 14:09:40 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,103 @@
|
||||
# API Reference: Process Hollowing Detection
|
||||
|
||||
## MITRE ATT&CK Mapping
|
||||
- **Technique**: T1055.012 — Process Hollowing
|
||||
- **Tactic**: Defense Evasion, Privilege Escalation
|
||||
|
||||
## Windows API Functions Used in Hollowing
|
||||
|
||||
### CreateProcessA/W (kernel32.dll)
|
||||
```c
|
||||
BOOL CreateProcessW(
|
||||
LPCWSTR lpApplicationName,
|
||||
LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags, // CREATE_SUSPENDED = 0x4
|
||||
LPVOID lpEnvironment,
|
||||
LPCWSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation
|
||||
);
|
||||
```
|
||||
|
||||
### NtUnmapViewOfSection (ntdll.dll)
|
||||
```c
|
||||
NTSTATUS NtUnmapViewOfSection(
|
||||
HANDLE ProcessHandle,
|
||||
PVOID BaseAddress
|
||||
);
|
||||
```
|
||||
|
||||
### VirtualAllocEx (kernel32.dll)
|
||||
```c
|
||||
LPVOID VirtualAllocEx(
|
||||
HANDLE hProcess,
|
||||
LPVOID lpAddress,
|
||||
SIZE_T dwSize,
|
||||
DWORD flAllocationType,
|
||||
DWORD flProtect // PAGE_EXECUTE_READWRITE = 0x40
|
||||
);
|
||||
```
|
||||
|
||||
### WriteProcessMemory (kernel32.dll)
|
||||
```c
|
||||
BOOL WriteProcessMemory(
|
||||
HANDLE hProcess,
|
||||
LPVOID lpBaseAddress,
|
||||
LPCVOID lpBuffer,
|
||||
SIZE_T nSize,
|
||||
SIZE_T *lpNumberOfBytesWritten
|
||||
);
|
||||
```
|
||||
|
||||
### ResumeThread (kernel32.dll)
|
||||
```c
|
||||
DWORD ResumeThread(HANDLE hThread);
|
||||
```
|
||||
|
||||
## Detection via Linux /proc Filesystem
|
||||
|
||||
### /proc/[pid]/exe
|
||||
Symlink to the actual executable. If deleted or replaced, shows `(deleted)`.
|
||||
|
||||
### /proc/[pid]/maps
|
||||
```
|
||||
address perms offset dev inode pathname
|
||||
00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/target
|
||||
```
|
||||
|
||||
### /proc/[pid]/status
|
||||
```
|
||||
Name: svchost
|
||||
Pid: 1234
|
||||
PPid: 567
|
||||
VmExe: 512 kB
|
||||
```
|
||||
|
||||
## Sysmon Event IDs for Detection
|
||||
|
||||
| Event ID | Description |
|
||||
|----------|-------------|
|
||||
| 1 | Process Create (check CREATE_SUSPENDED flag) |
|
||||
| 8 | CreateRemoteThread |
|
||||
| 10 | ProcessAccess (PROCESS_VM_WRITE + PROCESS_VM_OPERATION) |
|
||||
| 25 | ProcessTampering (image replaced) |
|
||||
|
||||
## PowerShell Detection Queries
|
||||
|
||||
### Get process with module mismatch
|
||||
```powershell
|
||||
Get-Process | Where-Object {
|
||||
$_.Path -and $_.MainModule.FileName -and
|
||||
($_.Path -ne $_.MainModule.FileName)
|
||||
}
|
||||
```
|
||||
|
||||
### Check for suspended child processes
|
||||
```powershell
|
||||
Get-CimInstance Win32_Process | Where-Object {
|
||||
$_.ExecutionState -eq 'Suspended'
|
||||
} | Select-Object ProcessId, Name, ParentProcessId, CommandLine
|
||||
```
|
||||
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for detecting process hollowing (T1055.012) in running processes."""
|
||||
|
||||
import argparse
|
||||
import ctypes
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def get_running_processes():
|
||||
"""Enumerate running processes via tasklist or ps."""
|
||||
procs = []
|
||||
if sys.platform == "win32":
|
||||
out = subprocess.check_output(
|
||||
["tasklist", "/FO", "CSV", "/NH", "/V"], text=True, errors="replace"
|
||||
)
|
||||
for line in out.strip().splitlines():
|
||||
parts = line.strip('"').split('","')
|
||||
if len(parts) >= 2:
|
||||
procs.append({"name": parts[0], "pid": int(parts[1])})
|
||||
else:
|
||||
out = subprocess.check_output(
|
||||
["ps", "-eo", "pid,ppid,comm,args", "--no-headers"], text=True
|
||||
)
|
||||
for line in out.strip().splitlines():
|
||||
fields = line.split(None, 3)
|
||||
if len(fields) >= 3:
|
||||
procs.append({
|
||||
"pid": int(fields[0]),
|
||||
"ppid": int(fields[1]),
|
||||
"name": fields[2],
|
||||
"cmdline": fields[3] if len(fields) > 3 else "",
|
||||
})
|
||||
return procs
|
||||
|
||||
|
||||
def check_memory_discrepancy_linux(pid):
|
||||
"""Check for signs of hollowing: discrepancy between mapped exe and memory."""
|
||||
indicators = []
|
||||
exe_link = f"/proc/{pid}/exe"
|
||||
maps_file = f"/proc/{pid}/maps"
|
||||
try:
|
||||
real_exe = os.readlink(exe_link)
|
||||
if " (deleted)" in real_exe:
|
||||
indicators.append(f"exe link points to deleted binary: {real_exe}")
|
||||
except (OSError, PermissionError):
|
||||
return indicators
|
||||
|
||||
try:
|
||||
with open(maps_file, "r") as f:
|
||||
maps = f.read()
|
||||
exe_base = os.path.basename(real_exe)
|
||||
first_exec_region = None
|
||||
for line in maps.splitlines():
|
||||
if "r-xp" in line:
|
||||
first_exec_region = line
|
||||
break
|
||||
if first_exec_region and exe_base not in first_exec_region:
|
||||
indicators.append(
|
||||
f"Executable memory region does not reference expected binary: {first_exec_region}"
|
||||
)
|
||||
except (OSError, PermissionError):
|
||||
pass
|
||||
return indicators
|
||||
|
||||
|
||||
def check_hollowing_windows(pid):
|
||||
"""Use Windows API to detect hollowing via PEB image base vs section."""
|
||||
indicators = []
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
["powershell", "-NoProfile", "-Command",
|
||||
f"Get-Process -Id {pid} | Select-Object Id,ProcessName,Path,"
|
||||
"MainModule,StartTime | ConvertTo-Json"],
|
||||
text=True, errors="replace", timeout=10
|
||||
)
|
||||
data = json.loads(result)
|
||||
if data.get("Path") and data.get("MainModule"):
|
||||
mod_path = data["MainModule"].get("FileName", "")
|
||||
if mod_path and data["Path"].lower() != mod_path.lower():
|
||||
indicators.append(
|
||||
f"Process path mismatch: Path={data['Path']} MainModule={mod_path}"
|
||||
)
|
||||
except (subprocess.SubprocessError, json.JSONDecodeError, KeyError):
|
||||
pass
|
||||
return indicators
|
||||
|
||||
|
||||
def analyze_process(pid):
|
||||
"""Analyze a single process for hollowing indicators."""
|
||||
if sys.platform == "win32":
|
||||
return check_hollowing_windows(pid)
|
||||
return check_memory_discrepancy_linux(pid)
|
||||
|
||||
|
||||
def scan_all(target_pids=None):
|
||||
"""Scan processes for process hollowing indicators."""
|
||||
results = []
|
||||
procs = get_running_processes()
|
||||
targets = procs if not target_pids else [p for p in procs if p["pid"] in target_pids]
|
||||
|
||||
for proc in targets:
|
||||
pid = proc["pid"]
|
||||
indicators = analyze_process(pid)
|
||||
entry = {
|
||||
"pid": pid,
|
||||
"name": proc.get("name", "unknown"),
|
||||
"hollowing_indicators": indicators,
|
||||
"suspicious": len(indicators) > 0,
|
||||
}
|
||||
results.append(entry)
|
||||
return results
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Detect process hollowing (T1055.012) in running processes"
|
||||
)
|
||||
parser.add_argument("--pid", type=int, nargs="*", help="Specific PIDs to scan")
|
||||
parser.add_argument("--output", "-o", help="Output JSON file path")
|
||||
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
|
||||
args = parser.parse_args()
|
||||
|
||||
print("[*] Process Hollowing Detection Agent")
|
||||
print(f"[*] Platform: {sys.platform}")
|
||||
print(f"[*] Scan started: {datetime.now(timezone.utc).isoformat()}")
|
||||
|
||||
results = scan_all(target_pids=args.pid)
|
||||
suspicious = [r for r in results if r["suspicious"]]
|
||||
|
||||
report = {
|
||||
"scan_time": datetime.now(timezone.utc).isoformat(),
|
||||
"platform": sys.platform,
|
||||
"total_scanned": len(results),
|
||||
"suspicious_count": len(suspicious),
|
||||
"suspicious_processes": suspicious,
|
||||
}
|
||||
|
||||
if args.verbose:
|
||||
for r in results:
|
||||
status = "SUSPICIOUS" if r["suspicious"] else "OK"
|
||||
print(f" [{status}] PID {r['pid']} ({r['name']})")
|
||||
for ind in r.get("hollowing_indicators", []):
|
||||
print(f" -> {ind}")
|
||||
|
||||
print(f"\n[*] Scanned {len(results)} processes, {len(suspicious)} suspicious")
|
||||
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
print(f"[*] Report saved to {args.output}")
|
||||
else:
|
||||
print(json.dumps(report, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user