ESCalator
6.57K subscribers
477 photos
1 video
18 files
190 links
Tips and tricks от команды экспертного центра безопасности Positive Technologies (PT ESC)
Download Telegram
СHavocают

Недавно к нам в руки попало фишинговое письмо. Тема письма указана в лучших традициях телефонных спам-звонков, когда вам звонят из ФСБ и пытаются развести на деньги 🥺

Злоумышленники переняли схему: некий Андреев Н. В. запугивает громкими словами и обязует предоставить в срок необходимый перечень документов 😳

По щелчку на документы․zip пользователь перенаправляется на сайт:


hffp[:]//inforussia[.]org/dokumenty.html


Вместо zip-архива по ссылке открывается HTML-страница с HTML smuggling. Внутри находится большой объем данных, которые зашифрованы base64 и add(35). Во избежание детекта внутри HTML-страницы ключевые названия методов обращены в base64-строки. Зашифрованный пейлоад сохраняется как Dokument_FSB.exe.

Внутри находится дроппер. По классике он динамически подтягивает стандартные функции из KERNEL32.DLL для загрузки шеллкода. При этом используется кастомный алгоритм хеширования:


def calc_hash(function: str, init=0x43AB):
calc_hash = init
for i in function:
calc_hash = (ord(i) + 0x7313 * calc_hash) & 0xffffffff
return calc_hash ^ 0xAB98


Но, кроме этого, загружаются такие функции:

• FindResourceW
• LoadResource
• LockResourceA
• SizeofResource
• RtlIpv6StringToAddressA

Эти API используются для расшифровки самого пейлоада. В одном из ресурсов файла лежат IPv6-адреса, разделенные символами 0D 0A. Эти строки считываются в массив строк, затем переводятся в байты при помощи RtlIpv6StringToAddressA. Уже потом полученный массив байт ксорится с огромным ключом-строкой в 0x2710 байт.

Полученный шеллкод понтово запускают в fiber, так же динамически подгружая API для этого. Внутри находится стандартный загрузчик demon Havoc.

IOCs


2a79d641b2c377474ff640343e77517b21a51315c3736966336372b3da8995b1
7c2f59d9790b816cb6f27a796d7c928046519f7429b7d2bbe53c60a7a55e22a7
ac301b7698ac040f219eb8dfb248595a406b075d91f51116ef60d4dd9f5242ad
inforussia[.]org
193.3.23[.]121
46.29.162[.]93


#TI #Phishing #ioc
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👏6👍3
Как не бороться с обфускацией 🫤

Автоматическое извлечение конфигураций упрощает выявление новых C2. Мы реверсим вредоносное семейство, находим конфигурацию и пишем скрипт для ее извлечения. Однако, если код сильно обфусцирован, как в случае, например, с Emotet 5, задача усложняется.

Помимо техники Control Flow Flattening, которая сама по себе неприятна, он добавляет много мертвого кода, а также раскладывает арифметические выражения на набор, казалось бы, бессмысленных и случайных операций, например, как на скрине 1.

Значение, которое кладется в edx, — второй аргумент функции run_send_recv_timer — вычисляется весьма странным образом, хотя в итоге результат выглядит как на скрине 2.

Все эти арифметические упражнения необходимы, чтобы в итоге получить 1.

📂 Эффективное извлечение конфигурации требует умения находить важные фрагменты кода и данных, в том числе среди подобных образцов.

Нас интересует в этом случае публичный ECDH-ключ сервера, используемый для генерации сессионного ключа шифрования данных в протоколе. Он зашифрован однобайтовым XOR. Проблема заключается в рандомизированных арифметических операциях для сборки буфера ключа на стеке.

Найти функцию расшифровки в дампе просто, нужный фрагмент кода — на скрине 3.

🧐 Встает проблема найти ссылку на функцию. Если бы семпл был x32, то задача была бы проста: найти начало функции и байты E8 <function-address-LE>, то есть call с операндом в виде адреса функции расшифровки.

