--- name: static-analysis description: > Analyze suspicious binaries without execution to extract structural information, strings, imports, exports, section entropy, packer signatures, embedded resources, and compiler artifacts. Use after initial triage confirms a binary warrants deeper investigation. Supports PE (Windows), ELF (Linux), and Mach-O (macOS) formats in both offline and online modes. --- # Static Analysis Examine a suspicious binary's structure, code, and data without executing it. Extract actionable intelligence from headers, strings, imports, resources, and entropy measurements to understand capabilities and determine if dynamic analysis or reverse engineering is needed. ## Prerequisites - **Linux**: `strings`, `readelf`, `objdump`, `file`, `binwalk` (optional) - **Windows**: PEStudio, CFF Explorer, or Python tools - **Python**: `pefile`, `pyelftools`, `yara-python` (optional), `capstone` (optional) - Completed initial triage (file type confirmed, hashes computed) ## Step-by-Step Instructions ### Step 1: Extract Strings (ASCII and Unicode) Strings reveal embedded URLs, IP addresses, file paths, registry keys, error messages, and API names that indicate the binary's functionality. **Using native tools:** ```bash # ASCII strings (minimum 4 characters) strings -a suspicious_file > strings_ascii.txt # Unicode strings (UTF-16LE, common in Windows malware) strings -el suspicious_file > strings_unicode.txt # Combined with line numbers for reference strings -a -t x suspicious_file > strings_with_offsets.txt ``` **Using the dedicated extraction script:** ```bash python3 scripts/extract_strings.py --file suspicious_file --output strings_report.json ``` This script categorizes findings into IPs, URLs, emails, file paths, registry keys, and suspicious API names. See `references/common-imports.md` for a list of suspicious Windows API imports. **Key patterns to look for:** - URLs and IP addresses (C2 servers, download locations) - File paths (dropped files, targeted data) - Registry keys (persistence mechanisms) - Encryption-related strings (ransomware indicators) - Debug strings, error messages, campaign identifiers - Base64-encoded blocks (embedded payloads) ### Step 2: Parse PE/ELF Headers Headers reveal compilation details, target architecture, and structural anomalies. **For Windows PE files:** ```bash python3 scripts/static_analyzer.py --file suspicious.exe --headers ``` **Manual PE inspection:** ```python import pefile pe = pefile.PE("suspicious.exe") print(f"Machine: {hex(pe.FILE_HEADER.Machine)}") print(f"Timestamp: {pe.FILE_HEADER.TimeDateStamp}") print(f"Entry Point: {hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)}") print(f"Subsystem: {pe.OPTIONAL_HEADER.Subsystem}") print(f"DLL: {bool(pe.FILE_HEADER.Characteristics & 0x2000)}") ``` **For ELF files:** ```bash readelf -h suspicious_elf # File header readelf -l suspicious_elf # Program headers readelf -S suspicious_elf # Section headers python3 scripts/static_analyzer.py --file suspicious_elf --headers ``` **Header anomalies to check:** - Compilation timestamp in the future or very old (1970, 2000) - Entry point outside the code section - Mismatched architecture claims - Unusual subsystem values ### Step 3: Analyze Import and Export Tables Imports reveal what OS capabilities the binary uses. Exports indicate DLL functionality. **PE imports:** ```bash python3 scripts/static_analyzer.py --file suspicious.exe --imports ``` **ELF dynamic symbols:** ```bash readelf --dyn-syms suspicious_elf ``` Refer to `references/common-imports.md` for suspicious imports grouped by capability category. Key categories: | Category | Example APIs | |----------|-------------| | Process injection | `CreateRemoteThread`, `VirtualAllocEx`, `WriteProcessMemory` | | File operations | `CreateFile`, `WriteFile`, `DeleteFile`, `MoveFile` | | Network | `InternetOpen`, `HttpSendRequest`, `WSAStartup`, `connect` | | Registry | `RegSetValueEx`, `RegCreateKeyEx` | | Crypto | `CryptEncrypt`, `CryptDecrypt`, `BCryptEncrypt` | | Anti-debug | `IsDebuggerPresent`, `CheckRemoteDebuggerPresent`, `NtQueryInformationProcess` | | Privilege | `AdjustTokenPrivileges`, `OpenProcessToken` | ### Step 4: Calculate Section Entropy High entropy (> 7.0 on a 0-8 scale) indicates compressed, encrypted, or packed data. Normal code sections have entropy around 5.5-6.5. ```bash python3 scripts/static_analyzer.py --file suspicious.exe --entropy ``` **Interpretation guide:** | Entropy Range | Likely Content | |--------------|----------------| | 0.0 - 1.0 | Sparse/empty data | | 1.0 - 3.5 | Plain text, resources | | 3.5 - 5.0 | Code with data | | 5.0 - 6.5 | Compiled code (normal) | | 6.5 - 7.5 | Compressed data or dense code | | 7.5 - 8.0 | Encrypted or packed data | **Red flags:** - `.text` section with entropy > 7.0 (likely packed) - All sections with high entropy (entire binary packed) - Single section containing everything (merged by packer) - Section named `.rsrc` with very high entropy (encrypted resources) ### Step 5: Identify Packers and Protectors Packed binaries require unpacking before meaningful analysis. ```bash python3 scripts/static_analyzer.py --file suspicious.exe --packer-detect ``` **Manual checks:** ```bash # Check for known packer section names strings suspicious.exe | grep -iE "UPX|ASPack|Themida|VMProtect|Enigma|MPRESS|PECompact" # Check with YARA packer rules (if available) yara packer_rules.yar suspicious.exe # Check import count (packed binaries have very few imports) python3 -c " import pefile pe = pefile.PE('suspicious.exe') imports = sum(len(e.imports) for e in pe.DIRECTORY_ENTRY_IMPORT) if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT') else 0 print(f'Total imports: {imports}') if imports < 10: print('WARNING: Very few imports - likely packed') " ``` **Common packer indicators:** - Very few imports (< 10), often just `LoadLibrary`/`GetProcAddress` - High entropy across all sections - Non-standard section names - Small code section with large data section - Known packer strings in overlay or sections ### Step 6: Extract Embedded Resources Resources may contain embedded executables, configuration data, scripts, or encrypted payloads. **PE resources:** ```bash python3 scripts/static_analyzer.py --file suspicious.exe --resources ``` **Manual extraction:** ```python import pefile pe = pefile.PE("suspicious.exe") for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries: resource_type = pefile.RESOURCE_TYPE.get(entry.id, f"Unknown({entry.id})") print(f"Type: {resource_type}") for dir_entry in entry.directory.entries: for res in dir_entry.directory.entries: data = pe.get_data(res.data.struct.OffsetToData, res.data.struct.Size) print(f" Size: {res.data.struct.Size}, First bytes: {data[:16].hex()}") ``` **Using binwalk for embedded files:** ```bash binwalk suspicious_file binwalk --extract suspicious_file ``` ### Step 7: Check Digital Signatures ```bash # PE signature verification (Windows) python3 scripts/static_analyzer.py --file suspicious.exe --signature # Linux: check with osslsigncode osslsigncode verify suspicious.exe ``` **Signature analysis:** - Valid signature from known publisher: likely legitimate or stolen cert - Invalid/expired signature: suspicious - Self-signed: suspicious - No signature on software claiming to be from a major vendor: suspicious - Check if the signing certificate has been revoked ### Step 8: Identify Compiler and Linker Compiler artifacts help determine the development environment and language. ```bash python3 scripts/static_analyzer.py --file suspicious.exe --compiler ``` **Common indicators:** | Artifact | Language/Compiler | |----------|------------------| | `Rich` header with specific prodIDs | MSVC (Visual Studio) | | `.rdata` with `_RTTI_` symbols | C++ (MSVC) | | `_CorExeMain` import | .NET (C#/VB.NET) | | Section `.text` named `CODE` | Delphi/Borland | | Import of `GetModuleHandle` + `Py` strings | Python (py2exe/PyInstaller) | | `__Go_` or `runtime.` symbols | Go (Golang) | | Rust-style mangled symbols | Rust | | `nim` in strings or symbols | Nim | | `AutoIt` strings | AutoIt compiled script | ### Full Analysis Run the complete static analysis pipeline: ```bash python3 scripts/static_analyzer.py --file suspicious_file --output report.json ``` ## Output Format ```json { "file": "suspicious.exe", "format": "PE32", "headers": { }, "sections": [ {"name": ".text", "virtual_size": 65536, "raw_size": 65536, "entropy": 6.2, "flags": "rx"} ], "imports": { }, "exports": [], "resources": [], "strings_summary": { "total_ascii": 1234, "total_unicode": 567, "urls": [], "ips": [], "suspicious_apis": [] }, "packer_detection": {"packed": false, "indicators": []}, "signature": {"signed": false}, "compiler": {"detected": "MSVC"}, "entropy_overall": 5.8, "anomalies": [] } ``` ## Tips - Always examine strings before diving into disassembly - they provide the fastest insight - Compare import hash (imphash) against known malware families for quick classification - Use YARA rules to match against known patterns before manual analysis - If the binary is packed, attempt automatic unpacking (UPX: `upx -d`) before proceeding - For .NET binaries, use dnSpy or ILSpy for direct decompilation instead of disassembly - For Go binaries, use `go_parser` or `GoReSym` for symbol recovery - Document all findings systematically - static analysis results feed into dynamic and RE phases