Статья Как спрятать процесс в Windows? Используем не документированные функции в API

Создание процессов в Windows — важный аспект операционной системы, позволяющий выполнять различные программы и задачи. Процессы создаются для выполнения программного кода, что позволяет операционной системе и пользователю выполнять несколько задач одновременно. Рассмотрим, как и зачем создаются процессы в Windows.

Информация предоставлена исключительно в ознакомительных целях

Сначала немного теории

Как создаются процессы в Windows​

Процессы в Windows создаются с помощью функции CreateProcess. Эта функция запускает новый процесс, который может выполнять другую программу или задачу. Рассмотрим пример создания процесса на языке C++
C++:
#include <windows.h>
#include <iostream>

void CreateNewProcess(const char* processName) {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    // Инициализация структуры STARTUPINFO
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // Создание нового процесса
    if (!CreateProcess(
        NULL,               // Имя исполняемого файла
        (LPSTR)processName, // Командная строка
        NULL,               // Указатель на структуру защиты процесса
        NULL,               // Указатель на структуру защиты потока
        FALSE,              // Унаследованные дескрипторы
        0,                  // Флаги создания процесса
        NULL,               // Указатель на блок окружения
        NULL,               // Текущий рабочий каталог
        &si,                // Указатель на структуру STARTUPINFO
        &pi)                // Указатель на структуру PROCESS_INFORMATION
    ) {
        std::cerr << "CreateProcess failed (" << GetLastError() << ").\n";
        return;
    }

    // Ожидание завершения процесса
    WaitForSingleObject(pi.hProcess, INFINITE);

    // Закрытие дескрипторов процесса и потока
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

int main() {
    const char* processName = "notepad.exe"; // Имя запускаемого процесса
    CreateNewProcess(processName);
    return 0;
}
Это стандартный метод создания процесса на C++, но есть и еще другие и одним из них является использование недокументированных возможностей. Что же это такое?
Недокументированные функции (англ. undocumented functions) — это функции в API операционной системы, которые не описаны в официальной документации, предоставляемой разработчиком системы (например, Microsoft для Windows). Они могут существовать по разным причинам, и их происхождение и использование имеют несколько аспектов.

Источники недокументированных функций​

  1. Внутренние потребности разработчиков:
    • Поддержка внутренней функциональности: Внутренние команды разработчиков операционных систем могут использовать эти функции для выполнения задач, которые не предназначены для общего использования. Эти функции могут быть необходимы для работы определенных системных компонентов или внутренних утилит.
    • Тестирование и отладка: Недокументированные функции могут использоваться для тестирования и отладки. Они позволяют разработчикам и инженерам получать доступ к низкоуровневым аспектам системы.
  2. Наследие и обратная совместимость:
    • Старое программное обеспечение: Некоторые недокументированные функции остаются в системе для обеспечения совместимости с устаревшими приложениями и драйверами, которые использовали эти функции в прошлых версиях ОС.
  3. Оптимизация производительности:
    • Специфические задачи: Эти функции могут быть оптимизированы для выполнения специфических задач быстрее или с меньшими затратами ресурсов, чем их документированные аналоги.

Методы обнаружения недокументированных функций​

  1. Реверс-инжиниринг:
    • Анализ двоичных файлов: Специалисты по безопасности и исследователи могут использовать инструменты для реверс-инжиниринга, такие как IDA Pro, чтобы исследовать исполняемые файлы и библиотеки Windows и находить недокументированные функции.
    • Декомпиляция: Декомпиляция бинарных файлов позволяет исследователям изучать машинный код и выявлять функции, которые не описаны в документации.
  2. Анализ утечек и ошибок:
    • Обратная связь и утечки: Недокументированные функции иногда могут стать известными через утечки информации или в результате изучения отчетов об ошибках, предоставляемых разработчикам.
  3. Исследования и публикации:
    • Исследовательские статьи и блоги: Исследователи часто публикуют свои находки в статьях, блогах и на специализированных форумах, делясь результатами своих исследований о недокументированных функциях.

Риски использования недокументированных функций​

  1. Несовместимость и нестабильность: Эти функции могут изменяться или исчезать в новых версиях операционной системы, что делает приложения, использующие их, уязвимыми к несовместимости.
  2. Отсутствие поддержки: Поскольку функции не документированы, разработчики не могут рассчитывать на поддержку или помощь при возникновении проблем.
  3. Безопасность: Использование недокументированных функций может представлять угрозу безопасности, так как они могут содержать уязвимости, не исправленные из-за их скрытого характера.
Если кому то интересно то вот ссылки для изучения:


Ну теперь можно перейти к практике.

Что нам понадобиться:
1.
2.
второй пункт нужен для того чтобы увидеть наш скрытый процесс ну и завершить его.
Мы будем использовать интересную функцию CreateHiddenProcess

Запускать будем конечно же блокнот)

