June 13, 2020

Пара строк про скрытие кода от антивирусов. Развеиваем мифы

Если вы почитаете эту статью:Малварь как искусство - Десяток трюков как обойти эмулятор антивируса и скрыть свой код

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

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

Ну во первых нормальные антивирусы вполне себе могут эмулировать и VirtualAllocExNuma (кстати в той статье были и ошибки в коде (поправил), также для работы нужно подключить и хидерники (гуглите сами, кому нужно)) и проверять выделение памяти, типо mallock.

Кстати про маллок, на самом деле он просто увеличивает размер виртуальной памяти, а free уменьшает размер виртуальной памяти по мере необходимости. :)

Например, рассмотрим приложение размером 64 K (включая размер bss) с начальным размером "кучи" равным 0. При этом используется от 0 до 64 К в виртуальной памяти (общий размер виртуальной памяти = 64 K + размер стека), как показано на Рисунке.

Рисунок Выделение памяти в "куче".

Теперь предположим, что приложение делает вызов malloc(4096). Это увеличит размер виртуальной памяти до 68 K, как показано на Рисунке. Фактическая физическая память выделяется только на фактическое время использования.

Когда-же это работает ?
В начале разберёмся что такое эмуляция кода ? По простому антивирус "исполняет" код и по шагам добирается до нашего "вредоносного кода", далее принимает решение о детекте используя сигнатуры и другие виды анализа (например количество определённых апи и т.д.).

Но понятно, что ресурсы антивируса ограничены, иначе-бы проверка одного файла занимала часы, а-то и проверка программы с например while (1), вообще могла повиснуть.

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

Этим и пользуются хакеры.

Но повторюсь, тут нужно не просто выделять память, а как-бы пользоваться ей.
Вот простой пример:
Код:

#define SIZE_MEM_MALLOC 1024*1024*1024
uint32_t *memdmp = NULL;
while(memdmp != NULL)
{
memdmp = malloc(SIZE_MEM_MALLOC);
memset(memdmp, 0x88, SIZE_MEM_MALLOC);        
free(memdmp);
err = bad_code(void);
if (!err) break;
}

В bad_code будет код, который хотим скрыть. В случае исполнения функции вернём ноль. Там также можно дополнительно что-то делать (вычисления и т.д.).

Ну-тут понятно, выделяем память, наполняем её значением 0x88. Далее освобождаем и вызываем функцию bad_code. Т.к. размер памяти слишком большой, большинство эмуляторов "частично" проэмулируют этот код и не доберутся до bad_code ! :)

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

Т.е. алгоритм примерно такой:

1)Выделить буфер маллоком, ну-ладно сжалимся и выделим 250 метров; :)

2)Заполним буфер мемсетом, неважно чем, я обычно люблю 0x55; :)

3)Создадим файл в темпе, или в папке с программой и запишем туда наш буфер, получим файл 250 метров с говном, я-бы даже на рандоме значения сделал, да-так лучше будет;

4)Выделяем новый буфер маллоком в 250 метров, считываем туда наш файл.

5)Проверяем область памяти из пункта два и пункта четыре. Например при помощи memcmp:

if (memcmp (src, dst, SIZE_MEM_MALLOC) == 0){//Выполняем свой код и чистим всё (Или наоборот как нужно, чистим всё и выполняем код)}

6)Если проверка не равна, то переходим в цикле на пункт один. Ну и не забывайте очищать память и закрывать/удалять файл. Ибо незачем хранить 250 метров говна, так-же как и такой объём памяти постоянно резервировать тоже плохо.

Я понимаю вирусы и т.д., но пожалейте своих жертв.

Всё на таком алгоритме отсеиваются все популярные антивирусы.

Всем удаче и не пишите локеры. :)