ESCalator
6.58K subscribers
477 photos
1 video
18 files
190 links
Tips and tricks от команды экспертного центра безопасности Positive Technologies (PT ESC)
Download Telegram
Генерация COM vtable в IDA 🐍

В процессе разбора одного из вариантов Snake Keylogger нужно было разобраться, какие managed-методы нативный модуль вызывает через COM-интерфейсы. Это означает, что нам нужно было вручную насоздавать какое-то количество структур. И еще нам бы хотелось видеть сигнатуру каждого метода, а их много.

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

OLE/COM Object Viewer (oleview)
MIDL компилятор (midl.exe, входит в Visual Studio Build Tools)
IDA

📂 Воспользуемся OLE/COM Object Viewer (oleview), чтобы открыть mscorlib.tlb и найти интересующие нас интерфейсы. Путь к нему:

C:\Program Files (x86)\Windows Kits\10\bin\<версия>\x86\oleview.exe


В mscorlib.tlb находятся COM-описания базовых managed-интерфейсов. Этот файл обычно лежит в каталоге:

C:\Windows\Microsoft.NET\Framework\<Версия>\mscorlib.tlb


Открыв файл, мы видим его IDL — Interface Definition Language (скриншот 1).

🫱 Далее находим в дереве oleview нужные нам интерфейсы (например, _AppDomain). Выгружаем их IDL и по примеру IDL для mscorlib (скриншот 1) собираем свой (скриншот 2). Пример минимального IDL представлен на скриншоте 3 (количество методов урезано).

На этом шаге нужно немного почистить файл:

1️⃣ Форварднуть интерфейсы, определить value-типы. Интерфейсы можно форвардить, так как указатель на них всегда одинакового размера. Но value-типы требуется определить полностью, иначе будет ошибка unsatisfied forward declaration. Мы обойдемся заглушками: для сигнатур методов этого достаточно.

2️⃣ Отредактировать объявления функций.

На скриншоте 4 мы видим, как объявлен COM-метод GetEvents_2. Это вариант перегрузки метода GetEvents. Нас интересует атрибут custom, который говорит, что этот метод — реализация .NET-метода Assembly.GetEvents и calling convention (_stdcall). Если мы оставим все так, как в сыром IDL, компилятор будет ругаться, потому что:

1️⃣ В IDL не пишут _stdcall: это появится в сгенерированном .h.

2️⃣ Атрибуты метода (включая custom(...)) должны быть только в квадратных скобках перед возвращаемым типом метода (в нашем случае — HRESULT).

Поэтому меняем содержимое на следующее:

[custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "GetEvents")]
HRESULT GetEvents_2([in] BindingFlags bindingAttr, [out, retval] SAFEARRAY(_EventInfo*)* pRetVal);


Далее воспользуемся командой для сборки:

midl /h appdomain.h appdomain.idl

👍 Если вы все сделали правильно и сборка прошла успешно, вывод будет выглядеть так, как на скриншоте 5.

Теперь у нас есть готовый хедер, который мы отправим в IDA. Но сначала в хедер-файл добавим инклюды (до содержимого appdomain.h), чтобы IDA clang знал все имена и не ругался на атрибуты или макросы (скриншот 6):

После этого загружаем файл в IDA: File → Load file → Parse C header file…

IDA использует встроенный clang для преобразования C-заголовков в базу типов IDA. Соответственно, в Options → Compiler нужно указать include-пути, чтобы clang видел стандартные заголовки (пути к стандартным хедерам Windows SDK). Обычно это выглядит так:

-target x86_64-pc-win32
-x c++
-std=c++11
-I"C:\Program Files (x86)\Windows Kits\10\Include\<version>\ucrt"
-I"C:\Program Files (x86)\Windows Kits\10\Include\<version>\um"
-I"C:\Program Files (x86)\Windows Kits\10\Include\<version>\shared"
-I"C:\Program Files (x86)\Windows Kits\10\Include\<version>\winrt"
-I"C:\Program Files (x86)\Windows Kits\10\Include\<version>\cppwinrt"


После в Local Types появятся методы _AppDomain, _Type и другие (скриншот 7).

👀 На скриншоте 8 мы видим вызовы двух методов интерфейса _Type. Делаем encr_resource указателем на структуру _Type (ее vtable мы видели на скриншоте 7) и понимаем, какие методы вызываются (скриншот 9). Все аргументы схлопнулись под правильной сигнатурой, которую нам не нужно прописывать вручную.

#tip #malware #reverse
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍11🤩9
Не сегодня 😑

