How to Scan EC2 and S3 With GuardDuty Malware Protection

December 20, 2028 · 12 min read

Security · SCS-C03 · part of The Exam Room

The situation

An estate with GuardDuty enabled across 40 accounts. Malware Protection is not currently enabled. Two recent incidents motivated the question of whether to turn it on:

  • Cryptominer on a developer instance. A dev installed an unofficial Docker image that happened to bundle XMRig. GuardDuty’s base detector caught the outbound CPU miner traffic via CryptoCurrency:EC2/BitcoinTool.B!DNS but couldn’t tell us where on the instance the miner binary lived. The responding engineer spent two hours SSH’ing around the instance’s filesystem manually.
  • Webshell on a partner-facing API instance. A known supply-chain compromise in an npm package dropped a webshell into node_modules/. No outbound connection to flag yet; the webshell was waiting for a trigger. GuardDuty’s base detector had nothing.

The security team wants:

  • On-demand scanning of suspicious instances (linked to GuardDuty findings).
  • Scheduled scanning of production instances regardless of findings.
  • Scanning of new S3 uploads for malware.
  • A finding format that integrates with the existing Security Hub triage pipeline.
  • Clarity on what the scanner can’t see (running-process memory, encrypted volumes without keys, etc.).

GuardDuty’s Malware Protection tiers address most of these, with known blind spots.

What actually matters

A malware scanner on AWS is solving a different problem than a CVE scanner or a network detector. Inspector asks “is any installed package known-vulnerable?” GuardDuty’s base detector asks “is the network behaviour consistent with a known attack?” A malware scanner asks “is there a file on disk that matches a known-malicious signature, or looks like a known-malicious pattern?”

That’s a filesystem-walking problem. Doing it on a running instance means either installing an agent (classical endpoint AV), which creates operational burden and possibly impacts workload performance, or doing it out-of-band by taking a snapshot of the instance’s disks and scanning the snapshot from somewhere else.

The snapshot approach has real advantages. It’s agentless (no install, no performance impact on the scanned instance). It’s safe against an attacker trying to evade detection, because the scanner runs in an isolated environment, so rootkit-style tampering can’t affect the scan. It’s consistent: the scan sees the filesystem at a single point in time.

It also has real limitations. It can’t see process memory (encrypted in-memory malware is invisible). It needs the volume to be decryptable; if it’s encrypted with a key the scanner can’t access, the scan fails. It runs on a schedule or trigger, not continuously, so malware that lands between scans isn’t seen until the next one. It doesn’t catch fileless attacks that never touch disk.

The three workload shapes the team cares about are also different problems. Scanning attached EBS volumes on suspicious activity or on-demand is one. Scanning objects newly uploaded to buckets is another. Catching in-memory and fileless attacks in real time is a third, and it requires an agent watching syscalls, not a periodic snapshot. A complete answer probably combines more than one of these.

What we’ll filter on

  1. Workload coverage. EC2, EKS, ECS, S3, Fargate?
  2. Trigger. GuardDuty finding, schedule, on-demand, or event-driven?
  3. In-memory / fileless detection. Does it see processes or just disk?
  4. EBS-encrypted volume handling. What happens with KMS-encrypted disks?
  5. Cost shape. Per-GB scanned, per-instance, or per-object?

The malware-scanning landscape