Но в x64 вся адресация RIP-relative, то есть операнды-адреса — это смещения относительно конца текущей инструкции. Значит, мы найдем все инструкции call и проверим, равен ли операнд адресу начала функции расшифровки. Выглядит это так:


calls = self.mdmp.find_bytes(b"\xE8", segment_start, segment_size, find_first=False)
decrypt_refs = []
for call_pos in calls:
call_offset = self.mdmp.read(call_pos + 1, 4)
call_offset = struct.unpack("<i", call_offset)[0]
if call_pos + 5 + call_offset == decrypt_key_func_start:
decrypt_refs.append(call_pos)
if len(decrypt_refs) == 2:
break


💡Примечание: ссылок две, потому что зашито два ключа — один для ECDH, второй для ECDSA, каждый расшифровывается в отдельной функции.

Найдя ссылку на функцию расшифровки, ищем начало вызывающей ее функции. Ее псевдокод — на скрине 4.

Зашифрованный ключ собирается на стеке и далее расшифровывается. Мы знаем, что за этой красотой стоит сильно обфусцированный ассемблерный код, значит, считать буфер «as is» будет тяжело.

Прибегнем к такому инструменту, как эмулятор. Мы не будем деобфусцировать это скриптом, воспроизводить логику, а просто «выполним» это и считаем результат.

Для этого, поскольку мы знаем адрес ссылки на функцию decrypt_KEY, мы должны всего лишь найти начало функции decrypt_ECK1, считать ее и отдать эмулятору, который сделает всю грязную работу. Для эмуляции используем Speakeasy, который умеет эмулировать не только инструкции, но и среду ОС.

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


def emulate_decrypt_key_func(self, func_body):
emul = speakeasy.Speakeasy()
shellcode = emul.load_shellcode(fpath=None, data=func_body, arch="amd64")
ctx = {"entry": True, "mem": emul.mem_alloc(4), "skip_call": True}
emul.add_code_hook(self.code_hook_key, ctx=ctx)
emul.run_shellcode(shellcode)
decrypted = self.decrypt(ctx["encrypted_string"], ctx["key"], ctx["length"])
return decrypted


Внутри коллбэка мы пропускаем один call — вызов пустышки nullsub_4 — и останавливаемся перед вызовом decrypt_key. В этот момент в одном из параметров лежит готовый буфер с зашифрованным ключом. Далее этот буфер считывается и расшифровывается в ECDH-ключ, как видно на скрине 5.

Благодаря эмулятору, мы не стали пытаться изменить обфускацию, а приняли ее такой, какая она есть, чтобы получить желаемое 😌

#tip #trick #C2
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍156🥰1👏1
Фишинговая легитимность 😂

В рамках анализа одного из фишинговых писем мы заметили, как злоумышленники попытались разместить фишинговый контент на странице домена telegra․ph.

Их задумка, вероятно, состояла не в использовании «обширного» функционала сервиса для публикации контента, а в репутации самого домена. И это может сработать, ведь с учетом вполне легитимного наполнения данных WHOIS, SSL-сертификата, а также веб-категории домена telegra․ph у различных агрегаторов эта страница при анализе получит минимум нейтральный статус.

Все это натолкнуло нас на мысль рассмотреть некоторые кейсы использования легитимных сервисов в фишинговых кампаниях, встречающиеся на практике.

1️⃣ Собственно, Telegraph.

Это анонимная блог-платформа известного разработчика. Функционал минималистичен, отсутствуют элементы управления, а текст публикуется с использованием только двух уровней заголовков: Title и сам текст.

В сам блог есть возможность поместить только кликабельные элементы для перехода на фишинговую страницу, при этом стилистика остается нейтральной и минималистичной. Пример фишинговой страницы в telegra․ph — на скриншоте.

В каком-то смысле подобный стиль страницы напоминает текстовое электронное письмо, с той лишь разницей, что непосредственно вредоносная ссылка прячется от автоматизированных средств анализа еще за одним уровнем перехода.

