
Обфускация конкретных Windows API с помощью других API
Обфусцируйте (скрывайте) импорты PE от средств статического/динамического анализа.
Это довольно просто. Допустим, я использовал VirtualProtect и хочу обфусцировать его с помощью Sleep. Инструмент изменит IAT так, что переход (thunk), указывающий на VirtualProtect, будет указывать на Sleep. При выполнении файла загрузчик Windows загрузит Sleep вместо VirtualProtect и передаст управление точке входа. Оттуда выполнение будет перенаправлено на шелл-код, который инструмент разместил ранее, чтобы найти адрес VirtualProtect и использовать его для замены адреса Sleep, который был назначен загрузчиком.
#include <cobf.hpp>
int main() {
cobf obf_file = cobf("sample.exe");
obf_file.load_pe();
obf_file.obf_sym("kernel32.dll", "SetLastError", "Beep");
obf_file.obf_sym("kernel32.dll", "GetLastError", "GetACP");
obf_file.generate("sample_obfuscated.exe");
obf_file.unload_pe();
return 0;
};
config.ini).cobf.exe <input file> <out file> [config file]; Template for the config file:
; * Sections can be written as:
; [dll_name]
; old_sym=new_sym
; * The dll name is case insensitive, but
; the old and the new symbols are not.
; * You can use the wildcard on both the
; dll name and the old symbol.
; * You can use '#' at the start of
; the old or the new symbol to flag
; an ordinal.
; * The new symbol should be exported
; by the dll so the windows loader can resolve it.
; For example:
; * Obfuscating all of the symbols
; imported from user32.dll with ordinal 1600.
[user32.dll]
*=#1600
; * Obfuscating symbols imported from both
; kernel32.dll and kernelbase.dll with Sleep.
[kernel*.dll]
*=Sleep
; * Obfuscating fprintf with exit.
[*]
fprintf=exit
Соберите этот пример кода
#include <windows.h>
#include <stdio.h>
int main() {
SetLastError(5);
printf("Last error is %d\n", GetLastError());
return 0;
};
После сборки импорты kernel32 выглядят так

Теперь давайте обфусцируем оба SetLastError и GetLastError с помощью Beep и GetACP (на самом деле подойдет любой API из kernel32, даже если он вообще не импортирован).
Используемые конфигурации:
[kernel32.dll]
SetLastError=Beep
GetLastError=GetACP
Вот вывод (также вы можете использовать библиотеку напрямую, как показано выше).

Снова взглянем на импорты kernel32

Нет упоминаний SetLastError или GetLastError
Подтверждение того, что оба файла будут работать корректно

Декомпилятор IDA HexRays

Отладчик IDA

Ghidra

ApiMonitor

Это связано с тем, что все инструменты статического анализа зависят от имени API, записанного в IAT, которым можно манипулировать, как показано.
Для ApiMonitor, из-за использования перехвата IAT, существует та же проблема.
С другой стороны, для таких инструментов, как x64dbg, отображаемые имена API будут зависеть только от того, что действительно вызывается (а не от того, что записано в IAT).

.cobf для хранения шелл-кода и других необходимых данных.git clone https://github.com/d35ha/CallObfuscator.