CG
SkillsPerforming Static Malware Analysis with PE Studio
Start Free
Back to Skills Library
Malware Analysis๐ŸŸก Intermediate

Performing Static Malware Analysis with PE Studio

Performs static analysis of Windows PE (Portable Executable) malware samples using PEStudio to examine file headers, imports, strings, resources, and indicators without executing the binary.

7 min read9 code examples

Prerequisites

  • PEStudio (free edition from https://www.winitor.com/) installed on an isolated analysis workstation
  • Python 3.8+ with `pefile` library for scripted PE analysis (`pip install pefile`)
  • CFF Explorer or PE-bear as supplementary PE analysis tools
  • Access to VirusTotal API for hash lookups and community intelligence
  • Isolated analysis VM with no network connectivity to production systems
  • FLOSS (FireEye Labs Obfuscated String Solver) for extracting obfuscated strings

Performing Static Malware Analysis with PEStudio

When to Use

  • A suspicious Windows executable has been collected and needs initial triage before sandbox execution
  • You need to identify imports, strings, and resources that reveal malware functionality without running the sample
  • Determining whether a PE file is packed, obfuscated, or contains anti-analysis techniques
  • Extracting indicators of compromise (hashes, URLs, IPs, registry keys) embedded in a binary
  • Classifying a sample's capabilities based on its import table and section characteristics

Do not use for dynamic behavioral analysis requiring execution; use a sandbox (Cuckoo, ANY.RUN) for runtime behavior observation.

Prerequisites

  • PEStudio (free edition from https://www.winitor.com/) installed on an isolated analysis workstation
  • Python 3.8+ with pefile library for scripted PE analysis (pip install pefile)
  • CFF Explorer or PE-bear as supplementary PE analysis tools
  • Access to VirusTotal API for hash lookups and community intelligence
  • Isolated analysis VM with no network connectivity to production systems
  • FLOSS (FireEye Labs Obfuscated String Solver) for extracting obfuscated strings

Workflow

Step 1: Compute File Hashes and Verify Sample Integrity

Generate cryptographic hashes for identification and intelligence lookup:

# Generate MD5, SHA-1, and SHA-256 hashes
md5sum suspect.exe
sha1sum suspect.exe
sha256sum suspect.exe

# Check hash against VirusTotal
curl -s -X GET "https://www.virustotal.com/api/v3/files/$(sha256sum suspect.exe | cut -d' ' -f1)" \
  -H "x-apikey: $VT_API_KEY" | jq '.data.attributes.last_analysis_stats'

# Get file type with magic bytes verification
file suspect.exe

Step 2: Examine PE Headers and Section Table

Open the sample in PEStudio and inspect structural properties:

PEStudio Analysis Points:
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
File Header:       Compilation timestamp, target architecture (x86/x64)
Optional Header:   Entry point address, image base, subsystem (GUI/console)
Section Table:     Section names, virtual/raw sizes, entropy values
                   High entropy (>7.0) in .text/.rsrc suggests packing
Signatures:        Authenticode signature presence and validity

Scripted PE Header Analysis with pefile:

import pefile
import hashlib
import math

pe = pefile.PE("suspect.exe")

# Compilation timestamp
import datetime
timestamp = pe.FILE_HEADER.TimeDateStamp
compile_time = datetime.datetime.utcfromtimestamp(timestamp)
print(f"Compile Time: {compile_time} UTC")

# Section analysis with entropy calculation
for section in pe.sections:
    name = section.Name.decode().rstrip('\x00')
    entropy = section.get_entropy()
    raw_size = section.SizeOfRawData
    virtual_size = section.Misc_VirtualSize
    ratio = virtual_size / raw_size if raw_size > 0 else 0
    print(f"Section: {name:8s} Entropy: {entropy:.2f} Raw: {raw_size:>10} Virtual: {virtual_size:>10} Ratio: {ratio:.2f}")
    if entropy > 7.0:
        print(f"  [!] HIGH ENTROPY - likely packed or encrypted")
    if ratio > 10:
        print(f"  [!] HIGH V/R RATIO - unpacking stub likely present")

Step 3: Analyze Import Address Table (IAT)

Identify suspicious API imports that indicate malware capabilities:

# Extract and categorize imports
suspicious_imports = {
    "Process Injection": ["VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread", "NtCreateThreadEx"],
    "Keylogging": ["GetAsyncKeyState", "SetWindowsHookExA", "GetKeyState"],
    "Persistence": ["RegSetValueExA", "CreateServiceA", "SchTasksCreate"],
    "Evasion": ["IsDebuggerPresent", "CheckRemoteDebuggerPresent", "NtQueryInformationProcess"],
    "Network": ["InternetOpenA", "HttpSendRequestA", "URLDownloadToFileA", "WSAStartup"],
    "File Operations": ["CreateFileA", "WriteFile", "DeleteFileA", "MoveFileA"],
    "Crypto": ["CryptEncrypt", "CryptDecrypt", "CryptAcquireContextA"],
}

for entry in pe.DIRECTORY_ENTRY_IMPORT:
    dll_name = entry.dll.decode()
    for imp in entry.imports:
        if imp.name:
            func_name = imp.name.decode()
            for category, funcs in suspicious_imports.items():
                if func_name in funcs:
                    print(f"[!] {category}: {dll_name} -> {func_name}")

Step 4: Extract and Analyze Strings

Use FLOSS for obfuscated strings and standard strings extraction:

# Standard strings extraction (ASCII and Unicode)
strings -a suspect.exe > strings_ascii.txt
strings -el suspect.exe > strings_unicode.txt

# FLOSS for decoded/deobfuscated strings
floss suspect.exe --output-json floss_output.json

# Search for network indicators in strings
grep -iE "(http|https|ftp)://" strings_ascii.txt
grep -iE "([0-9]{1,3}\.){3}[0-9]{1,3}" strings_ascii.txt
grep -iE "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" strings_ascii.txt

# Search for registry keys
grep -i "HKLM\\|HKCU\\|SOFTWARE\\|CurrentVersion\\Run" strings_ascii.txt

# Search for file paths and extensions
grep -iE "\.(exe|dll|bat|ps1|vbs|tmp)" strings_ascii.txt

Step 5: Inspect Resources and Embedded Data

Examine the PE resource section for embedded payloads or configuration:

# Extract resources from PE file
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
    for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
        if hasattr(resource_type, 'directory'):
            for resource_id in resource_type.directory.entries:
                if hasattr(resource_id, 'directory'):
                    for resource_lang in resource_id.directory.entries:
                        data = pe.get_data(resource_lang.data.struct.OffsetToData,
                                          resource_lang.data.struct.Size)
                        entropy = calculate_entropy(data)
                        print(f"Resource Type: {resource_type.id} Size: {len(data)} Entropy: {entropy:.2f}")
                        if entropy > 7.0:
                            print(f"  [!] High entropy resource - possible embedded payload")
                        # Check for PE signature in resource (embedded executable)
                        if data[:2] == b'MZ':
                            print(f"  [!] Embedded PE detected in resource")
                            with open(f"extracted_resource_{resource_type.id}.bin", "wb") as f:
                                f.write(data)

Step 6: Check for Packing and Protection

Determine if the binary is packed or protected:

# Detect packer with Detect It Easy (DIE)
diec suspect.exe

# Check with PEiD signatures (command-line version)
python3 -c "
import pefile
pe = pefile.PE('suspect.exe')
# Check for common packer section names
packer_sections = {'.upx0': 'UPX', '.aspack': 'ASPack', '.adata': 'ASPack',
                   '.nsp0': 'NsPack', '.vmprotect': 'VMProtect', '.themida': 'Themida'}
for section in pe.sections:
    name = section.Name.decode().rstrip('\x00').lower()
    if name in packer_sections:
        print(f'[!] Packer detected: {packer_sections[name]} (section: {name})')

# Check import table size (very few imports suggest packing)
import_count = sum(len(entry.imports) for entry in pe.DIRECTORY_ENTRY_IMPORT)
if import_count < 10:
    print(f'[!] Only {import_count} imports - likely packed')
"

Step 7: Generate Static Analysis Report

Compile all findings into a structured triage report:

Document the following for each analyzed sample:
- File identification (hashes, file type, size, compile timestamp)
- Packing/protection status and identified packer
- Suspicious imports categorized by capability
- Network indicators extracted from strings (IPs, domains, URLs)
- Embedded resources and their characteristics
- Overall threat assessment and recommended next steps (sandbox execution, YARA rule creation)

Key Concepts

TermDefinition
PE (Portable Executable)The file format for Windows executables (.exe, .dll, .sys) containing headers, sections, imports, and resources that define how the OS loads the binary
Import Address Table (IAT)PE structure listing external DLL functions the executable calls at runtime; reveals program capabilities and intent
Section EntropyStatistical measure of randomness in a PE section; values above 7.0 (out of 8.0) indicate compression, encryption, or packing
FLOSSFireEye Labs Obfuscated String Solver; automatically extracts and decodes obfuscated strings that standard strings misses
PackingCompression or encryption of a PE file's code section to hinder static analysis; requires runtime unpacking stub to execute
PE ResourcesData section within a PE file that can contain icons, dialogs, version info, or attacker-embedded payloads and configuration data
Compilation TimestampTimestamp in the PE header indicating when the binary was compiled; can be forged but often reveals development timeline

Tools & Systems

  • PEStudio: Free Windows tool for static analysis of PE files providing indicators, imports, strings, and resource inspection in a single interface
  • pefile (Python): Python library for parsing and analyzing PE file structures programmatically for automated analysis pipelines
  • FLOSS: FireEye tool that extracts obfuscated strings from malware using static analysis techniques including stack string decoding
  • Detect It Easy (DIE): Packer and compiler detection tool that identifies protectors, compilers, and linkers used to build PE files
  • CFF Explorer: Advanced PE editor and viewer for detailed inspection of PE headers, sections, imports, and resource directories

Common Scenarios

Scenario: Triaging a Suspicious Email Attachment

Context: SOC receives an alert on a suspicious executable attached to a phishing email. The file needs rapid triage to determine if it is malicious before committing sandbox resources.

Approach:

  1. Compute SHA-256 hash and query VirusTotal for existing detections and community comments
  2. Open in PEStudio and check the indicators tab for red/yellow flagged items
  3. Verify compile timestamp (future dates or dates from 1970 indicate timestamp manipulation)
  4. Check imports for VirtualAllocEx, CreateRemoteThread (injection), URLDownloadToFileA (downloader)
  5. Extract strings and search for C2 URLs, IP addresses, and file paths
  6. Check resources for embedded PE files or high-entropy data blobs
  7. Assess packing status; if packed, note the packer and plan for unpacking before deeper analysis

Pitfalls:

  • Trusting the PE compile timestamp without corroborating evidence (timestamps are trivially forged)
  • Concluding a file is benign because it has few suspicious imports (packed malware hides real imports)
  • Missing Unicode strings by only running ASCII string extraction
  • Not checking overlay data appended after the last PE section (common hiding spot for configuration data)

Output Format

STATIC MALWARE ANALYSIS REPORT
=================================
Sample:           suspect.exe
MD5:              d41d8cd98f00b204e9800998ecf8427e
SHA-256:          e3b0c44298fc1c149afbf4c8996fb924...
File Size:        245,760 bytes
File Type:        PE32 executable (GUI) Intel 80386
Compile Time:     2025-09-14 08:23:15 UTC

PACKING STATUS
Packer Detected:  None (native binary)
Section Entropy:  .text=6.42 .rdata=4.89 .data=3.21 .rsrc=7.81
Note:             .rsrc section entropy elevated - check resources

SUSPICIOUS IMPORTS
[INJECTION]       kernel32.dll -> VirtualAllocEx
[INJECTION]       kernel32.dll -> WriteProcessMemory
[INJECTION]       kernel32.dll -> CreateRemoteThread
[EVASION]         kernel32.dll -> IsDebuggerPresent
[NETWORK]         wininet.dll  -> InternetOpenA
[NETWORK]         wininet.dll  -> HttpSendRequestA
[PERSISTENCE]     advapi32.dll -> RegSetValueExA

EXTRACTED INDICATORS
URLs:             hxxps://update.malicious[.]com/gate.php
IPs:              185.220.101[.]42, 91.215.85[.]17
Registry Keys:    HKCU\Software\Microsoft\Windows\CurrentVersion\Run\svchost
File Paths:       C:\Users\Public\svchost.exe

EMBEDDED RESOURCES
Resource 101:     Size=98304 Entropy=7.89 [!] Embedded PE detected
Resource 102:     Size=4096  Entropy=2.14 (configuration XML)

ASSESSMENT
Threat Level:     HIGH
Classification:   Dropper with process injection capabilities
Recommended:      Execute in sandbox, extract embedded PE for separate analysis

Verification Criteria

Confirm successful execution by validating:

  • [ ] All prerequisite tools and access requirements are satisfied
  • [ ] Each workflow step completed without errors
  • [ ] Output matches expected format and contains expected data
  • [ ] No security warnings or misconfigurations detected
  • [ ] Results are documented and evidence is preserved for audit

Compliance Framework Mapping

This skill supports compliance evidence collection across multiple frameworks:

  • SOC 2: CC7.2 (Anomaly Detection), CC7.4 (Incident Response)
  • ISO 27001: A.12.2 (Malware Protection), A.16.1 (Security Incident Management)
  • NIST 800-53: SI-3 (Malicious Code Protection), IR-4 (Incident Handling)
  • NIST CSF: DE.CM (Continuous Monitoring), RS.AN (Analysis)

Claw GRC Tip: When this skill is executed by a registered agent, compliance evidence is automatically captured and mapped to the relevant controls in your active frameworks.

Deploying This Skill with Claw GRC

Agent Execution

Register this skill with your Claw GRC agent for automated execution:

# Install via CLI
npx claw-grc skills add performing-static-malware-analysis-with-pe-studio

# Or load dynamically via MCP
grc.load_skill("performing-static-malware-analysis-with-pe-studio")

Audit Trail Integration

When executed through Claw GRC, every step of this skill generates tamper-evident audit records:

  • SHA-256 chain hashing ensures no step can be modified after execution
  • Evidence artifacts (configs, scan results, logs) are automatically attached to relevant controls
  • Trust score impact โ€” successful execution increases your agent's trust score

Continuous Compliance

Schedule this skill for recurring execution to maintain continuous compliance posture. Claw GRC monitors for drift and alerts when re-execution is needed.

Use with Claw GRC Agents

This skill is fully compatible with Claw GRC's autonomous agent system. Deploy it to any registered agent via MCP, and every execution will be logged in the tamper-evident audit trail.

// Load this skill in your agent
npx claw-grc skills add performing-static-malware-analysis-with-pe-studio
// Or via MCP
grc.load_skill("performing-static-malware-analysis-with-pe-studio")

Tags

malwarestatic-analysisPE-analysisPEStudioreverse-engineering

Related Skills

Malware Analysis

Analyzing Android Malware with Apktool

3mยทintermediate
Malware Analysis

Analyzing Packed Malware with UPX Unpacker

7mยทintermediate
Malware Analysis

Analyzing Linux ELF Malware

7mยทadvanced
Malware Analysis

Analyzing Malicious PDF with peepdf

3mยทadvanced
Malware Analysis

Analyzing PDF Malware with Pdfid

7mยทadvanced
Malware Analysis

Analyzing Ransomware Encryption Mechanisms

8mยทadvanced

Skill Details

Domain
Malware Analysis
Difficulty
intermediate
Read Time
7 min
Code Examples
9

On This Page

When to UsePrerequisitesWorkflowKey ConceptsTools & SystemsCommon ScenariosOutput FormatVerification CriteriaCompliance Framework MappingDeploying This Skill with Claw GRC

Deploy This Skill

Add this skill to your Claw GRC agent and start automating.

Get Started Free โ†’