2️⃣ Онлайн-среды разработки.

Онлайн-среда разработки, поддерживающая HTML, JavaScript, да еще и с функцией совместной разработки и публикации (вроде JSFiddle), может использоваться для доставки вредоносов или внедрения в цепочку сложных и разнообразных техник редиректа.
Вот, например, размещенный на JSFiddle код с загрузкой png-картинки, исполняющийся без дополнительных действий:


a = document.createElement('a');
document.body.appendChild(a);
a.download = name;
a.href = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAYAAAAmL5yKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABWSURBVDhPY0xISPh//0UOA7mAiVyNMH2jBjAwkBQGjD9KGBTEJ6OEO0kG2NvbMwCjnXwDsEU5SS5ANuDhjRCGJbPFSQsDdBfIyMhQZgDIQLK9QLWkDABPsQw5I+5qmAAAAABJRU5ErkJggg==";
a.click();


Проблема подобных ссылок с онлайн-IDE понятна: под них легко придумать фишинговое содержание письма («я разработчик, вот мое портфолио с проектами»), а репутация их доменов не даст сработок у средств анализа.

Кроме того, для анализа содержимого страницы потребуются продвинутые средства, позволяющие эмулировать переходы по страницам или загрузку контента путем выполнения JavaScript-кода.

3️⃣ IPFS.

Известный протокол распределенного хранения файлов стал популярным инструментом среди злоумышленников. Точнее, не сам протокол, а так называемые IPFS-шлюзы — онлайн-сервисы, предоставляющие доступ к файлам, размещенным с использованием этой технологии без специальных клиентов. Они являются своего рода прокси для доступа к размещенным в подобном хранилище HTML-страницам, что позволяет злоумышленнику не заморачиваться с хостингом страницы.

Кроме того, файл с IPFS-хранилища невозможно удалить: IPFS-хостинг может лишь повесить заглушку о вредоносном содержимом запрашиваемого файла, при этом самому хостингу, чтобы найти такой контент в хранилище, требуется время и ресурсы.

Чтобы защититься от подобной эксплуатации легитимных сервисов, при защите периметра можно использовать средства защиты, проверяющие контент веб-содержимого URL-ссылок перед вынесением вердикта. А при получении подобных ссылок на личную почту или в мессенджере лучше перестраховаться и проверить их в нескольких сервисах, показывающих репутацию индикаторов компрометации.

#web #ti #tip
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍8😱31
Полковники пишут первыми! (🔞)

В коллекции вредоносных рассылок от имени правоохранительных органов пополнение.

В сентябре нескольким адресатам было отправлено письмо от «Следственного комитета» с повесткой для вызова на допрос в качестве свидетеля по уголовному делу (скриншот 1).

Сама повестка — это PDF-документ, который при попытке открыть его грустно констатирует, что просмотреть содержимое не получается и нужно скачать Adobe Font Package, чтобы данные отобразились корректно (скриншот 2).

🔗 Ссылка ведет на домен adobe.updatedownloader.com, откуда, если обратиться к нему с российского IP-адреса, действительно скачивается файл с именем:


adobe_PDF_reader_fonts_update_24.2.5_Win_x86-64.exe (bea1dfdae82c67aac7a262c25dffadc0190270e2412db0c051da9ffab8e3a157)


К сожалению, файл представляет собой Medusa Stealer, поэтому прочитать документ так и не получится…

🧐 Если внимательно приглядеться к письму, можно заметить пасхалки — и разоблачить злоумышленников:

В поле отправителя указано noreply@sledcom.ru — это легитимный адрес электронной почты государственного органа, однако письмо не содержит подписи DKIM, позволяющей проверить подлинность отправителя.

Письмо отправлено c IP-адреса, не принадлежащего организации, от имени которой якобы пришла повестка.

«СЛЕДСТВЕННIЙ КОМИТЕТ» в шапке письма.

IOCs

Net:

updatedownloader.com
62.197.48.140
5.42.73.251


Files:

