
Обфускатор x64-двоичных файлов PE с уплощением потока управления, защитой от дизассемблирования, обфускацией импорта и мутацией инструкций для затруднения обратной разработки.
Alcatraz — это обфускатор x64-двоичных файлов, способный обфусцировать различные PE-файлы, включая:
Установите: https://vcpkg.io/en/getting-started.html
asmjit: vcpkg.exe install asmjit:x64-windows
Zydis: vcpkg.exe install zydis:x64-windows
1.) Загрузите двоичный файл, нажав «file» в верхнем левом углу.
2.) Добавьте функции, развернув дерево «Functions». (Вы можете выполнить поиск, введя имя в строке поиска вверху)
3.) Нажмите «compile» (примечание: обфускация большого количества функций может занять несколько секунд)
В следующей демонстрации все возможности (кроме демонстрируемой) отключены.
Если непосредственное значение перемещается в регистр, мы обфусцируем его, применяя несколько побитовых операций. Рассмотрим популярную функцию _security_init_cookie.
До:
После:

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

Если мы передадим это в IDA 7.6, декомпилятор её оптимизирует:

Теперь сгладим её поток управления и снова проанализируем в IDA:

Как видите, сложность значительно возросла, хотя я показываю лишь небольшую часть сгенерированного кода. Если хотите увидеть, как выглядит граф потока управления:

Если регистр (например, RAX) добавляется к другому регистру (например, RCX), мы мутируем инструкцию. Это означает, что синтаксис изменяется, но семантика остаётся прежней.
Инструкция ADD RCX, RAX может быть мутирована в:
push rax
not rax
sub rcx, rax
pop rax
sub rcx, 1
Если хотите узнать больше о мутации, взгляните на perses.
Если PE-файл является .exe (поддержка .dll будет добавлена), мы создадим пользовательскую точку входа, которая расшифровывает реальную при запуске (!!! не работает при ручном маппинге).

Обфускация LEA довольно проста, но эффективна. Мы помещаем другой адрес в регистр и затем расшифровываем его. Таким образом, реверс-инженеры не могут перекрестно ссылаться на определённые данные/функции.
Допустим, мы находим следующую инструкцию: lea rcx, [0xDEAD]
Мы мутируем её в:
pushf
lea rcx, [1CE54]
sub rcx, EFA7
popf
rcx -> 0xDEAD
Если мы находим инструкцию, начинающуюся с байта 0xFF, мы помещаем перед ней 0xEB.
Мы делаем это, потому что 0xEB 0xFF кодируется как jmp rip + 1, что в итоге переходит к нашему фактическому первому 0xFF. Это сбивает с толку инструменты, декодирующие инструкции линейным образом.
До:

После:

Время от времени мы можем вставлять:
jz 3
jne 1
0xE8
IDA попытается декодировать 0xE8 (call), но безуспешно:

На данный момент нет «правильной» обфускации IAT. Об этом пока заботится трюк анти-дизассемблирования 0xFF. Правильная реализация запланирована здесь:
iat.cpp
Это фрагмент нашей функции main со всеми включенными возможностями, кроме анти-дизассемблирования (чтобы IDA могла создать функцию):