@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
😁24👍4😱4😭3👏2👌1🌚1😎1
Curing a problem 🔧

Недавно исследователи из ARMO представили статью и PoC вредоносного ПО Curing, которое использует интерфейс io_uring для обхода мониторинга файловых и сетевых операций, осуществляемого через системные вызовы.

🧐 Для начала расскажем о самом интерфейсе io_uring. Он появился в версии ядра 5.1 для выполнения асинхронных операций ввода-вывода. До него существовал интерфейс Linux AIO, который тоже предлагал асинхронный ввод-вывод, но имел ряд недостатков. Интерфейс io_uring разрабатывался с учетом этого и предлагает сокращение издержек, связанных с выполнением соответствующих системных вызовов, минуя их, а также реализует сам обмен данными внутри ядра, сокращая переключение контекста между ядром и пользовательским пространством (user-space). Для ввода-вывода используются два кольцевых буфера: очередь отправки (Submission Queue, SQ) и очередь завершения (Completion Queue, CQ), которые используются для постановки операций в очередь и получения результатов соответственно.

🪞 Для примера будем использовать упомянутый выше PoC Curing. Он производит чтение файла /etc/shadow и отправку его на сервер, все это средствами io_uring. Поэтому нет смысла настраивать auditd или другое средство аудита, использующее для мониторинга системные вызовы, так как после настройки интерфейса эти операции будут осуществляться в обход сисколов. В связи с этим для демонстрации аудита будет использоваться Tetragon — готовый движок на базе eBPF с возможностью гибко настраивать политики мониторинга через механизм TracingPolicy. Используя механизм привязки kprobes, мы можем подключиться к любой функции ядра для аудита. Существуют и другие интерфейсы, которые можно использовать для аудита доступа к файлам, например fanotify, но Tetragon универсальнее.

Тут стоит отметить, что средства, отслеживающие системные вызовы, не совсем бесполезны в этом случае: они все еще могут перехватывать вызовы функций io_uring_setup и io_uring_enter, используемых для создания и взаимодействия с экземпляром интерфейса io_uring. В этом случае мы будем видеть, что приложение выполняет действия с этим интерфейсом, но подробности операции и ее параметры получить мы не можем. С этим уже можно работать и помечать подобную активность как подозрительную, так как обычно приложения не опираются на io_uring, а легитимных пользователей этого интерфейса можно без особых проблем занести в белый список. Отсюда сам факт обращения к интерфейсу будет подозрительным поведением.

🫥 Но в нашем случае нам требуется постоянный мониторинг файлов или сокетов. Поэтому составим простую политику для мониторинга файлов через LSM-хук security_file_permission (скриншот 1, скопировать код). Сама функция принимает два аргумента: путь к файлу и запрашиваемые разрешения в виде битовой маски, поэтому в политике через оператор Equal ищем файл по полному пути, а в маске через оператор Mask фильтруем по цифре 4, что означает доступ на чтение. И в результате получаем событие (скриншот 2), когда Curing пытается прочитать файл.

Аналогично можно отследить соединение с сервером: в политике (скриншот 3, скопировать код) используем функцию ядра tcp_connect для получения аргумента sock в ней, где будет вся сетевая информация. Тут у нас нет вводных для фильтрации, и мы увидим все TCP-соединения, так как порт сервера можно переназначить, но тут нам важнее сам факт возможности перехватить событие (скриншот 4) — как мы видим, Curing подключается к своему стандартному порту 8888.

Пусть io_uring и предоставляет обход системных вызовов, но, используя правильные инструменты, его можно перехватить без особых проблем.

#tip #news
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥115👍5
Злоумышленники скомпрометировали десятки NPM-пакетов на ~2 млрд скачиваний 🐾

Что произошло

В рамках фишинговой рассылки был скомпрометирован мейнтейнер Josh "Qix" Junon.

Ему и еще нескольким разработчикам пришло письмо с просьбой обновить второй фактор, так как прошло 12+ месяцев с последнего изменения (скриншоты 1, 2, 3). Письмо пришло с ящика, имитирующего официальный ([email protected]). 🐱

Qix является мейнтейнером больших проектов в экосистеме NPM, среди которых:

🟢chalk (882 форка и 22.7к звезд на GitHub, 313 млн. скачиваний в NPM за последнюю неделю);
🟢debug (957 форков, 11.3к звезд, 372 млн. скачиваний);
🟢strip-ansi (272 млн. скачиваний);
🟢wrap-ansi (206 млн. скачиваний);
🟢has-flag (200 млн. скачиваний).

Проверить, что атака вас не затронула