bea1dfdae82c67aac7a262c25dffadc0190270e2412db0c051da9ffab8e3a157
7fa0642a96e8e9a796a4dba55877d1c730c64f257956872c3f6d405417e30024


#ti #phishing #ioc
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍11👾4🤯2
🟥 ⚔️ 💿 Виртуальный диск как начало атаки

В начале сентября эксперты группы киберразведки TI департамента PT ESC обнаружили интересный VHDX-файл, который оказался частью цепочки атаки на организации в странах Азии. Мы не знаем точного исходного вектора, но, скорее всего, файл распространялся через фишинг.

✍️ VHDX-файл — это виртуальный диск, который можно подключить к системе начиная с Windows 8 двойным нажатием мыши. Он будет считаться логическим томом до выключения системы.

Как и любой контейнер, VHDX-файл может выступать в роли вредоносного объекта. Исследователь Уилл Дорманн в посте от 2019 года рассказал, что с помощью специально подготовленного образа можно спровоцировать системную ошибку в Windows и вызвать «синий экран смерти».

👾 В атаках мы редко видим использование этого контейнера, однако виртуальный диск может содержать в себе вредоносные файлы, которые должна запустить жертва. Хакер может убедить жертву сделать это через техники социальной инженерии. Для начала заражения устройства жертве достаточно открыть присланный ей диск и запустить вредоносный файл внутри него. Схема заражения (например, как на первом скриншоте) такая же, как в случае, если бы пользователю прислали архив с таким же вредоносным вложенным файлом.

💡 Для хакеров преимущество в использовании VHDX-файлов (как и в использовании ZIP-файлов) заключается в том, что они не подпадают под действие MoTW (Mark of the Web): при запуске документа из этих контейнеров не включается режим Protected View, а Windows SmartScreen не предупреждает жертву об опасности. Стоит также отметить, что под VHDX-формат приспособлено меньшее количество антивирусных решений, чем под те же ISO-файлы. Следовательно, при попадании в систему образ вряд ли будет моментально удален этим СЗИ.

Хотя VHDX-файлы и редко используются в атаках, TI-аналитику, как и любому другому исследователю, важно уметь качественно анализировать эти файлы, чтобы не упустить важные детали, которые могут помочь провести атрибуцию или дать дополнительные IoC, позволяющие построить связи с другими атаками.

Хакеры допускают ошибки: они могут использовать один VHDX-файл в двух разных атаках или же загрузить ошибочные файлы. В любом из этих случаев злоумышленники, как правило, удаляют файлы, а так как это диск, то аналитик может попробовать их восстановить (в том числе с точными датами создания этих файлов) — другими словами, аналитик может построить таймлайн изменения файлов на диске. Это можно сделать с помощью специальных инструментов для проведения форензики.

👀 Рассмотрим наиболее эффективные методы и инструменты, которые можно использовать для анализа диска:

Создание виртуальной машины и монтирование диска в нее. Это позволит посмотреть файлы в проводнике и увидеть то, что получила жертва атаки (но не удаленные файлы).

Autopsy — универсальный инструмент для исследования образов, который может получать данные из множества файлов разных типов, физических дисков, сырых образов. Есть таймлайн изменения файлов внутри образа (пример — на втором скриншоте).

• FTK Imager — аналог программы Autopsy, показавший наилучшие результаты в извлечении удаленных файлов с диска.

🛡 Как вариант защиты от атак с использованием VHDX стоит использовать почтовые фильтры, запрещающие передачу этого типа файла во вложениях писем — как от внешних отправителей, так и от внутренних.

В скором времени мы опубликуем статью, в которой детально разберем эту атаку. Следите за новостями.

#ti #tool #tip #news
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥166👍6🐳1🆒1
🛠 Реверсим Delphi без IDR

Когда активно занимаешься реверсом, рано или поздно возникает ситуация, когда на твоем пути появляется исполняемый файл на Delphi. Анализ объектов в Delphi требует особого подхода, и вручную это делать сложно. Однако такой анализ можно значительно ускорить с помощью автоматизации, если знать, как именно устроена структура объектов.

