• VLMI - форум по обмену информацией. На форуме можете найти способы заработка, разнообразную информацию по интернет-безопасности, обмен знаниями, курсы/сливы.

    После регистрации будут доступны основные разделы.

    Контент форума создают пользователи, администрация за действия пользователей не несёт ответственности, отказ от ответственности. Так же перед использованием форума необходимо ознакомиться с правилами ресурса. Продолжая использовать ресурс вы соглашаетесь с правилами.
  • Подпишись на наш канал в Telegram для информации о актуальных зеркалах форума: https://t.me/vlmiclub

Системный/неубиваемый процесс (службы на c++)

HideMan

Участник
Сообщения
12
Реакции
38
0 руб.
Telegram
Давненько не было статей, но это не потому что я забил. Просто нужно было набрать немного материалов и идей для написания. Знаете бывает у нас программеров такой «творческий кризис». Думаю скоро пройдет, но в это время буду по немногу продолжать писать.

services-icon.png

Вся информация предоставляется исключительно в ознакомительных целях. Автор не несет ответственности за любой возможный вред причиненный материалами данной статьи.
Ну в общем добрый вечер =)
Раньше меня многие спрашивали как поднять процесс до системного, сейчас смотрю все уже забили на этот вопрос. Но так как мейнстримом это не стало, думаю пора приоткрыть занавес и показать один из нескольких способов, и объяснить некоторые нюансы.

Система Windows так устроена что запустить процесс с определенными привилегиями может только процесс (или пользователь) имеющий не меньшие привилегии. То есть по сути мы не система а всего лишь (максимум) администратор и запустить процесс мы можем только с правами администратора.
Но как заставить систему запускать процесс саму?
В этом нам помогут службы windows.
Их система запускает сама и выполняются они от имени системы, это дает нам некоторое поле для маневров. Например как я уже говорил что только системный процесс может запустить другой процесс с системными правами (не будем брать в учет некоторые баги\фичи винды).

Сегодня мы напишем службу которая будет запускать наш процесс и следить чтобы его некто не смог закрыть (если кто не знал то системные процессы тоже можно закрывать).

Создаем новый проект и пишем нашу функцию мейн (в случае сервиса у нас будет SvcMain) и дополнительные функции для установки и удаления сервиса.
C++:
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <array>
#include <string>

#pragma comment(lib, "advapi32.lib")

#define SVCNAME TEXT("MicrosoftAlphaVite4")

SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;

VOID SvcInstall(void);
VOID SvcUninstall(void);
VOID SvcWork(void);
VOID WINAPI SvcCtrlHandler(DWORD);
VOID WINAPI SvcMain(DWORD, LPTSTR *);

VOID ReportSvcStatus(DWORD, DWORD, DWORD);
VOID SvcInit(DWORD, LPTSTR *);

void __cdecl _tmain(int argc, TCHAR *argv[])
{
    if (lstrcmpi(argv[1], TEXT("install")) == 0)
    {
        SvcInstall();
        return;
    }
    else if (lstrcmpi(argv[1], TEXT("uninstall")) == 0)
    {
        SvcUninstall();
        return;
    }

    SERVICE_TABLE_ENTRY DispatchTable[] =
    {
        { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
        { NULL, NULL }
    };


    if (!StartServiceCtrlDispatcher(DispatchTable))
    {
    }
}

VOID SvcInstall()
{
    SC_HANDLE schSCManager;
    SC_HANDLE schService;

    TCHAR szPath[MAX_PATH];
    if (!GetModuleFileName(NULL, szPath, MAX_PATH))
    {
        return;
    }

    schSCManager = OpenSCManager(
        NULL,                 
        NULL,                
        SC_MANAGER_ALL_ACCESS);

    if (NULL == schSCManager)
    {
        return;
    }

    schService = CreateService(
        schSCManager,              // SCM database
        SVCNAME,                   // name of service
        SVCNAME,                   // service name to display
        SERVICE_ALL_ACCESS,         // desired access
        SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type
        SERVICE_AUTO_START,       // start type
        SERVICE_ERROR_NORMAL,       // error control type
        szPath,                    // path to service's binary
        NULL,                      // no load ordering group
        NULL,                      // no tag identifier
        NULL,                      // no dependencies
        NULL,                      // LocalSystem account
        NULL);                     // no password

    if (schService == NULL)
    {
        CloseServiceHandle(schSCManager);
        return;
    }

    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
}


VOID SvcUninstall(void)
{
    SC_HANDLE schSCManager;
    SC_HANDLE schService;

    schSCManager = OpenSCManager(
        NULL,              
        NULL,                   
        SC_MANAGER_ALL_ACCESS); 

    if (NULL == schSCManager)
    {
        return;
    }

    schService = OpenService(
        schSCManager,
        SVCNAME,      
        DELETE);   

    if (schService == NULL)
    {
        CloseServiceHandle(schSCManager);
        return;
    }

    if (!DeleteService(schService));

    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
}

VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
    gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME, SvcCtrlHandler);
    if (!gSvcStatusHandle)
    {
        return;
    }

    gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    gSvcStatus.dwServiceSpecificExitCode = 0;

    ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);

    SvcInit(dwArgc, lpszArgv);
}

VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv)
{
    ghSvcStopEvent = CreateEvent(
        NULL,   
        TRUE, 
        FALSE,
        NULL);

    if (ghSvcStopEvent == NULL)
    {
        ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
        return;
    }

    ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);

    while (TRUE)
    {
        SvcWork();

        WaitForSingleObject(ghSvcStopEvent, INFINITE);

        ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
        return;
    }
}

VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
    static DWORD dwCheckPoint = 1;


    gSvcStatus.dwCurrentState = dwCurrentState;
    gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
    gSvcStatus.dwWaitHint = dwWaitHint;

    if (dwCurrentState == SERVICE_START_PENDING)
        gSvcStatus.dwControlsAccepted = 0;
    else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

    if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
        gSvcStatus.dwCheckPoint = 0;
    else gSvcStatus.dwCheckPoint = dwCheckPoint++;

    SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
}

VOID WINAPI SvcCtrlHandler(DWORD dwCtrl)
{

    switch (dwCtrl)
    {
    case SERVICE_CONTROL_STOP:
        ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);


        SetEvent(ghSvcStopEvent);
        ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);

        return;

    case SERVICE_CONTROL_INTERROGATE:
        break;

    default:
        break;
    }
}

Создаем файл work.cpp и пишем код который будет выполнять наша служба.

C++:
#include <windows.h>
#include <tchar.h>
#include <wtsapi32.h>
#include <userenv.h>
#include <stdio.h>
#include <direct.h>
#include <iostream>
#include <array>
#include <string>

#pragma comment(lib, "wtsapi32")
#pragma comment(lib, "userenv")


//функция поиска процесса
int GetProcessByName(const char* process_name)
{
    WTS_PROCESS_INFO* pWPIs = NULL;
    DWORD dwProcCount = 0;
    if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
    {
        //Go through all processes retrieved
        for (DWORD i = 0; i < dwProcCount; i++)
        {
            if (_stricmp(pWPIs[i].pProcessName, process_name) == 0)
            {
                return 1;
            }
            //pWPIs[i].pProcessName = process file name only, no path!
            //pWPIs[i].ProcessId = process ID
            //pWPIs[i].SessionId = session ID, if you need to limit it to the logged in user processes
            //pWPIs[i].pUserSid = user SID that started the process
        }
    }

    //Free memory
    if (pWPIs)
    {
        WTSFreeMemory(pWPIs);
        pWPIs = NULL;
    }
    return 0;
}
VOID SvcWork()
{
    std::string systemDrive = getenv("SystemDrive");
    systemDrive = systemDrive + "\\";
    _chdir(systemDrive.c_str());


    //выполняем цикл пока процесс не будет запущен

    HANDLE hToken = NULL;
    DWORD dwSessionId = WTSGetActiveConsoleSessionId();

    WTSQueryUserToken(dwSessionId, &hToken);

    while (true)
    {

        if (GetProcessByName("svc_worker.exe") == 0)
        {

            STARTUPINFO si;
            ZeroMemory(&si, sizeof(STARTUPINFO));
            si.cb = sizeof(STARTUPINFO);
            si.lpDesktop = TEXT("winsta0\\default");

            si.dwFlags = STARTF_USESHOWWINDOW;
            si.wShowWindow = SW_SHOW;

            PROCESS_INFORMATION pi;
            ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

            PVOID lpEnvironment = NULL;
            CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE);

            LPTSTR szCmdline = _tcsdup(_T("\"svc_worker.exe\""));

            CreateProcessAsUser(hToken,
                NULL,
                szCmdline,
                NULL,
                NULL,
                FALSE,
                NORMAL_PRIORITY_CLASS | DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
                lpEnvironment,
                NULL,
                &si,
                &pi);
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
        }

        Sleep(5000);
    }
    CloseHandle(hToken);
}
В данном файле мы ищем нужный нам процесс в цикле и если не находим то запускаем его (svc_worker.exe)
Таким образом мы не даем закрыть процесс.

Вы спросите зачем нам следить за файлом если процесс системный и закрыть его не даст сама система? Об этом чуть ниже…

Когда программа работает из под системы то функции типо получить директорию аппдата и т.д. получают путь не пользователя, а путь системной папки аппдата. Когда служба запускает наш ехе то автоматически директория работы нашей программы является C:\\windows\system32 процессы этой директории (если они системные) закрыть не получится, но если мы сменили рабочую директорию на директорию пользователя (например командой _chdir) то наш процесс хоть и работает от имени системы, но уязвим к закрытию из обычного диспетчера. Это кстати одна из особенностей работы из под системы.

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

Для запуска нашей службы достаточно открыть командную строку от имени администратора и выполнить команду «[название службы] install»

Либо написать отдельную программу для установки сервиса. Код самой установки есть в коде выше. Надеюсь разберетесь.

 
Последнее редактирование:

Fathak

Участник
Сообщения
68
Реакции
33
0 руб.
Большое спасибо за статью! Полезная и информативная статья. Я как раз давно интересовался вопросом создания не убиваемых процессов. Нужно для моего проекта.
 

deorex

Участник
Сообщения
17
Реакции
30
0 руб.
Спасибо, реально очень годно.
Можешь подсказать на каких ресурсах смотреть или искать подобное? Блуждаю по всяким статьям, но они за 2011 и старше года, грустно и неактуально.
 

HideMan

Участник
Сообщения
12
Реакции
38
0 руб.
Telegram
Спасибо, реально очень годно.
Можешь подсказать на каких ресурсах смотреть или искать подобное? Блуждаю по всяким статьям, но они за 2011 и старше года, грустно и неактуально.
В основном все новое это модификация старого. Чаще всего это личные наблюдения и разработки. Но как ресурс могу посоветовать хабр. Из книг посоветовал бы почитать не по програмированию а про внутреннему устройству винды, дает общее понимание.
 
Сверху Снизу