Вопрос Защита в реальном времени


Spectrum735

Просветленный
Просветленный
Регистрация
21.02.2019
Сообщения
271
Репутация
146
Приветствую всех! Зародилась идея реализовать некую защиту в реальном времени для своего детища от злых майнеров. Возможно это кому-то будет нужно. Какие задачи возлагаются на такую защиту:
1) В первую очередь скан процессов, тут вроде всё понятно, по сути это бесконечный цикл. Но тут возникает вопрос баланса между безопасностью и производительностью. Никто не захочет такое ПО, которое всё время что-то грузит. Как тут быть?
2) Скан реестра. Определённо майнеру захочется жить подольше и будет стучаться в автозагрузку. Проверка одной ветки недостаточно, путей пережить перезагрузку очень много. Тут возникает вопрос, что мониторить?
3) И на последок, скан файлов. Опять же все файлы сканить долго и бессмысленно, полагаю что сканировать нужно те, что были скачаны или появились недавно. По каким критериям будет детект уже буду думать на ходу. Может быть есть какие-то "подписки" на события?
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 101
Репутация
8 223
Привет!

1)Если делать бесконечный цикл, он не должен постоянно делать итерации, иначе займешь все свободное время CPU (Это ошибка называется busy loop).
Тут либо делать в цикле sleep сколько-то секунд, либо дожидаться какого-то события, например создания процесса.

2)Про автозагрузку, наверное достаточно мониторить основное: "Автозагрузка в реестре, ключи", "Планировщик", "Папка автозагрузки".

Вообще по вопросам 1-3, самое простое это сделать хуки на определенные функции, например при помощи MinHook или ещё что-то поискать.

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

Примерно так делают и EDR, и антивирусы, только там хуки сложнее и драйверные есть.

Я выкладывал статью про EDR:Малварь как искусство - Архитектура антивирусов и EDR - систем

Вот примерно тебе надо что-то сделать такое, но не ядерные хуки, а юзермодные...

По причине с ядерными хуками нужна подпись.
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 101
Репутация
8 223
Вообще можно ещё проще оказывается, вот что ответил ChatGPT.)

В C# вы можете отслеживать события, такие как создание файла, изменение ветки в реестре и создание процесса, используя различные методы. Один из способов - использовать классы из пространства имен System.IO, Microsoft.Win32 и System.Diagnostics. Вот примеры:

Создание файла:

C#:
using System;
using System.IO;

class Program
{
    static void Main()
    {
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = @"C:\путь\к\папке"; // Укажите путь к папке, которую нужно отслеживать
        watcher.Filter = "*.*"; // Отслеживать все файлы
        watcher.Created += OnFileCreated;
        watcher.EnableRaisingEvents = true;

        Console.WriteLine("Нажмите Enter для выхода.");
        Console.ReadLine();
    }

    private static void OnFileCreated(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"Создан файл: {e.FullPath}");
    }
}

Изменение ветки в реестре:

C#:
using System;
using Microsoft.Win32;

class Program
{
    static void Main()
    {
        RegistryKey key = Registry.CurrentUser;
        RegistryKey subKey = key.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion", true); // Укажите путь к отслеживаемой ветке
        subKey.ValueChanged += OnRegistryValueChanged;

        Console.WriteLine("Нажмите Enter для выхода.");
        Console.ReadLine();
    }

    private static void OnRegistryValueChanged(object sender, EventArgs e)
    {
        Console.WriteLine("Произошло изменение в реестре.");
    }
}

Создание процесса:

C#:
using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        ManagementEventWatcher watcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
        watcher.EventArrived += OnProcessStarted;
        watcher.Start();

        Console.WriteLine("Нажмите Enter для выхода.");
        Console.ReadLine();
    }

    private static void OnProcessStarted(object sender, EventArrivedEventArgs e)
    {
        string processName = e.NewEvent.Properties["ProcessName"].Value.ToString();
        Console.WriteLine($"Запущен процесс: {processName}");
    }
}

Попробуй, отпишись.)

Я не пробовал...)))
 

Spectrum735

Просветленный
Просветленный
Регистрация
21.02.2019
Сообщения
271
Репутация
146
Надо попробовать)
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 101
Репутация
8 223
Надо попробовать)
Да должно работать, т.к. в винде можно подписаться на события, функция CreateEvent, вот примеры на С++.)

Изменение ветки в реестре:
C++:
#include <iostream>
#include <Windows.h>

void OnRegistryValueChanged()
{
    std::cout << "Произошло изменение в реестре." << std::endl;
}

int main()
{
    HKEY hKey;
    LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_NOTIFY, &hKey);

    if (result != ERROR_SUCCESS)
    {
        std::cerr << "Ошибка при открытии ключа реестра." << std::endl;
        return 1;
    }

    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    result = RegNotifyChangeKeyValue(hKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, hEvent, TRUE);

    if (result != ERROR_SUCCESS)
    {
        std::cerr << "Ошибка при регистрации изменений в реестре." << std::endl;
        RegCloseKey(hKey);
        return 1;
    }

    WaitForSingleObject(hEvent, INFINITE);
    OnRegistryValueChanged();

    CloseHandle(hEvent);
    RegCloseKey(hKey);
    return 0;
}

Создание процесса:
C++:
#include <iostream>
#include <Windows.h>

void OnProcessStarted(LPWSTR lpProcessName)
{
    std::wcout << L"Запущен процесс: " << lpProcessName << std::endl;
}