🕵️ Первый шаг при анализе Delphi — не забыть переключить параметр компилятора в OptionsCompiler OptionsCompiler, тогда IDA будет лучше обрабатывать вызовы функций.

Классы в Delphi создаются через функцию ClassCreate, которая получает на вход указатель на структуру класса и вызывает в нем функцию Tobject_NewInstance путем вычитания оффсета из указателя на VMT.

👀 Сама структура класса в Delphi выглядит следующим образом (пример на скриншоте 1):


struct DelphiClassInternal
{
DWORD* vmt;
DWORD* InterfaceTable; используется только для интерфейсов
DWORD* PAutoTable;
DWORD* PInitTable;
DWORD* TypeInfo;
DWORD* FieldTable;
DWORD* MethodTable;
DWORD* DynamicMethodTable;
}


💼 Рассмотрим содержимое полей TypeInfo, MethodTable и FieldTable подробнее, поскольку в них больше всего полезной для анализа информации.

➡️ TypeInfo

В Delphi каждый тип объекта имеет свой идентификатор. Как видно на скриншоте 2, для нашего объекта выставлен идентификатор 7 — тип Class. В зависимости от этого типа, для объекта указывается соответствующий контекст. Для классов это информация о Property и указатель на родительский тип. Зная имя Property, нетрудно понять и разметить Get/Set-функции. Восстановление этих имен позволяет сильно упростить восприятие некоторых блоков кода. Пример на скриншоте 3.

➡️ MethodTable

Внимательный читатель заметит, что на скриншоте 1 присутствуют имена некоторых методов. Достать их можно, заглянув в таблицу опубликованных (Published) методов (текущего и родительского классов). Delphi не хранит информацию о других типах методов: приватных, защищенных и публичных. Помимо имени, там приводятся: возвращаемый тип, количество аргументов, их типы и имена.

Псевдоструктуру метода можно представить так (пример на скриншоте 4):


struct CMArg
{
DWORD* TypeInfo;
WORD UNK;
BYTE NameLen;
char Name[];
BYTE UNK2[3];
}
struct ClassPubMethod
{
WORD EntrySize;
DWORD* MethodPtr;
BYTE NameLen;
char Name[];
WORD W_UNK1;
DWORD* ReturnType;
WORD W_UNK2;
BYTE ArgCount;
CMArg Args[];
}


Из-за механизма наследования методов в Delphi восстановление даже части имен методов имеет большую пользу, если сделать это глобально, для всех классов. Затем это можно использовать среди прочего и для генерации структуры VMT класса с осмысленными именами. Пример — на скриншоте 5.

➡️ FieldTable

Заглянув в ClassFieldTable, можно найти большое количество информации о переменных (пример на скриншоте 6). Представлена она может быть в двух вариантах:

1. В виде имени, оффсета и номера типа переменной (из таблицы типов). Первые два байта в FieldTable — количество элементов в этой таблице, следующие четыре — указатель на таблицу типов.

2. В виде имени, оффсета и указателя на тип переменной (таблица начинается сразу после таблицы из п. 1).

Структура переменных имеет следующий вид:


struct VarTypeTable
{
WORD Count;
DWORD* Entries[];
}
struct ClassVar
{
DWORD* TypeInfo;
WORD VarOffset;
WORD UNK;
BYTE NameLen;
char Name[];
}
struct TableClassVar
{
WORD VarOffet;
WORD UNK;
WORD TableTypeNum;
BYTE NameLen;
char Name[];
}


Исходя из полученной информации о переменных можно составить структуру класса (нужно не забыть, что переменные также наследуются из родительских классов). Пример — на скриншоте 7.

🤔 Резюме: в Delphi присутствует большое количество RTTI-информации, за счет которой можно относительно просто разметить большое количество функций или восстановить структуру классов для упрощения статического анализа.

#TI #Delphi #Reverse
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥25👏6👍5👎1😱1💩1🤡1