Chrome
Let us place all of our trust in a password manager.

TryHackMe: Прохождение комнаты Chrome.
Дан файл с записью перехваченных пакетов сетевого трафика в формате .pcapng
(Packet CAPture Next Generation). Необходимо разобраться, что именно украл злоумышленник.
Обзор
Работать с данными файлами можно различными инструментами, например популярным сниффером и анализатором Wireshark или фреймворком pyshark. Здесь будет использован tshark.
Взглянем на общую картину перехваченного трафика, а именно на статистику по протоколам:

Можно заметить активный трафик по SMB, а так же 60 Мб трафика данных (data), что говорит о передаче файлов.
Извлечем эти файлы:

Получен ряд файлов, 71 Мб занимает файл encrypted_files
, файлы же transfer*.exe
идентичны.
Изучим transfer.exe
. Если глянуть на строки в файле, легко обнаружить, что это некое .net приложение.
FrameworkDisplayName
.NET Framework 4.7.2
RSDS
C:\Users\hadri\Desktop\Chrome\transfer\obj\Debug\transfer.pdb
_CorExeMain
mscoree.dll
Приложения под .net компилируются в промежуточный язык который транслируется в машинный код уже только во время выполнения, поэтому их можно крайне эффективно декомпилировать. Существует множество инструментов для этого, например десктопный AvaloniaILSpy, либо онлайн сервис decompiler.com
Декомпилированный код приложения:
private static void
Приложение довольно примитивно, оно берёт некий файл files.zip
и зашифровав его с помощью AES сохраняет под видом encrypted_files
. Нам доступны ключ и вектор исполнения (инициализации, IV). Размер ключа равен 32 байтам (256 бит):
|
Такой размер ключа означает использование AES-256. Расшифруем файл encrypted_files
с помощью openssl
:
enc
– режим шифрования/дешифрования.-in
– входной (зашифрованный) файл.-out
– расшифрованный файл.-aes-256-cbc
– алгоритм AES-256, CBC.-d
– задача расшифровать файл.-iv
– вектор исполнения, он задается в шестнадцатеричном формате. Для перевода строки в hex можно воспользоватьсяxxd
:-p
– перевод строки в hex.-c0
– убрать разбиение на столбцы.
-K
– ключ, так же задается в шестнадцатеричном формате.

Теперь можно распаковать полученный архив:

Очевидно злоумышленник скопировал папку AppData
, она предназначена для хранения приложениями своих служебных данных. Например, можно заметить папку с профайлом браузера Chrome. Именно здесь браузеры на основе Chromium хранят пароли от сайтов. Проверим наличие паролей, они хранятся в файле User Data > Default > Login Data
. Данный файл представляет ни что иное, как обычную базу данных SQLite:
В качестве альтернативы
sqlite3
можно использовать куда более удобную утилитуlitecli
. Она поддерживает автодополнение и правильное форматирование выводимых данных.

В таблице logins
находятся две записи с паролями. Пароли, конечно же, зашифрованы.
Во всех браузерах на основе Chromium (кроме Яндекс.Браузера) применяется один и тот же алгоритм: пароли зашифрованы с помощью AES GCM единым ключом. Данный ключ же в свою очередь зашифрован с помощью стандартного API Windows - DPAPI. API предоставляет простые функции CryptProtectData
/CryptUnprotectData
основная идея которых заключается в том, что расшифровать данные может только пользователь с той же учётной записью, что и пользователь зашифровавший данные. Достигается это за счёт того, что данные шифруются с помощью случайно сгенерированного мастер-ключа который в свою очередь зашифрован с помощью предварительного ключа (pre-key) что генерируется на основе пользовательского пароля в системе (NT-хэша) и его уникального идентификатора безопасности (SID); так же используется определенное число итераций, соль и код проверки подлинности (HMAC).
Зашифрованный мастер-ключ и параметры генерации (а разные версии ОС используются различные алгоритмы шифрования и хеширования) хранятся в специальном файле. Имея данный файл, SID пользователя и пароль в системе, можно сгенерировать предварительный ключ и расшифровать мастер-ключ, а с ним и расшифровать любые данные зашифрованные с помощью CryptProtectData()
.
А что произойдёт, если пользователь сменил пароль, ведь в этом случае предварительный ключ так же изменится и станет невозможно расшифровать мастер-ключ. Станут ли пользовательские данные зашифрованные старым ключом невалидны? На этот случай Windows хранит хеши (NT/SHA1) всех прошлых паролей пользователя в специальном файле CREDHIST
, равно как и все зашифрованные мастер-ключи, каждый в своём отдельном файле. Таким образом, если система не может расшифровать текущий мастер-ключ, она последовательно будет перебирать все записи из данного файла.
Мастер-ключ хранится в %USER%\AppData\Roaming\Microsoft\Protect\<SID>\
. Если пользователь менял пароли, то там будет несколько файлов, указатель на текущий мастер-ключ будет записан в файле Preferred
. <SID>
– обозначает идентификатор безопасности.
В полученном архиве имеются все данные файлы:
SID пользователя:
S-1-5-21-3854677062-280096443-3674533662-1001
файл с зашифрованным мастер-ключом:
8c6b6187-8eaa-48bd-be16-98212a441580
история паролей:
CREDHIST
What is the first password that we find?
Чтобы расшифровать ключ из браузера Chrome которым зашифрованы пароли, можно воспользоваться приложением DataProtectionDecryptor. Оно требует указать путь к папке Protect
с данными для DPAPI, а так же пароль пользователя в системе. Пароль пользователя нам не известен, но имея SID и файл с зашифрованным мастер-ключом можно провести брутфорс атаку на пароль.
Если у вас в системе нет словарей паролей, то их можно скачать с репозитория SecLists. В Linux дистрибутивах Parrot и Kali они предустановлены в
/usr/share/wordlist
.
С помощью DPAPImk2john.py достанем хеш и проведем атаку по словарю:
-S
– SID пользователя, берется из имени папки с мастер-ключами.-mk
– файл с данными мастер-ключа.-c local
– контекст определяющий откуда ключ: локальный (local
) или контроллера домена (domain
).