int main()
{
    HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (hEvent == NULL)
    {
        std::cerr << "Ошибка при создании события." << std::endl;
        return 1;
    }

    HANDLE hProcess = CreateEventW(NULL, TRUE, FALSE, L"Global\\MyProcessStartEvent");

    if (hProcess == NULL)
    {
        std::cerr << "Ошибка при создании события для процесса." << std::endl;
        CloseHandle(hEvent);
        return 1;
    }

    HANDLE hThread = CreateThread(NULL, 0, [](LPVOID lpParam) -> DWORD
    {
        WaitForSingleObject((HANDLE)lpParam, INFINITE);
        OnProcessStarted(L"Процесс");
        return 0;
    }, hProcess, 0, NULL);

    if (hThread == NULL)
    {
        std::cerr << "Ошибка при создании потока." << std::endl;
        CloseHandle(hEvent);
        CloseHandle(hProcess);
        return 1;
    }

    WaitForSingleObject(hEvent, INFINITE);

    CloseHandle(hEvent);
    CloseHandle(hProcess);
    CloseHandle(hThread);
    return 0;
}

Создание файла:
C++:
#include <iostream>
#include <Windows.h>

void OnFileCreated(LPCWSTR lpFileName)
{
    std::wcout << L"Создан файл: " << lpFileName << std::endl;
}

int main()
{
    HANDLE hDir = CreateFile(L"C:\\путь\\к\\папке", FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

    if (hDir == INVALID_HANDLE_VALUE)
    {
        std::cerr << "Ошибка при открытии папки." << std::endl;
        return 1;
    }

    BYTE buffer[4096];
    DWORD dwBytesReturned;

    while (true)
    {
        if (ReadDirectoryChangesW(hDir, buffer, sizeof(buffer), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME,
            &dwBytesReturned, NULL, NULL))
        {
            FILE_NOTIFY_INFORMATION* pInfo = (FILE_NOTIFY_INFORMATION*)buffer;
            do
            {
                if (pInfo->Action == FILE_ACTION_ADDED)
                {
                    OnFileCreated(pInfo->FileName);
                }
                pInfo = (FILE_NOTIFY_INFORMATION*)((LPBYTE)pInfo + pInfo->NextEntryOffset);
            } while (pInfo->NextEntryOffset);
        }
       Sleep(1000); // Задержка в 1 секунду
    }

    CloseHandle(hDir);
    return 0;
}

Примечательно что при создании файла используется подход не ожидания события, а просто бесконечный цикл с чтением директории.)
 

Spectrum735

Просветленный
Просветленный
Регистрация
21.02.2019
Сообщения
271
Репутация
146
Проверил на каталогах, всё так как ожидалось. Но как узнать каким процессом был создан файл (или каталог)? GPT меня не понимает, или не хочет понимать
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 101
Репутация
8 223
Проверил на каталогах, всё так как ожидалось. Но как узнать каким процессом был создан файл (или каталог)? GPT меня не понимает, или не хочет понимать
А мне ответил, причём тот который бесплатный даже.)

Для того чтобы узнать, какой процесс создал файл, вы можете использовать класс System.Diagnostics.Process. Вот как можно модифицировать ваш код, чтобы он выводил имя процесса, создавшего файл:

C#:
using System;
using System.IO;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = @"C:\путь\к\папке"; // Укажите путь к папке, которую нужно отслеживать
        watcher.Filter = "*.*"; // Отслеживать все файлы
        watcher.Created += OnFileCreated;
        watcher.EnableRaisingEvents = true;

        Console.WriteLine("Нажмите Enter для выхода.");
        Console.ReadLine();
    }

    private static void OnFileCreated(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"Создан файл: {e.FullPath}");
        try
        {
            FileInfo fileInfo = new FileInfo(e.FullPath);
            using (Process process = Process.GetProcessById(GetProcessIdByFilePath(fileInfo.FullName)))
            {
                Console.WriteLine($"Создан процессом: {process.ProcessName}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ошибка при получении информации о процессе: {ex.Message}");
        }
    }

    private static int GetProcessIdByFilePath(string filePath)
    {
        var query = $"SELECT ProcessId FROM Win32_Process WHERE ExecutablePath = '{filePath.Replace("'", "''")}'";
        using (var searcher = new ManagementObjectSearcher(query))
        using (var results = searcher.Get())
        {
            var process = results.Cast<ManagementObject>().FirstOrDefault();
            if (process != null)
            {
                return Convert.ToInt32(process["ProcessId"]);
            }
            else
            {
                throw new Exception("Процесс не найден.");
            }
        }
    }
}
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 101
Репутация
8 223
Хотя судя по всему это находит процесс по имени пути файла, если он есть, не то-что нужно...

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

Да и не очень понятно зачем знать имя процесса ?
 

Spectrum735

Просветленный
Просветленный
Регистрация
21.02.2019
Сообщения
271
Репутация
146
@X-Shar, можно не имя, главно понимать какой процесс создает, чтобы знать легальный ли процесс колдует или нет, аля детект по поведению. Если вредоносный по базе - блокировать, если действия похожи на вредоносные - приостановить процесс, вывести окошко юзеру на выбор что делать.
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 101
Репутация
8 223
@X-Shar, можно не имя, главно понимать какой процесс создает, чтобы знать легальный ли процесс колдует или нет, аля детект по поведению. Если вредоносный по базе - блокировать, если действия похожи на вредоносные - приостановить процесс, вывести окошко юзеру на выбор что делать.
В юзермоде мне кажется врядли так можно, не делая уже хуков нужных функций в самом процессе.

Максимум по событиям можно определить что, что-то произошло, а дальше придется уже проверять вредоносный это файл или нет.
Тоже и с процессами.

Короче мне кажется так просто тут уже не сделать, если нужен прям поведенческий детект.)
 
Верх Низ