mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 05:34:55 +03:00
c21af3347e
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
188 lines
6.2 KiB
Python
188 lines
6.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Windows ShellBag artifact analysis agent.
|
|
|
|
Parses ShellBag registry artifacts to reconstruct folder access history,
|
|
directory browsing patterns, and evidence of accessed network shares.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import struct
|
|
import hashlib
|
|
import datetime
|
|
from collections import defaultdict
|
|
|
|
try:
|
|
import Registry
|
|
HAS_REGISTRY = True
|
|
except ImportError:
|
|
try:
|
|
from regipy.registry import RegistryHive
|
|
HAS_REGIPY = True
|
|
HAS_REGISTRY = False
|
|
except ImportError:
|
|
HAS_REGISTRY = False
|
|
HAS_REGIPY = False
|
|
|
|
|
|
SHELLBAG_PATHS = {
|
|
'ntuser': [
|
|
'Software\Microsoft\Windows\Shell\BagMRU',
|
|
'Software\Microsoft\Windows\Shell\Bags',
|
|
'Software\Microsoft\Windows\ShellNoRoam\BagMRU',
|
|
'Software\Microsoft\Windows\ShellNoRoam\Bags',
|
|
],
|
|
'usrclass': [
|
|
'Local Settings\Software\Microsoft\Windows\Shell\BagMRU',
|
|
'Local Settings\Software\Microsoft\Windows\Shell\Bags',
|
|
],
|
|
}
|
|
|
|
|
|
def filetime_to_datetime(filetime):
|
|
if not filetime or filetime == 0:
|
|
return None
|
|
try:
|
|
epoch = datetime.datetime(1601, 1, 1)
|
|
delta = datetime.timedelta(microseconds=filetime // 10)
|
|
return (epoch + delta).isoformat() + 'Z'
|
|
except (OverflowError, OSError):
|
|
return None
|
|
|
|
|
|
def parse_shell_item(data):
|
|
if len(data) < 2:
|
|
return None
|
|
item_size = struct.unpack_from('<H', data, 0)[0]
|
|
if item_size < 2 or item_size > len(data):
|
|
return None
|
|
item_type = data[2] if len(data) > 2 else 0
|
|
result = {'size': item_size, 'type': hex(item_type)}
|
|
|
|
if item_type == 0x1F:
|
|
result['class'] = 'Root Folder (GUID)'
|
|
if len(data) >= 18:
|
|
guid = data[4:20].hex()
|
|
result['guid'] = guid
|
|
elif item_type in (0x31, 0x32, 0x35):
|
|
result['class'] = 'File Entry'
|
|
if len(data) > 14:
|
|
file_size = struct.unpack_from('<I', data, 4)[0]
|
|
result['file_size'] = file_size
|
|
name_offset = 14
|
|
if name_offset < len(data):
|
|
name_end = data.find(b' |