
загрузчик PE и трассировщик Windows API. Полезен при анализе вредоносного ПО.
Этот проект был создан для упрощения процесса анализа вредоносного ПО. Цель — создать бинарник-активатор, который загружает заданный пользователем бинарник и отслеживает его выполнение с помощью хуков Win32 API. Соответствующие данные сохраняются на диск. Код поддерживает как x86, так и x64 бинарники.
Я написал пост в блоге, объясняющий, как это работает: http://antonioparata.blogspot.com/2022/06/thematrix-process-inspection-tool-aimed.html
Для мониторинга нового бинарника необходимо создать активатор. Активатор загружает и отслеживает заданный пользователем бинарник. Для создания активатора используйте опцию -add. Пример использования:
c:\>TheMatrix.exe -add c:\path\to\my\binary.dll
Файл активатора создан
c:\>regsvr32.exe TheMatrix.build.dll
Эта команда создаст новый PE-файл, представляющий активатор. Активатор будет иметь тот же формат (DLL или EXE), что и исходный бинарник.
После создания вы можете запустить его любым удобным способом (для DLL рекомендуется использовать утилиту rundll32.exe).
Во время выполнения данные, сгенерированные отслеживаемыми функциями, сохраняются в ./Desktop/thematrix/[ID процесса]/ (это зависит от функции log_data, реализованной в utility.c).
Ограничения:
Проект изменяет структуру PEB.Ldr, чтобы некоторые API (например, GetModuleHandle, ...) работали корректно. Если запустить активатор в системе WOW64 (x86 бинарник на x64 ОС), изменяется только x86 PEB.Ldr (в процессах WOW64 существуют как x86, так и x64 PEB). Когда процессор переключается на x64, нативные Windows API (ntdll.dll) используют x64 версию PEB.Ldr. Это означает, что активатор может работать некорректно. Чтобы гарантировать правильную работу x86, запускайте бинарник на x86 ОС.
Созданный файл не экспортирует все методы и не содержит ресурсы исходного файла. Это может вызвать ошибки, например, если DLL вызывает GetModuleFileName -> LoadLibrary -> FindResource. Этот код загрузит оригинальную DLL TheMatrix, которая не содержит нужного ресурса.
Добавление новых функций для мониторинга — простая задача. Посмотрите на файл hooks.c для примеров хуков Kernel32.dll и bcrypt.dll. Чтобы добавить новый хук, достаточно вызвать функцию hook_add. Ниже показан пример создания хука:
LPVOID __stdcall hook_BCryptEncrypt(BCRYPT_KEY_HANDLE hKey, PUCHAR pbInput, ULONG cbInput, VOID* pPaddingInfo, PUCHAR pbIV, ULONG cbIV, PUCHAR pbOutput, ULONG cbOutput, ULONG* pcbResult, ULONG dwFlags)
{
// сохранить открытые данные
if (cbInput) {
char name[MAX_PATH] = { 0 };
snprintf(name, sizeof(name), "BCryptEncrypt_%llx_%d", (uint64_t)pbInput, cbInput);
log_data(cbInput, pbInput, name);
}
LPVOID ret = call_original(
hKey,
pbInput,
cbInput,
pPaddingInfo,
pbIV,
cbIV,
pbOutput,
cbOutput,
pcbResult,
dwFlags
);
return ret;
}
hook_add("Bcrypt.dll", "BCryptEncrypt", hook_BCryptEncrypt);
Функция должна иметь ту же сигнатуру, что и перехватываемая функция. Функция call_original используется для вызова оригинальной функции. Достаточно передать ей те же входные параметры, что и у оригинальной функции — фреймворк сам выполнит всю сложную работу, чтобы вызвать правильную функцию ;) Вызов call_original должен выполняться в том же потоке, который исполняет хук, иначе процесс упадёт.