Martin Rozariyo
Back to writeups

L3m0nCTF2025-Writeups

Challenge Overview: Layers of Trust

Forensics/LayersOfTrust/Readme.md

Challenge Overview: Layers of Trust

Category: Forensics / Cryptography
Event: L3m0nCTF 2025
Role: Challenge Author

Category: Forensics / Crypto

🛠️ Author Note
This challenge was authored by me for L3m0nCTF 2025.
The following explanation describes the intended multi-layer analysis path.


image

Intended Analysis Path

The challenge was designed to test:

  • recognition of email containers as structured forensic artifacts
  • inspection of MIME nesting rather than surface content
  • correlation of metadata across unrelated formats
  • cryptographic key derivation from contextual email data
  • separation of decoy encryption from the true trust chain

Attempting to decrypt the PGP content directly without reconstructing the trust layers was intentionally ineffective.

Analysis Phase 1 — Establishing the Investigation Scope

The challenge explicitly mentions:

  • Raw email dump
  • Structure
  • Attachments
  • Encrypted content
  • Multiple layers

This indicates the challenge is not solved by reading the email body alone.
Instead, the solver must inspect the email container itself.

The investigation begins by treating the .eml file as a structured MIME container.

Analysis Phase 2 — Email Container Inspection

file mysterious_mail.eml

Expected output confirms it is an RFC 822 email.

On inspecting the file you can conclude there is a

We observe:

  • The email is multipart/mixed
  • It contains:
    • A plain text body with hints
    • An embedded PNG image (logo.png)
    • A nested email (Content-Type: message/rfc822)
    • A PGP block (decoy)

This confirms that the email structure itself is important.

Analysis Phase 3 — Nested Email Extraction

Scrolling through the file reveals a message/rfc822 section.

This represents a nested email, which we extract into a separate file.

nano inner.eml

Inspect it:

less inner.eml

Key headers found:

From: "A L1ce" <alice314@example.com>
Subject: Confidential Notes
Date: Thu, 20 Nov 2025 13:00:00 +0530

The body of this email explicitly defines the cryptographic logic used to derive the decryption key.

Analysis Phase 4 — Metadata-Based Key Material Discovery

The outer email embeds an image (logo.png) as base64.

We extract and decode it:

nano logo.b64
base64 -d logo.b64 > logo.png

Now inspect the metadata:

exiftool logo.png
image

Relevant fields:

Software          : argon2id
Artist            : time=3;mem=65536
Image Description : parallel=1
Copyright         : salt=7f3c8a21b4d9e012f3a5c9de7e12ab77

These values clearly correspond to Argon2id parameters.

Analysis Phase 5 — Base Secret Reconstruction

From the inner email instructions, the base secret is defined as:

image

Values used:

  • Outer From address (from outer email):admin@example.com
  • Inner Subject (lowercase, spaces removed):confidentialnotes
  • Inner Date converted to UNIX timestamp (UTC):
python3 - << 'EOF'
import email.utils
from datetime import timezone

dt = email.utils.parsedate_to_datetime(
    "Thu, 20 Nov 2025 13:00:00 +0530"
)
print(int(dt.astimezone(timezone.utc).timestamp()))
EOF

This gives the UNIX timestamp.

Final base secret format:

admin@example.com|confidentialnotes|1763623800

Analysis Phase 6 — Cryptographic Key Derivation

Using the extracted Argon2 parameters and base secret:

from argon2.low_level import hash_secret_raw, Type
import hashlib, binascii

base_secret = "admin@example.com|confidentialnotes|<timestamp>"
salt = binascii.unhexlify("7f3c8a21b4d9e012f3a5c9de7e12ab77")

hardened = hash_secret_raw(
   secret=base_secret.encode(),
   salt=salt,
   time_cost=3,
   memory_cost=65536,
   parallelism=1,
   hash_len=32,
   type=Type.ID
)

passphrase = hashlib.sha256(hardened).hexdigest()[:16]
print(passphrase)

The result is the correct PGP passphrase.

Final Output

From inner.eml, extract the PGP block and save it.

Decrypt using GPG:

gpg --decrypt inner.asc > secret.png

When prompted, enter the derived passphrase.

This successfully produces:

secret.png

image

you can see the flag in the image.

Flag: L3M0NCTF{m41l_ch41n_pgp_4rg0n2_kdf_png_st3g0_m4st3ry}