vc获取系统服务信息 收藏
对系统服务的管理几乎是木马必不可少的功能了,比如神气儿,上兴远程控制等 要是能我们给自己的木马加上这个功能,看着也不赖。我们实现的效果如图3-4所示 图3 图4
好啦,现在开始干活 取得配置权限 在对服务进行管理设置前,需要以相应的权限打开服务,可通过下面两个API实现 SC_HANDLE OpenSCManager( LPCTSTR lpMachineName, // pointer to machine name string LPCTSTR lpDatabaseName, // pointer to database name string DWORD dwDesiredAccess // type of access ); SC_HANDLE OpenService( SC_HANDLE hSCManager, // handle to service control manager // database LPCTSTR lpServiceName, // pointer to name of service to start DWORD dwDesiredAccess // type of access to service ); 通常我们以完全权限打开,示例代码如下: SC_HANDLE scm; SC_HANDLE service; if((scm=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))==NULL) { Printf("OpenSCManager Error\n"); } service=OpenService(scm,ServerName,SERVICE_ALL_ACCESS); if(!service) { Printf("OpenService error!\n"); } 这样就可以通过service句柄对服务进行各种操作了 枚举基本服务信息 想要对服务进行设置就需要知道服务的当前信息,对我们有用的通常是以下几项 服务名称,显示名称,启动状态,启动方式,程序路径等。 这些信息我们可以通过API函数EnumServicesStatus来实现,它的原形如下: BOOL EnumServicesStatus( SC_HANDLE hSCManager, // handle to service control manager database DWORD dwServiceType, // type of services to enumerate DWORD dwServiceState, // state of services to enumerate LPENUM_SERVICE_STATUS lpServices, // pointer to service status buffer DWORD cbBufSize, // size of service status buffer LPDWORD pcbBytesNeeded, // pointer to variable for bytes needed LPDWORD lpServicesReturned, // pointer to variable for number returned LPDWORD lpResumeHandle // pointer to variable for next entry ); 其中 LPENUM_SERVICE_STATUS lpServices是一个结构,它的原形如下: typedef struct _ENUM_SERVICE_STATUS { // ess LPTSTR lpServiceName; LPTSTR lpDisplayName; SERVICE_STATUS ServiceStatus; } ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS; 结构中包含服务名称,显示名称,启动状态。虽然它所返回的信息是及为有限的,但它是一次枚举所有服务信息 在要求不高的情况下,用它还是相当方便的,下面的示例代码可以枚举系统中所有服务的基本信息,代码如下: LPENUM_SERVICE_STATUS lpServices = NULL; DWORD nSize = 0; DWORD n; DWORD nResumeHandle = 0; lpServices = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, 64 * 1024); //注意分配足够的空间 EnumServicesStatus(scm,SERVICE_WIN32, SERVICE_STATE_ALL, (LPENUM_SERVICE_STATUS)lpServices, 64 * 1024, &nSize, &n, &nResumeHandle); for ( i = 0; i < n; i++) { Printf("服务名称: %s",lpServices[i].lpServiceName); Printf("显示名称: %s",lpServices[i].lpDisplayName); if ( lpServices[i].ServiceStatus.dwCurrentState!=SERVICE_STOPPED) { Printf("启动状态: 已启动\n"); } } 枚举详细服务信息 如果想得到更详细的服务信息,我们可以使用另一个API函数QueryServiceConfig 它的原形如下: BOOL QueryServiceConfig( SC_HANDLE hService, // handle of service LPQUERY_SERVICE_CONFIG lpServiceConfig, // address of service config. structure DWORD cbBufSize, // size of service configuration buffer LPDWORD pcbBytesNeeded // address of variable for bytes needed ); LPQUERY_SERVICE_CONFIG lpServiceConfig是一个结构,它包含指定服务的详细资料,它的原形如下 typedef struct _QUERY_SERVICE_CONFIG { // qsc DWORD dwServiceType; DWORD dwStartType; DWORD dwErrorControl; LPTSTR lpBinaryPathName; LPTSTR lpLoadOrderGroup; DWORD dwTagId; LPTSTR lpDependencies; LPTSTR lpServiceStartName; LPTSTR lpDisplayName; } QUERY_SERVICE_CONFIG, LPQUERY_SERVICE_CONFIG; 很清楚了吧,服务类型,启动类型,程序路径,服务名称,显示名称尽在其中。 下面的示例代码可以得到程序路径,启动方式,其代码如下: LPQUERY_SERVICE_CONFIG ServicesInfo = NULL; for ( i = 0; i < n; i++) { SC_HANDLE service = NULL; DWORD nResumeHandle = 0; service=OpenService(scm,lpServices[i].lpServiceName,SERVICE_ALL_ACCESS); ServicesInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 64 * 1024); //注意分配足够的空间 QueryServiceConfig(service,ServicesInfo,64 * 1024,&nResumeHandle); //枚举各个服务信息 Printf("程序路径: %s",ServicesInfo->lpBinaryPathName); if(2==ServicesInfo->dwStartType) //启动方式 { Printf("自动\n"); } if(3==ServicesInfo->dwStartType) { Printf("手动\n"); } if(4==ServicesInfo->dwStartType) { Printf("禁止\n"); } } 上面的代码稍加修改就可以用到你的程序中,现在对于服务信息的显示就完成了。 启动/停止服务 启动一个服务可以用StartService函数实现,不过在启动前先用QueryServiceStatus检查一下服务的运行状态,如下代码 SERVICE_STATUS status; BOOL isSuccess=QueryServiceStatus(service,&status); if (!isSuccess) { Printf("QueryServiceStatus error!\n"); } if ( status.dwCurrentState==SERVICE_STOPPED ) { isSuccess=StartService(service,NULL,NULL); if (!isSuccess) { Printf("启动服务失败!"); } } 下面是停止服务的实现代码: if ( status.dwCurrentState!=SERVICE_STOPPED ) { isSuccess=ControlService(service,SERVICE_CONTROL_STOP,&status); if (!isSuccess ) { Printf("停止服务失败!"); } } 创建/删除服务 创建服务使用的API为CreateService,它的原形为: SC_HANDLE CreateService( SC_HANDLE hSCManager, // handle to service control manager // database LPCTSTR lpServiceName, // pointer to name of service to start LPCTSTR lpDisplayName, // pointer to display name DWORD dwDesiredAccess, // type of access to service DWORD dwServiceType, // type of service DWORD dwStartType, // when to start service DWORD dwErrorControl, // severity if service fails to start LPCTSTR lpBinaryPathName, // pointer to name of binary file LPCTSTR lpLoadOrderGroup, // pointer to name of load ordering // group LPDWORD lpdwTagId, // pointer to variable to get tag identifier LPCTSTR lpDependencies, // pointer to array of dependency names LPCTSTR lpServiceStartName, // pointer to account name of service LPCTSTR lpPassword // pointer to password for service account ); 其中 DWORD dwStartType是指动方式,有三种方式 SERVICE_AUTO_START //自动 SERVICE_DEMAND_START //手动 SERVICE_DISABLED //禁用 此函数的参比较多但我们通常只用其中的一部分,如 SC_HANDLE hSCManager, //用OpenSCManager打开的句柄 LPCTSTR lpServiceName, // 服务名称 LPCTSTR lpDisplayName, // 显示名称 DWORD dwStartType, // 启动方式 LPCTSTR lpBinaryPathName, // 程序路径 其它直接赋0或NULL就可以了 例如下面的代码可以创建一个名为 LengFeng 路径为C:\LengFeng.EXE的自启动服务 void CreateServer() { SC_HANDLE scm=NULL; SC_HANDLE service=NULL; if((scm=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE))==NULL) { Printf("OpenSCManager Error"); } service=CreateService( scm,"LengFeng" ,"LengFeng" , SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, "C:\LengFeng.EXE", 0, 0, 0, 0, 0 ); if(!service) Printf("服务创建失败"); CloseServiceHandle(service); CloseServiceHandle(scm); } 删除服务更容易些,可以用DeleteService来实现 BOOL DeleteService( SC_HANDLE hService); SC_HANDLE hService是我们以前用OpenService打开的服务句柄,在删除前注意先用,启动/停止服务中介绍的方法 停止正在运行的服务。 配置启动方式 有时候我们需要对服务的启动方式进行更改,比如TELNET改为自动运行,对以存在的服务进行配置 可以用ChangeServiceConfig来实现,它的原形如下: BOOL ChangeServiceConfig( SC_HANDLE hService // handle to service DWORD dwServiceType, // type of service DWORD dwStartType, // when to start service DWORD dwErrorControl, // severity if service fails to start LPCTSTR lpBinaryPathName, // pointer to service binary file name LPCTSTR lpLoadOrderGroup, // pointer to load ordering group name LPDWORD lpdwTagId, // pointer to variable to get tag identifier LPCTSTR lpDependencies, // pointer to array of dependency names LPCTSTR lpServiceStartName, // pointer to account name of service LPCTSTR lpPassword, // pointer to password for service account LPCTSTR lpDisplayName // pointer to display name ); 揉揉眼睛仔细看一下,是不是有点面熟?嘿它的参数跟创建服务的CreateService就是一样的嘛!这样就好办了 我们把需要的地方改掉,不需要的就放个NULL或SERVICE_NO_CHANGE就行了。 为了安全更新配置信息,微软要求在执行ChangeServiceConfig之前需要用LockServiceDatabase来锁定服务数据 偶测试了一下,有时候会锁定失败,但仍然可以实现对服务配置的更改。 下面的示例代码,可以把上面创建的LengFeng服务的启动方式改为 禁止 其代码如下: SC_LOCK sclLock; sclLock = LockServiceDatabase(scm); if (sclLock == NULL) { if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) Printf("LockServiceDatabase error\n"); } if (! ChangeServiceConfig( service, // handle of service SERVICE_NO_CHANGE, // service type: no change SERVICE_DISABLED, // 这里做了更改 SERVICE_NO_CHANGE, // error control: no change NULL, // binary path: no change NULL, // load order group: no change NULL, // tag ID: no change NULL, // dependencies: no change NULL, // account name: no change NULL, // password: no change NULL)) //displayname { Printf("ChangeServiceConfig error!\n"); } UnlockServiceDatabase(sclLock); 伸个懒腰,与服务相关的操作,我们也搞个六七八九不离十啦,想把它加到自己的木马中时,只要设计一个便于网络传输的结构,然后把代码拷进去就差不多了。在写这个小程序时遇到的相关问题写在了blog.csdn.net/chinafe有兴趣可以跟我讨论。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/houjinfeng210/archive/2010/05/11/5577758.aspx
|
|