открываем Visual Studio и создаем консольный проект на C++:
Снимок экрана 2024-07-17 120325.png
Жмем Далее, указываем куда сохранить проект и после этого откроется шаблонный файл проекта где будет функция main()
Снимок экрана 2024-07-17 124042.png
Удаляем все что там есть
Теперь пишем код:
C++:
#include <windows.h>
#include <iostream>

void CreateHiddenProcess(const char* processName) {
    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;

    if (CreateProcess(NULL, (LPSTR)processName, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        std::cout << "Process created successfully." << std::endl;
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    } else {
        std::cerr << "CreateProcess failed (" << GetLastError() << ")." << std::endl;
    }
}

int main() {
    const char* processName = "notepad.exe";
    CreateHiddenProcess(processName);
    return 0;
теперь прокомментирую каждую строку кода:
  • #include <windows.h>: Подключает заголовочный файл, который содержит объявления функций и типов данных Windows API.
  • #include <iostream>: Подключает заголовочный файл для работы с потоками ввода-вывода, такими как std::cout и std::cerr.
  • *void CreateHiddenProcess(const char processName)**: Объявление функции CreateHiddenProcess, которая принимает имя исполняемого файла в качестве аргумента.
  • STARTUPINFO si = { sizeof(si) }: Инициализация структуры STARTUPINFO и установка поля cb на размер структуры.
  • PROCESS_INFORMATION pi: Объявление структуры PROCESS_INFORMATION для хранения информации о процессе и его основном потоке.
  • si.dwFlags = STARTF_USESHOWWINDOW: Установка флага, указывающего на использование поля wShowWindow.
  • si.wShowWindow = SW_HIDE: Указание, что окно должно быть скрыто (не отображаться).
  • if (CreateProcess(NULL, (LPSTR)processName, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)): Вызов функции CreateProcess для создания нового процесса с заданными параметрами. Проверка возвращаемого значения для определения успешности вызова.
  • std::cout << "Process created successfully." << std::endl: Вывод сообщения об успешном создании процесса.
  • CloseHandle(pi.hProcess): Закрытие дескриптора процесса для освобождения системных ресурсов.
  • CloseHandle(pi.hThread): Закрытие дескриптора основного потока процесса для освобождения системных ресурсов.
  • else: Блок кода, выполняющийся в случае ошибки создания процесса.
  • std::cerr << "CreateProcess failed (" << GetLastError() << ")." << std::endl: Вывод сообщения об ошибке с кодом ошибки, возвращаемым функцией GetLastError.
  • int main(): Объявление функции main, точки входа в программу.
  • *const char processName = "notepad.exe"**: Задание имени исполняемого файла для создаваемого процесса. В данном случае это notepad.exe.
  • CreateHiddenProcess(processName): Вызов функции CreateHiddenProcess с аргументом processName.
  • return 0: Завершение функции main с кодом возврата 0, что означает успешное завершение программы.
Теперь жмем сборка в самом верху окна и жмем собрать решение или просто Ctrl+Shift+B.
В консоли вы должны увидеть
125525.png
Теперь идем в папку проекта и в папке Debug видим файл ВашПроект.exe, у меня это HideProcess.exe. Его можно запустить на своей машине или на виртуалке - без разницы. Ведь блокнот не причинит вреда).
запускаем и пробуем увидеть процесс Notepad.exe штатными средствами Windows. Процесс конечно же не найдется, но для этого у нас есть открываем и вводим в поиск название процесса Notepad.exe и видим
hide.png
завершить процесс можно отсюда же. На этом все, но если к статье будет интерес разговор про недокументированные возможности будет продолжен например про

NtQuerySystemInformation​

Эта функция используется для получения различной системной информации, которая не всегда доступна через обычные API. или про запуск процесса с привbлегиями System c помощью токена или много есть чего интересного.
Но помните
  • Безопасность: Использование недокументированных функций может нарушить стабильность системы и привести к уязвимостям в безопасности.
  • Совместимость: Эти функции могут изменяться между версиями Windows, что может привести к несовместимости.
  • Тестирование: Рекомендуется тестировать код в изолированной среде, например, в виртуальной машине.
Всем спасибо за внимание.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!