Вооружитесь osv-scanner. Информация о вредоносных пакетах уже есть в базе osv.dev.

Можно воспользоваться пользовательским скриптом или проверить перечисленные там пакеты самостоятельно (npm ls, yarn why, pnpm why).

Рекомендации для мейнтейнеров

1. Если вам приходится логиниться по ссылкам из писем — проверяйте URL. Помните, что вы — лакомая цель для злоумышленников.

2. Используйте второй фактор. Даже если злоумышленник сможет его выманить фишинговой страницей авторизации, то ему придется как-то получать его вновь и вновь, если у вас 2FA стоит в режиме Authorization and writes (подтверждение всех чувствительных действий, в т.ч. публикация новой версии пакета, режим включен по умолчанию).

3. Ознакомьтесь с практиками OIDC/"trusted publishing" — так вы усложните цель злоумышленнику, ведь ему придется захватить публичный CI/репозиторий для осуществления атаки.

Рекомендации для разработчиков

1. Фиксируйте зависимости. Не допускайте, чтобы пакетный менеджер просто тянул последний релиз используемых вами зависимостей.

2. Добавьте аудит зависимостей (для начала может подойти и osv-scanner) — так вы сможете узнать о проблемах на этапе сканирования зависимостей, а не из новостей.

Рекомендации для AppSec

Вы и без нас все знаете:

1. Настройте внутренний прокси с поддержкой карантина для внутренних проектов.

2. Убедитесь, что ваши разработчики ходят на внутреннее прокси, а не берут пакеты из глобальных репозиториев. 🐱

Stay safe 👍
#npm #supplychain #appsec
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥11😁71🐳1
How to CVE-2025-54916? Low-effort vulnerability research 💻

Привет, на связи ESC-VR.

Формат поста в телеграме редко подходит для разборов комплексных уязвимостей, но баг, найденный нами в недрах NTFS, исправленный сентябрьским патчем, можно было найти весьма необычным способом (и мы смогли уложить рассказ об этом в пост).

Если вы интересуетесь анализом уязвимостей, наверняка слышали про CodeQL, SonarQube, Snyk, Semgrep — классические SAST-системы. Их общий минус: чаще всего нужен полный доступ к исходникам. Когда его нет, ценность таких инструментов быстро стремится к нулю, а сложность запросов мешает применять их к декомпилированным листингам или фрагментам кода.

Нужно что-то простое, с понятным языком запросов и без требования полной кодовой базы. Такое решение есть — это weggli-rs: интерактивная, консольная утилита для выполнения семантического поиска. Она подходит для поиска по декомпилированным листингам и частичным кодовым базам.

Что мы называем «частичными кодовыми базами»? Например, утекшие исходники Windows XP SP1, слитые в 2020 году. Несмотря на возраст, это бесценный источник знаний о внутренностях современной Windows.

🎯 Наша цель: найти классические переполнения стека через вызовы memcpy/memmove. Ищем функцию, где:

• на стеке объявлен буфер;
• есть вызов memcpy/memmove;
• в первый аргумент передается адрес этого стекового буфера.

Этого достаточно, чтобы собрать множество кандидатов на stack buffer overflow (не все, но многие). Запрос на weggli:

weggli -R "$func=RtlCopyMemory|memmove|memcpy" "_ $v; $func(&$v,_,_)"


Дальше нужно сужать выборку. Например, требуем, чтобы размер копируемого буфера задавался выражением с вычитанием. Таким образом мы подсвечиваем места с риском целочисленного underflow:

weggli.exe -R "$func=RtlCopyMemory|memmove|memcpy" "_ $v; $func(&$v,_,_(_-_))"


Уязвимость, закрытую в сентябре, можно было подсветить таким запросом:

weggli -R "$func=RtlCopyMemory|memmove|memcpy" "_ $v; $func(&$v,_,_($a->$b))


В данном шаблоне мы ищем все функции, в которых:

• на стеке объявлен буфер;
• есть вызов memcpy/memmove;
• в первый аргумент передается адрес этого стекового буфера;
• размер копируемого буфера определяется полем какой бы то ни было структуры.

В заключение мы призываем вас попробовать использовать weggli-rs и найти исправленную уязвимость в исходном коде Windows XP SP1.

HINT: кажется, искать нужно в base/fs, а в названии уязвимой функции было что-то связанное с записью в лог или еще куда 😏

А если вы хотите узнать, как стриггерить эту уязвимость, то ознакомьтесь с нашим предыдущим исследованием, опубликованным в блоге PT SWARM.

#escvr #cve #win
@ptescalator
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍108💯1