【逆向】Windows服务逆向分析调试
前言
本文主要对Windows服务进行简要介绍,并对服务程序分析方法进行记录。
名词解释
1 服务进程: //通过服务方式运行的可执行程序 2 服务控制程序: //所有用于启动服务(StartService())的程序,Windows中可以使用“services.msc”命令启动 3 服务控制管理器: //SCM(Service Control Manager),Windows中其实就是services.exe或者svchost.exe进程 4 5 服务Main函数: //注册服务控制处理函数、设置服务运行状态、执行其它操作。 6 服务控制处理函数: //SCM通过该回调函数设置服务运行状态。
启动流程
1、"服务控制程序" 调用StartService()启动服务,然后由SCM(services.exe)创建对应的 "服务进程"。 2、"服务进程" 在Main函数中调用StartServiceCtrlDispatcher()关联服务主线程,将 "服务Main函数" 地址提交给SCM。 3、SCM调用 "服务Main函数"。 4、"服务Main函数" 调用RegisterServiceCtrlHandler()注册 "服务控制处理函数",然后调用SetServiceStatus()设置服务运行状态。
示例代码
1 #include <windows.h> 2 #include <tchar.h> 3 #include <stdio.h> 4 5 #define SVCNAME L"SvcTest" 6 7 VOID InstallService(LPCTSTR szSvcName, LPCTSTR szPath); 8 VOID UninstallService(LPCTSTR szSvcName); 9 VOID WINAPI SvcMain(DWORD argc, LPCTSTR *argv); 10 VOID WINAPI SvcCtrlHandler( DWORD dwCtrl ); 11 12 SERVICE_STATUS_HANDLE g_hServiceStatusHandle = NULL; 13 SERVICE_STATUS g_ServiceStatus = {SERVICE_WIN32_OWN_PROCESS, 0, 0xFF, 0, 0, 0, 0}; 14 15 //Main 16 void _tmain(int argc, TCHAR *argv[]) 17 { 18 TCHAR szPath[MAX_PATH] = {0,}; 19 SERVICE_TABLE_ENTRY DispatchTable[] = 20 { 21 { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain }, 22 { NULL, NULL } 23 }; 24 25 //作为服务进程启动 26 if( argc == 1 ) 27 { 28 //关联服务主线程,将"服务Main函数"地址提交给SCM 29 if (!StartServiceCtrlDispatcher( DispatchTable )) 30 { 31 _tprintf(L"StartServiceCtrlDispatcher() failed!!! [%d]\n", 32 GetLastError()); 33 } 34 } 35 //作为服务安装卸载程序启动 36 else if( argc == 2 ) 37 { 38 if( !GetModuleFileName(NULL, szPath, MAX_PATH) ) 39 { 40 _tprintf(L"GetModuleFileName() failed! [%d]\n", 41 GetLastError()); 42 return; 43 } 44 45 if( _tcsicmp(argv[1], L"install") == 0 ) 46 { 47 //安装服务 48 InstallService(SVCNAME, szPath); 49 return; 50 } 51 else if( _tcsicmp(argv[1], L"uninstall") == 0 ) 52 { 53 //卸载服务 54 UninstallService(SVCNAME); 55 return; 56 } 57 else 58 { 59 _tprintf(L"Wrong parameters!!!\n"); 60 } 61 } 62 63 _tprintf(L"\nUSAGE : %s <install | uninstall>\n", argv[0]); 64 } 65 66 //创建服务 67 VOID InstallService(LPCTSTR szSvcName, LPCTSTR szPath) 68 { 69 SC_HANDLE schSCManager = NULL; 70 SC_HANDLE schService = NULL; 71 DWORD dwError = 0; 72 73 schSCManager = OpenSCManager( 74 NULL, // local computer 75 NULL, // ServicesActive database 76 SC_MANAGER_ALL_ACCESS); // full access rights 77 if( NULL == schSCManager ) 78 { 79 _tprintf(L"InstallService() : OpenSCManager failed (%d)\n", GetLastError()); 80 return; 81 } 82 83 schService = CreateService( 84 schSCManager, // SCM database 85 szSvcName, // name of service 86 szSvcName, // service name to display 87 SERVICE_ALL_ACCESS, // desired access 88 SERVICE_WIN32_OWN_PROCESS, // service type 89 SERVICE_DEMAND_START, // start type 90 SERVICE_ERROR_NORMAL, // error control type 91 szPath, // path to service's binary 92 NULL, // no load ordering group 93 NULL, // no tag identifier 94 NULL, // no dependencies 95 NULL, // LocalSystem account 96 NULL); // no password 97 if( NULL == schService ) 98 { 99 dwError = GetLastError(); 100 _tprintf(L"InstallService() : CreateService failed (%d)\n", dwError); 101 if( ERROR_SERVICE_EXISTS == dwError ) 102 _tprintf(L" -> The specified service already exists.\n"); 103 goto _EXIT; 104 } 105 106 _tprintf(L"InstallService() : Service installed successfully\n"); 107 108 _EXIT: 109 if( schService ) CloseServiceHandle(schService); 110 if( schSCManager) CloseServiceHandle(schSCManager); 111 } 112 113 //卸载服务 114 VOID UninstallService(LPCTSTR szSvcName) 115 { 116 SC_HANDLE schSCManager = NULL; 117 SC_HANDLE schService = NULL; 118 SERVICE_STATUS ss = {0,}; 119 DWORD dwError = 0; 120 121 schSCManager = OpenSCManager( 122 NULL, // local computer 123 NULL, // ServicesActive database 124 SC_MANAGER_ALL_ACCESS); // full access rights 125 if( NULL == schSCManager ) 126 { 127 _tprintf(L"UninstallService() : OpenSCManager failed (%d)\n", GetLastError()); 128 return; 129 } 130 131 schService = OpenService( 132 schSCManager, // SCM database 133 szSvcName, // name of service 134 SERVICE_INTERROGATE | 135 DELETE); // need delete access 136 if( NULL == schService ) 137 { 138 dwError = GetLastError(); 139 if( dwError != ERROR_SERVICE_DOES_NOT_EXIST ) 140 _tprintf(L"UninstallService() : OpenSCManager failed (%d)\n", dwError); 141 142 goto _EXIT; 143 } 144 145 ControlService(schService, SERVICE_CONTROL_INTERROGATE, &ss); 146 if( ss.dwCurrentState != SERVICE_STOPPED ) 147 { 148 _tprintf(L" -> Service is running! Stop the service!!!\n"); 149 goto _EXIT; 150 } 151 152 if( !DeleteService(schService) ) 153 _tprintf(L"UninstallService() : DeleteService failed (%d)\n", GetLastError()); 154 else 155 _tprintf(L"Service uninstalled successfully\n"); 156 157 _EXIT: 158 if( schService ) CloseServiceHandle(schService); 159 if( schSCManager ) CloseServiceHandle(schSCManager); 160 } 161 162 //服务Main(设置服务控制处理函数,修改服务运行状态) 163 VOID WINAPI SvcMain(DWORD argc, LPCTSTR *argv) 164 { 165 // Service Control Handler 166 g_hServiceStatusHandle = RegisterServiceCtrlHandler( 167 SVCNAME, 168 SvcCtrlHandler); 169 if( !g_hServiceStatusHandle ) 170 { 171 OutputDebugString(L"RegisterServiceCtrlHandler() failed!!!"); 172 return; 173 } 174 175 // Service Status -> SERVICE_RUNNING 176 g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; 177 SetServiceStatus(g_hServiceStatusHandle, &g_ServiceStatus); 178 179 // Print debug string 180 while( TRUE ) 181 { 182 OutputDebugString(L"[SvcTest] service is running..."); 183 Sleep(3 * 1000); // 3 sec 184 } 185 } 186 187 //服务控制处理函数 188 VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) 189 { 190 switch(dwCtrl) 191 { 192 //根据SCM传递过来的参数修改服务运行状态 193 case SERVICE_CONTROL_STOP: 194 g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; 195 SetServiceStatus(g_hServiceStatusHandle, &g_ServiceStatus); 196 197 g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; 198 SetServiceStatus(g_hServiceStatusHandle, &g_ServiceStatus); 199 200 OutputDebugString(L"[SvcTest] service is stopped..."); 201 break; 202 203 default: 204 break; 205 } 206 }
服务调试
1、直接设置EIP到服务Main函数
2、修改服务进程入口点代码为死循环,附加后改回原代码,继续往下调试