Anatomy of a Phish: Decoding Quoted-Printable & Base64 Payloads
Attackers hide malicious URLs inside layers of encoding; here’s how to rip them out of a raw email header and find the phish.

You’re staring at a blob of text in a raw email source: `href=3D"h= ttps://evil.corp/malware.exe"`. The equals signs are a dead giveaway. This isn’t just text; it’s Quoted-Printable encoding, a simple trick to bypass naive security filters that are only looking for a clean `https://` string.
This is the daily reality of phishing analysis. Attackers aren't just sending you a link; they're wrapping it in layers of legitimate, standards-compliant encoding defined decades ago. RFC 2045 wasn't written for evil, but it's now a primary tool for it.
Understanding how to manually peel back these layers—Quoted-Printable and its cousin, Base64—is a non-negotiable skill for any serious analyst. It’s the difference between closing a ticket as 'benign' and catching a campaign before it spreads.
A Quick Refresher on MIME and Encodings
Before we get to the malicious parts, let's establish a baseline. Modern email isn't just plain text. It's a structured collection of parts, defined by the Multipurpose Internet Mail Extensions (MIME) standard. This is what allows an email to contain styled text, images, and attachments all in one message.
Two headers are critical here: `Content-Type` tells the email client what a specific part of the message is (e.g., `text/html`, `image/jpeg`, `application/pdf`). The `Content-Transfer-Encoding` header tells the client *how* that content is packaged for safe transport across systems that might only handle 7-bit ASCII characters.
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
This is where Quoted-Printable and Base64 enter the picture. They are two common encoding schemes. Base64 is designed to represent any binary data (like an image) using only 64 printable ASCII characters. Quoted-Printable is meant for text that is *mostly* ASCII but contains some non-ASCII characters (like accented letters or symbols). It does this by encoding problematic characters as an `=` followed by two hex digits.
Neither is inherently malicious. They are foundational technologies for a global email system. The problem is when they're used not for compatibility, but for evasion.
Why Attackers Bother with Encoding
The motive is simple: break the scanner. Many email security gateways, especially older or poorly configured ones, rely heavily on static signatures and regular expression matching to find threats. They have lists of known-bad domains, IP addresses, and URL patterns. If they can read the content, they can flag it.
Bypassing Simple String Matches
Imagine a filter rule that blocks any email containing the string `phishing-domain.com`. An attacker can take that URL, encode just the HTML body of the email using Base64, and send it on its way. The raw source will contain a large, harmless-looking block of characters like `aHR0cHM6Ly9waGlzaGluZy1kb21haW4uY29t`. The filter, scanning the raw message body for `phishing-domain.com`, finds nothing and passes the email.
The user's email client, however, dutifully reads the `Content-Transfer-Encoding: base64` header, decodes the content, and renders the malicious link perfectly. The attack succeeds. It's a lazy tactic, but it works far more often than it should.
Fractionated Obfuscation with Quoted-Printable
Quoted-Printable (QP) offers a more granular way to hide. Instead of encoding the entire block, an attacker can encode just a few key characters. They can even insert soft line breaks (an equals sign at the end of a line) to chop up the URL string, making regex matching even harder.
A link to `https://secure-login.com/update` could become `h= ttp=3A//s= ecure-login.com/updat=65`. Notice the mix of encoded and plaintext characters. The `=` is encoded to `=3D`, `/` becomes `=2F`, and even the `e` is encoded as `=65`. This is noise designed to defeat pattern matching while remaining perfectly renderable by the email client. This is the kind of thing you'll see in a BEC attempt trying to impersonate a legitimate service.
Pulling Back the Curtain with Python
When you have the raw `.eml` file, you don't have to guess. Python's standard library has everything you need to deconstruct these payloads in seconds. No external dependencies required. Let's assume you've isolated the encoded string.
Decoding Quoted-Printable
Python's `quopri` module is your tool for this. It’s direct and effective. Given a string, it will decode the `=XX` hex sequences and stitch the soft line breaks back together.
import quopri
encoded_string = b'Click here for your invoice: <a href=3D"https://bad.guy/inv=_=
voice.html">Link</a>'
decoded_string = quopri.decodestring(encoded_string)
print(decoded_string.decode('utf-8'))
# Output: Click here for your invoice: <a href="https://bad.guy/invoice.html">Link</a>
Note the `b` prefix on the string, indicating it's a bytes object. Encoding and decoding operations in Python 3 work on bytes, not strings. This is a crucial detail. You often need to handle the `charset` specified in the `Content-Type` header to decode the resulting bytes into a readable string correctly.
Decoding Base64
Similarly, the `base64` module handles Base64-encoded data. The function `b64decode` is what you need. It's just as straightforward.
Let's say a phisher encoded an entire HTML part. You'd extract that block of text from the email source and feed it to the decoder. Be mindful of padding errors; valid Base64 input length must be a multiple of 4, sometimes requiring `=` padding characters at the end. A malformed payload might indicate a broken script or a deliberate attempt to crash naive decoders.
Hunting for the Real Payload
It’s rarely as simple as finding one encoded block. Attackers know that modern security solutions *can* decode Base64 and QP. So, they layer their tricks within the MIME structure itself.
A common technique involves a `multipart/alternative` message. This MIME type is designed to provide the same content in multiple formats, typically `text/plain` and `text/html`. An email client will display the 'richest' version it can handle, which is almost always the HTML part.
Attackers exploit this by putting benign, harmless text in the `text/plain` part. An automated scanner that only looks at the first part, or prefers the simpler text part, might see "Please see the attached invoice" and move on. The real payload—the encoded, malicious link—is buried in the `text/html` part, which is what the user actually sees and clicks.
As an analyst, you must parse the full MIME tree. Never stop at the first `Content-Type` you see. Look for all the parts, decode them all, and compare what you find. The discrepancy between the plain text part and the HTML part is often the biggest red flag.
Furthermore, look for encoding on top of encoding. It's not uncommon to see a URL with certain characters HTML-entity encoded (e.g., `.` becomes `.`) inside a Quoted-Printable HTML body which is then wrapped in a MIME message. Each layer is meant to fool a different type of parser.
From URL to Verdict: The Sandbox Handoff
Once you’ve successfully decoded the payload and extracted the true destination URL, your job isn't done. You've just found the real weapon. Now you need to know what it does.
Never, ever visit the URL from your corporate workstation. Don't even run a `curl` against it from your analysis machine unless you know exactly what you're doing and have it properly isolated. The initial GET request could be enough to trigger a download or reveal your organization's IP address to the attacker.
This is the point of handoff to a URL analysis sandbox. These tools will visit the URL in a secure, instrumented, and disposable environment. They'll record what happens: Does it redirect? Does it serve a file? What's the file's hash? Does it attempt to exploit the browser? Does it present a credential harvesting form that looks like your company's SSO page?
The output from the sandbox provides the final pieces of evidence you need to declare a verdict. The decoded URL is your lead, but the sandbox report is the proof you need to justify blocking the domain, purging the email from inboxes, and potentially escalating the incident.
Key Deep-Dive RFCs
For those who want to go straight to the source, reading the original RFCs is invaluable. They clarify the 'why' behind the email standards that are now being abused. They're not light reading, but they are the ground truth.
RFC 2045: MIME Part One: Format of Internet Message Bodies
RFC 2046: MIME Part Two: Media Types
RFC 2047: MIME Part Three: Message Header Extensions for Non-ASCII Text — Internet Engineering Task Force (IETF)
Understanding these documents gives you an edge. When you see an unusual header or a strange encoding choice, you can reference the spec to determine if it's a legitimate, if obscure, feature or a deliberate deviation designed for evasion. That distinction is critical in separating sophisticated attacks from system quirks.
The takeaway
Encoding is a fundamental part of email, not a bolt-on feature. And because of that, it's not going away. Attackers will continue to use these built-in functions as a low-cost way to conceal their tracks from first-pass security filters. Being able to quickly and confidently decode their payloads is a core competency.
The next time you find a suspicious email, don't just look at the rendered output. Pop the hood. Grab the raw source, find those `Content-Transfer-Encoding` headers, and start peeling. Your ability to see what the machine sees—and what the attacker hopes it will miss—is your greatest asset. High-level analysis platforms like MailSleuth.AI automate this deconstruction, but knowing how to do it yourself is the only way to truly validate the findings and hunt for novel threats.
We dissect phishing campaigns and email infrastructure so you don't have to.