1. GuardDuty Malware Protection for EC2. Agentless snapshot-based scan. On a triggering GuardDuty finding (types like Trojan:EC2/*, CryptoCurrency:EC2/*, Backdoor:EC2/*), GuardDuty takes an EBS snapshot, scans it in an AWS-managed account, and emits a follow-up finding if malware is detected. Also supports aws guardduty start-malware-scan for on-demand scans. Does not cover in-memory or fileless attacks. Requires EBS volumes to be unencrypted or encrypted with KMS keys that grant the AWS-managed role access.

2. GuardDuty Malware Protection for S3. Managed scanner on S3 PutObject. Configured per-bucket; scans objects on upload, tags them with a scan result (NO_THREATS_FOUND, THREATS_FOUND, UNSUPPORTED), and emits findings. Useful for buckets accepting uploads from customers or partners. Priced per GB scanned.

3. GuardDuty Runtime Monitoring. eBPF agent on EKS nodes (deployed as an add-on), on ECS tasks on Fargate (sidecar model), and on EC2 (SSM-installed agent). Watches syscalls, process trees, file operations, network connections in real time. Detects fileless malware, in-memory injection, privilege escalation. Priced per-vCPU-hour for the monitored resource.

4. Third-party EDR (CrowdStrike, SentinelOne, Microsoft Defender, Trend Micro). Agent-based endpoint detection and response. Deep signal, strong UX, cross-cloud. Agent install, licence cost, operational overhead.

5. Custom signature scanners (ClamAV, YARA). Open-source antivirus tools. Can be deployed as a sidecar, scheduled Lambda, or EC2 scanner. Cheaper per-scan; require signature management and integration work.

6. Amazon Inspector. CVE scanner, not a malware scanner. Complementary rather than competitive; Inspector tells you “this package has a known vulnerability”, and Malware Protection tells you “there’s a known-malicious file on disk.”

Side by side

Option Coverage Trigger In-memory Encryption handling Cost shape
GD Malware Protection (EC2) EC2 EBS volumes GD finding + on-demand + scheduled KMS key must grant AWS role Per-GB scanned
GD Malware Protection (S3) S3 uploads PutObject ✗ (objects at rest) SSE-S3 / KMS supported Per-GB scanned
GD Runtime Monitoring EKS, ECS-Fargate, EC2 Continuous ✓ (eBPF) N/A Per-vCPU-hour
Third-party EDR Anywhere agent runs Continuous Agent-based Per-endpoint
ClamAV / YARA DIY Anywhere you deploy Custom Custom Operational
Inspector EC2, ECR, Lambda Continuous ✗ (CVE only) N/A Per-resource

Reading the table: Malware Protection for EC2 is the agentless-disk answer; Runtime Monitoring is the in-memory answer; S3 Malware Protection is the upload-scanning answer. They coexist rather than substitute.

The snapshot scan path

Malware Protection for EC2 — automatic trigger flow EC2 instance (customer) EBS volumes attached agent-free workload continues running 1 GuardDuty base detector Trojan:EC2/BlackHoleTraffic (or similar type that triggers MP) severity routed to MP 2 EBS snapshot auto-triggered by MP fully cow, no workload impact minutes 3 Shared to scanner account AWS-owned isolated Scanner EC2 ephemeral mounts snapshot RO signature DB current 4 Filesystem walk signature-based detection finds: paths + hashes snapshot deleted post-scan 5 Malware finding emitted Execution:EC2/MaliciousFile file path, threat name, hash linked to original finding 6 Security Hub ASFF-formatted finding routed by resource tag EventBridge to on-call What the snapshot scan cannot see — Running processes (kernel memory, RAM-resident payloads, fileless malware) — Volumes encrypted with KMS keys the AWS scanner role cannot access — Instance store (ephemeral) volumes — EBS snapshots only — Malware installed after the snapshot was taken — adds latency to "is this host clean right now?" Runtime Monitoring (eBPF agent) fills the in-memory and fileless gap; the two tiers complement
Numbered steps trace a finding from base detector to scan to linked follow-up finding; the bottom panel lists the scan's blind spots.

The picks in depth

Malware Protection for EC2 with automatic triggers. Enable from the GuardDuty console or CLI. Once enabled, GuardDuty automatically triggers a malware scan when base detector findings indicate potential malware (types like Trojan:EC2/*, CryptoCurrency:EC2/*, Backdoor:EC2/*). The scan completes within ~15-45 minutes for typical volume sizes and emits follow-up findings of type Execution:EC2/MaliciousFile or similar, linked to the original finding by resource ID. On-demand scans via aws guardduty start-malware-scan for investigation of specific instances.

KMS key policy for encrypted volumes. For EBS volumes encrypted with customer-managed KMS keys, the scanner’s AWS-managed role needs kms:CreateGrant, kms:Decrypt, kms:DescribeKey, kms:GenerateDataKey* on the key. Add this to every CMK that might be attached to a scan-eligible instance; without it, the scan fails with a “cannot access volume” error. AWS provides a documented key policy snippet for this.

Malware Protection for S3 on upload-accepting buckets. Enable per-bucket for any bucket that accepts uploads from external sources (customer uploads, partner-dropzone buckets, form attachments). The scanner tags objects on PutObject with the scan result; a bucket policy can require GuardDutyMalwareProtection:NoThreatsFound on read actions, effectively quarantining unscanned or threat-found objects until a human reviews. Priced per GB scanned; exempt internal-only buckets to control cost.

Runtime Monitoring for in-memory coverage. Enable on the production EKS clusters and on EC2 hosts running long-lived stateful workloads where fileless attacks are a concern. The eBPF agent is deployed automatically on EKS via an add-on and on EC2 via SSM-installed agent. Runtime Monitoring catches process-injection, unexpected network activity, unusual syscall sequences: signals the snapshot scan can’t see.

A worked incident

01:42 UTC. GuardDuty fires Trojan:EC2/BlackholeTraffic.DNS on i-0beef in a payments account. Malware Protection’s automatic trigger fires. Snapshot of the instance’s EBS volume taken in the customer account, shared to the AWS scanner account, scanner walks the filesystem.

02:04. Scanner emits Execution:EC2/MaliciousFile with:

  • File path: /tmp/.X11-unix/xmrig
  • Threat name: MinerX.XMRig.Generic
  • SHA256: 7d4b...
  • Linked to the earlier Trojan:EC2/BlackholeTraffic.DNS finding.

02:05. Security Hub receives the finding; EventBridge rule routes HIGH-severity Execution findings to PagerDuty. On-call already paged from the base detector finding.

02:08. With the specific file path in hand, the on-call SSHs to the instance (via Session Manager), confirms the file exists, notes its parent process in /proc, identifies the calling user (a deployment service account), and traces back to the Docker image pulled 40 minutes earlier.

02:15. Contain: quarantine the instance, pull the image from the deployment target, revoke the service account’s ECR pull permission, open a supply-chain incident for the image source. Base detector finding alone told the on-call something was wrong; Malware Protection finding told them what and where. That’s what cuts response time.

What’s worth remembering

  1. Malware Protection for EC2 is agentless snapshot-based. Triggered by specific GuardDuty base finding types or on-demand; emits follow-up findings with file paths and hashes.
  2. Encrypted volumes need KMS permission for the scanner. Grant the AWS-managed scanner role access on every CMK that might be attached to a scannable instance.
  3. Malware Protection for S3 scans uploads on PutObject. Per-bucket enable; tags objects with scan results; bucket policies can enforce scan-before-read.
  4. Runtime Monitoring is the in-memory complement. eBPF agent on EKS, ECS-Fargate, EC2 for fileless and memory-injection detection.
  5. The snapshot scan is not real-time. Malware that lands between scans is invisible until the next scan; Runtime Monitoring closes this gap.
  6. Base GuardDuty findings trigger the scan automatically. The feedback loop “network signal → trigger disk scan → correlate filesystem evidence” is the value.
  7. Findings flow to Security Hub via ASFF. Routing, severity, and workflow are consistent with the rest of the GuardDuty finding stream.
  8. Pricing is per-GB scanned. Large multi-TB volumes are expensive to scan on every finding; plan policy so that only severity-relevant findings trigger the scan.

GuardDuty sees packets; Inspector sees packages; Malware Protection reads the disk; Runtime Monitoring watches the processes. The real defence-in-depth is all four, each answering what the others can’t.

These posts are LLM-aided. Backbone, original writing, and structure by Craig. Research and editing by Craig + LLM. Proof-reading by Craig.