Пароль успешно подобран. Это ответ на первый вопрос.
What is the URL found in the first index? What is the password found in the first index?
Теперь имея пароль пользователя в системе, можно расшифровать ключ для паролей Chrome. Данный ключ находится в json файле Local State
:
"os_crypt": ,
Значение закодировано в base64. Особо стоит отметить, что в самом начале ключа добавлен суффикс DPAPI
, поэтому первые 5 байт необходимо пропустить (ключ -s +5
для xxd
):
|
| |

Получив зашифрованный ключ, теперь можно приступить к его расшифровке. Для DataProtectionDecryptor необходимо в настройках “DPAPI Decryption Options” выбрать режим “Decrypt DPAPI data from external drive or another user”, указать путь к AppData
, пароль пользователя, выбрать опцию “Decrypt DPAPI data from the specified string” и ввести данные полученные выше. Программа расшифрует ключ:
В качестве альтернативы DataProtectionDecryptor можно использовать
mimikatz
,pypykatz
,Impacket
,DPAPI-NG
илиDPAPIck
.
Получив расшифрованный ключ, можно расшифровать и пароли, для удобства написан скрипт на Go.
Дополнительно необходимо уточнить структуру паролей: первые три байта это сигнатура (версия), следующие 12 байт это вектор инициализации, далее собственно сам пароль.
package main
import (
"crypto/aes"
"crypto/cipher"
"database/sql"
"encoding/hex"
"errors"
"flag"
"fmt"
_ "github.com/mattn/go-sqlite3"
"os"
"text/tabwriter"
)
var dbfile string
var aeskey string
var key []byte
func init()
func main()
func checkErr(err error)

Пароли успешно расшифрованы. Получены ответы на все вопросы комнаты.
Дополнительно
Среди перехваченных пакетов сетевого трафика можно обнаружить пакеты аутентификации протокола NTLMSSP используемого smb:
|

В этих пакетах достаточно данных для попытки подобрать пароль. Создадим файл с данными в следующем формате:
пользователь::домен:NTLM Server Challenge:NTProofStr:остаток NTLMV2 Response
Выведем все необходимые данные:
-Y "ntlmssp.messagetype == 0x3"
– отфильтруем пакетNTLMSSP_AUTH
-Tfields
– вывести значения полей-e ntlmssp.auth.username
– имя пользователя-e ntlmssp.auth.domain
– домен-e ntlmssp.ntlmv2_response.ntproofstr
– NTProofStr-e ntlmssp.ntlmv2_response
– ответ NTLMV2 (ответ будет включать, в том числе и NTProofStr, их нужно разделить двоеточием, поэтому для удобства где разделить, NTProofStr выводится выше отдельно)
tr -s "\t" "\n"
– замена табуляторов на символ новой строки, чтобы все поля были выведены не последовательно, а каждое на новой строке.
|
-Y "ntlmssp.messagetype == 0x2"
– отфильтруем пакетNTLMSSP_CHALLENGE
-Tfields
– вывести значения полей-e ntlmssp.ntlmserverchallenge
– NTLM Server Challenge

Получим следующий файл:
hacked::MicrosoftAccount:aaaaaaaaaaaaaaaa:244685bd249979d4bd166a0abdfa27d9:
010100000000000080a583db9f04da01b18aaf3d35164a6f000000000100100048006200580
06a004400450052006600030010004800620058006a00440045005200660002001000780053
006c004e006500720054006b0004001000780053006c004e006500720054006b00070008008
0a583db9f04da0106000400020000000800300030000000000000000100000000200000553d
e98b4e7403dd7106431cb8cc73ab2e76205f81fdc4bede196950942fb3020a0010000000000
000000000000000000000000009001c0063006900660073002f00310030002e0030002e0032
002e00330036000000000000000000
Теперь можно попробовать в hashcat
подобрать пароль:
-m 5600
– NetNTLMv2-a 0
– подбор по словарю

На этом всё.