自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

網(wǎng)絡(luò)安全編程:服務(wù)控制管理器實(shí)例

安全
幾乎每一種操作系統(tǒng)都有一種在系統(tǒng)啟動(dòng)時(shí)啟動(dòng)的進(jìn)程機(jī)制,這種機(jī)制不會(huì)依賴于用戶的交互。

 [[382170]]

幾乎每一種操作系統(tǒng)都有一種在系統(tǒng)啟動(dòng)時(shí)啟動(dòng)的進(jìn)程機(jī)制,這種機(jī)制不會(huì)依賴于用戶的交互。在Windows下,類似的機(jī)制被稱為服務(wù)或Windows服務(wù)。服務(wù)是一種程序類型,它在后臺(tái)運(yùn)行,服務(wù)程序通??梢栽诒镜睾屯ㄟ^網(wǎng)絡(luò)為用戶提供一些功能,服務(wù)在操作系統(tǒng)啟動(dòng)時(shí)就會(huì)隨之啟動(dòng)的程序。服務(wù)程序可能是EXE程序,具有其單獨(dú)的進(jìn)程,也有可能是DLL文件依附于某個(gè)進(jìn)程(比如svchost.exe),更有可能是SYS文件而處于系統(tǒng)的內(nèi)核之中。由于服務(wù)所處的核心地位、啟動(dòng)方式等因素,它也是反病毒軟件與惡意軟件的“兵家必爭(zhēng)之地”。對(duì)于研究系統(tǒng)安全來說則非常重要。

01 如何查看系統(tǒng)服務(wù)

在Windows下,有很多服務(wù)是跟隨操作系統(tǒng)一起啟動(dòng)的,具體有哪些服務(wù)是跟隨操作系統(tǒng)一起啟動(dòng)的呢?如何查看呢?其實(shí)非常簡(jiǎn)單。在“我的電腦”上單擊鼠標(biāo)右鍵,然后在彈出的菜單上選擇“管理”,打開“計(jì)算機(jī)管理”工具,單擊左面樹形列表的“服務(wù)和應(yīng)用程序”會(huì)打開子列表,選擇“服務(wù)”,則在右側(cè)出現(xiàn)服務(wù)項(xiàng)列表。較為簡(jiǎn)單的方法是直接在“運(yùn)行”窗口中輸入“services.msc”,打開服務(wù)管理器。服務(wù)管理器主要用于顯示系統(tǒng)中已經(jīng)存在的應(yīng)用程序服務(wù),顯示對(duì)服務(wù)的描述,還可以控制服務(wù)的啟動(dòng)狀態(tài)和啟動(dòng)方式。服務(wù)管理器如圖1所示。

圖1  Windows下的服務(wù)管理程序

在圖1顯示的服務(wù)列表中,只能查看Win32應(yīng)用程序的服務(wù),無法查看關(guān)于驅(qū)動(dòng)程序的服務(wù)。可以借助于其他一些工具來查看驅(qū)動(dòng)程序級(jí)別的服務(wù),圖2使用SREng來查看驅(qū)動(dòng)程序相關(guān)的服務(wù)列表。

圖2  使用SREng查看驅(qū)動(dòng)程序服務(wù)列表

接下來會(huì)編寫一個(gè)類似的程序,既可以查看應(yīng)用程序服務(wù)列表,也可以查看驅(qū)動(dòng)程序服務(wù)列表。編寫完成后的程序界面如圖3所示。

圖3  服務(wù)管理程序界面

編寫的服務(wù)管理程序既可以查看“Win32服務(wù)應(yīng)用程序”,也可以查看“驅(qū)動(dòng)服務(wù)程序”,并且可以對(duì)它們的運(yùn)行狀態(tài)進(jìn)行簡(jiǎn)單的控制。這里開發(fā)的服務(wù)控制管理器使用MFC的對(duì)話框,其中用到了CListCtrl控件?,F(xiàn)在就開始打造一個(gè)屬于自己的服務(wù)控制管理器。

02 服務(wù)控制管理器的實(shí)現(xiàn)

服務(wù)控制管理器的開發(fā)過程與注冊(cè)表啟動(dòng)管理器的開發(fā)過程比較類似,主要也是枚舉服務(wù)并顯示到列表控件中。對(duì)服務(wù)狀態(tài)的控制,是通過服務(wù)相關(guān)的API函數(shù)來完成的。首先來編寫代碼,希望大家能夠掌握服務(wù)相關(guān)的API函數(shù)。在代碼的后面,會(huì)對(duì)開發(fā)服務(wù)管理器涉及的API進(jìn)行相應(yīng)的解釋。

學(xué)習(xí)API函數(shù)的使用,MSDN是最好的老師,詳細(xì)、透徹、權(quán)威。在編程的道路上,要不斷通過閱讀別人的代碼來提高自己的編程能力,就需要自己來掌握陌生的API函數(shù),那時(shí)一定要想起查閱MSDN。

1. 服務(wù)的類型

服務(wù)控制管理器的界面都已經(jīng)熟悉了,界面的布局可以按照自己的方式進(jìn)行調(diào)整。在枚舉服務(wù)的時(shí)候,將“Win32應(yīng)用程序服務(wù)”和“驅(qū)動(dòng)程序服務(wù)”分開枚舉,這樣有助于對(duì)各種服務(wù)的了解。

枚舉這兩類服務(wù)的主要差別在于調(diào)用EnumServicesStatus()函數(shù)時(shí)為其傳遞的第二個(gè)參數(shù)。如果枚舉“Win32應(yīng)用程序服務(wù)”,那么傳遞的參數(shù)為SERVICE_WIN32;如果枚舉“驅(qū)動(dòng)程序服務(wù)”,那么傳遞的參數(shù)為SERVICE_DRIVER。這兩個(gè)參數(shù)其實(shí)是系統(tǒng)定義的宏,該宏定義在WinNt.h頭文件中,具體定義如下: 

  1. #define SERVICE_DRIVER (SERVICE_KERNEL_DRIVER | \  
  2.  SERVICE_FILE_SYSTEM_DRIVER | \  
  3.  SERVICE_RECOGNIZER_DRIVER)  
  4. #define SERVICE_WIN32 (SERVICE_WIN32_OWN_PROCESS | \  
  5.  SERVICE_WIN32_SHARE_PROCESS) 

SERVICE_DRIVER 和 SERVICE_WIN32 是其他宏的組合,而那些宏又有具體的值。下面解釋一下其他宏的含義。

SERVICE_DRIVER 宏由 3 個(gè)宏組成,具體如下: 

  1. #define SERVICE_KERNEL_DRIVER 0x00000001 // 設(shè)備驅(qū)動(dòng)程序  
  2. #define SERVICE_FILE_SYSTEM_DRIVER 0x00000002 // 內(nèi)核模式文件系統(tǒng)驅(qū)動(dòng)程序  
  3. #define SERVICE_RECOGNIZER_DRIVER 0x00000008 // 文件系統(tǒng)識(shí)別器驅(qū)動(dòng)程序 

SERVICE_WIN32 宏由兩個(gè)宏組成,具體如下: 

  1. #define SERVICE_WIN32_OWN_PROCESS 0x00000010 // 獨(dú)占一個(gè)進(jìn)程的服務(wù)  
  2. #define SERVICE_WIN32_SHARE_PROCESS 0x00000020 // 與其他服務(wù)共享一個(gè)進(jìn)程的服務(wù) 

如果想要枚舉全部類型的服務(wù),那么使用SERVICE_TYPE_ALL宏即可,該宏的定義如下: 

  1. #define SERVICE_TYPE_ALL (SERVICE_WIN32 | \  
  2.  SERVICE_ADAPTER | \  
  3.  SERVICE_DRIVER | \  
  4.  SERVICE_INTERACTIVE_PROCESS) 

2. 服務(wù)的枚舉函數(shù)

服務(wù)的枚舉所使用的API函數(shù)是EnumServicesStatus(),該函數(shù)中需要指定枚舉的類型分別是SERVICE_DRIVER和SERVICE_WIN32。

具體來看服務(wù)枚舉的函數(shù),代碼如下: 

  1. VOID CManageServicesDlg::ShowServiceList(DWORD dwServiceType)  
  2.  
  3.   m_ServiceList.DeleteAllItems();  
  4.   // 打開服務(wù)管理器  
  5.   SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  
  6.   if ( NULL == hSCM )  
  7.   {  
  8.     AfxMessageBox("OpenSCManger Error!");  
  9.     return ; 
  10.   }  
  11.   DWORD ServiceCount = 0 
  12.   DWORD dwSize = 0 
  13.   LPENUM_SERVICE_STATUS lpInfo;  
  14.   // 第一次調(diào)用  
  15.   BOOL bRet = EnumServicesStatus(hSCM,  
  16.     dwServiceType, SERVICE_STATE_ALL,  
  17.     NULL, 0, &dwSize,  
  18.     &ServiceCount, NULL);  
  19.   // 由于沒有給定接收服務(wù)列表的緩沖區(qū),這里必定會(huì)調(diào)用失敗  
  20.   // 失敗的原因是 ERROR_MORE_DATA  
  21.   // 說明需要更大的緩沖區(qū)來保存數(shù)據(jù)  
  22.   if ( !bRet && GetLastError() == ERROR_MORE_DATA )  
  23.   {  
  24.     // 分配緩沖區(qū),保存服務(wù)列表  
  25.     lpInfo = (LPENUM_SERVICE_STATUS)(new BYTE[dwSize]);  
  26.       bRet = EnumServicesStatus(hSCM,  
  27.       dwServiceType, SERVICE_STATE_ALL,  
  28.       (LPENUM_SERVICE_STATUS)lpInfo,  
  29.       dwSize, &dwSize,  
  30.       &ServiceCount, NULL);  
  31.     if ( !bRet )  
  32.     {  
  33.       CloseServiceHandle(hSCM); 
  34.       return ;  
  35.     }  
  36.     //逐個(gè)獲取數(shù)據(jù),添加至列表控件  
  37.     for ( DWORD i = 0; i < ServiceCount; i ++)  
  38.     {  
  39.       CString str;  
  40.       m_ServiceList.InsertItem(i, lpInfo[i].lpServiceName);  
  41.       m_ServiceList.SetItemText(i, 1, lpInfo[i].lpDisplayName);  
  42.       switch ( lpInfo[i].ServiceStatus.dwCurrentState )  
  43.       {  
  44.       case SERVICE_PAUSED: 
  45.         {  
  46.           m_ServiceList.SetItemText(i, 2, "暫停");  
  47.           break;  
  48.         }  
  49.       case SERVICE_STOPPED:  
  50.         {  
  51.           m_ServiceList.SetItemText(i, 2, "停止");  
  52.           break;  
  53.         }  
  54.       case SERVICE_RUNNING:  
  55.         {  
  56.           m_ServiceList.SetItemText(i, 2, "運(yùn)行");  
  57.           break;  
  58.         }  
  59.       default:  
  60.         {  
  61.           m_ServiceList.SetItemText(i, 2, "其他");  
  62.         }  
  63.       }  
  64.     }  
  65.     // 釋放申請(qǐng)的空間  
  66.     delete lpInfo;  
  67.   }  
  68.   // 關(guān)閉服務(wù)管理器句柄  
  69.   CloseServiceHandle(hSCM);  

該函數(shù)有一個(gè)參數(shù),用來指明枚舉類型是“Win32應(yīng)用程序服務(wù)”,還是“驅(qū)動(dòng)程序服務(wù)”。該函數(shù)的默認(rèn)參數(shù)為“Win32應(yīng)用程序服務(wù)”,該函數(shù)的定義如下: 

  1. VOID ShowServiceList(DWORD dwServiceType = SERVICE_WIN32); 

3. 枚舉服務(wù)相關(guān)API函數(shù)解釋

(1)打開和關(guān)閉服務(wù)管理器

打開服務(wù)管理器的函數(shù)定義如下: 

  1. SC_HANDLE OpenSCManager(  
  2.  LPCTSTR lpMachineName, // computer name  
  3.  LPCTSTR lpDatabaseName, // SCM database name  
  4.  DWORD dwDesiredAccess // access type  
  5. ); 

參數(shù)說明如下。

lpMachineName:指向欲打開服務(wù)控制管理器數(shù)據(jù)庫的目標(biāo)主機(jī)名,本機(jī)則設(shè)置為 NULL。

lpDatabaseName:指向目標(biāo)主機(jī) SCM 數(shù)據(jù)庫名字的字符串。

dwDesiredAccess:指定對(duì) SCM 數(shù)據(jù)庫的訪問權(quán)限。

該函數(shù)調(diào)用成功,返回一個(gè) SCM 句柄,否則返回 NULL。

SCM是服務(wù)控制管理器的意思,它是系統(tǒng)服務(wù)的一個(gè)組成部分,跟開發(fā)的軟件不是一個(gè)概念。

關(guān)閉服務(wù)句柄的函數(shù)定義如下: 

  1. BOOL CloseServiceHandle(  
  2.  SC_HANDLE hSCObject // handle to service or SCM object  
  3. ); 

該函數(shù)用來關(guān)閉由OpenSCManager()和OpenService()打開的句柄。

(2)服務(wù)的枚舉函數(shù)

枚舉服務(wù)的函數(shù)定義如下: 

  1. BOOL EnumServicesStatus(  
  2.  SC_HANDLE hSCManager, // handle to SCM database  
  3.  DWORD dwServiceType, // service type  
  4.  DWORD dwServiceState, // service state  
  5.  LPENUM_SERVICE_STATUS lpServices, // status buffer  
  6.  DWORD cbBufSize, // size of status buffer  
  7.  LPDWORD pcbBytesNeeded, // buffer size needed  
  8.  LPDWORD lpServicesReturned, // number of entries returned  
  9.  LPDWORD lpResumeHandle // next entry  
  10. ); 

參數(shù)說明如下。

hSCManager:OpenSCManager()函數(shù)返回的句柄。

dwServiceType:指定枚舉的服務(wù)類型,也就是自定義函數(shù)的參數(shù)。

dwServiceState:枚舉指定狀態(tài)的服務(wù)。

lpServices:指向 ENUM_SERVICE_STATUS 類型的指針。

cbBufSize:指定緩沖區(qū)的大小。

pcbBytesNeeded:返回實(shí)際使用的內(nèi)存空間大小。

lpServicesReturned:返回枚舉服務(wù)的個(gè)數(shù)。

lpResumeHandle:返回枚舉是否成功。

ENUM_SERVICE_STATUS 結(jié)構(gòu)體的定義如下: 

  1. typedef struct _ENUM_SERVICE_STATUS {  
  2.  LPTSTR lpServiceName;  
  3.  LPTSTR lpDisplayName;  
  4.  SERVICE_STATUS ServiceStatus;  
  5. } ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS; 

SERVICE_STATUS 結(jié)構(gòu)體的定義如下: 

  1. typedef struct _SERVICE_STATUS {  
  2.  DWORD dwServiceType;  
  3.  DWORD dwCurrentState;  
  4.  DWORD dwControlsAccepted;  
  5.  DWORD dwWin32ExitCode;  
  6.  DWORD dwServiceSpecificExitCode;  
  7.  DWORD dwCheckPoint;  
  8.  DWORD dwWaitHint;  
  9. } SERVICE_STATUS, *LPSERVICE_STATUS; 

代碼中兩次調(diào)用EnumServicesStatus()函數(shù)。第1次沒有傳遞第4個(gè)和第5個(gè)參數(shù),使得函數(shù)返回FALSE,用GetLastError()得到錯(cuò)誤的原因?yàn)镋RROR_MORE_DATA。這時(shí),第6個(gè)參數(shù)pcbBytesNeeded返回實(shí)際需要使用的內(nèi)存大小,這樣可以通過new動(dòng)態(tài)申請(qǐng)所需的堆空間。以這種方式來獲取實(shí)際所需緩沖區(qū)大小的情況是比較多的,請(qǐng)大家一定要理解。

4. 服務(wù)的啟動(dòng)與停止

對(duì)服務(wù)的操作只介紹兩種,一種是啟動(dòng)服務(wù),另一種是停止服務(wù),也就是改變服務(wù)的狀態(tài)。經(jīng)常會(huì)用到停止服務(wù)的操作,因?yàn)橄到y(tǒng)中有很多用不到的服務(wù),但是它仍然會(huì)隨著系統(tǒng)的啟動(dòng)而啟動(dòng),這樣既會(huì)影響到系統(tǒng)的啟動(dòng)速度,也會(huì)占用寶貴的系統(tǒng)資源。因此,沒有用的系統(tǒng)服務(wù)最好將其停止(其實(shí)真正停止服務(wù)是改變它的啟動(dòng)狀態(tài),而不是這里介紹的運(yùn)行狀態(tài))。

啟動(dòng)服務(wù)的代碼如下: 

  1. void CManageServicesDlg::OnBtnStart()  
  2.  
  3.   // TODO: Add your control notification handler code here  
  4.   // 選中服務(wù)的索引  
  5.   POSITION Pos = m_ServiceList.GetFirstSelectedItemPosition();  
  6.   int nSelect = -1;  
  7.   while ( Pos )  
  8.   {  
  9.     nSelect = m_ServiceList.GetNextSelectedItem(Pos);  
  10.   }  
  11.   if ( -1 == nSelect )  
  12.   {  
  13.     AfxMessageBox("請(qǐng)選擇要啟動(dòng)的服務(wù)");  
  14.     return ; 
  15.   }  
  16.   // 獲取選中服務(wù)的服務(wù)名  
  17.   char szServiceName[MAXBYTE] = { 0 };  
  18.   m_ServiceList.GetItemText(nSelect, 0, szServiceName, MAXBYTE);  
  19.   SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  
  20.   if ( NULL == hSCM )  
  21.   {  
  22.     AfxMessageBox("OpenSCManager Error");  
  23.     return ;  
  24.   }  
  25.   // 打開指定的服務(wù)  
  26.   SC_HANDLE hSCService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);  
  27.   // 啟動(dòng)服務(wù)  
  28.   BOOL bRet = StartService(hSCService, 0, NULL);  
  29.   if ( bRet == TRUE )  
  30.   {  
  31.     m_ServiceList.SetItemText(nSelect, 2, "運(yùn)行");  
  32.   }  
  33.   else  
  34.   {  
  35.     AfxMessageBox("啟動(dòng)失敗!");  
  36.   }  
  37.   CloseServiceHandle(hSCService);  
  38.   CloseServiceHandle(hSCM);  

停止服務(wù)的代碼如下: 

  1. void CManageServicesDlg::OnBtnStop()  
  2.  
  3.   // TODO: Add your control notification handler code here  
  4.   // 選中服務(wù)的索引  
  5.   // 此部分操作與啟動(dòng)服務(wù)相同,為節(jié)省篇幅,此處省略  
  6.   // ……  
  7.   SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  
  8.   if ( NULL == hSCM )  
  9.   {  
  10.     AfxMessageBox("OpenSCManager Error");  
  11.     return ;  
  12.   }  
  13.   // 打開指定的服務(wù)  
  14.   SC_HANDLE hSCService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);  
  15.   SERVICE_STATUS ServiceStatus;  
  16.   // 停止服務(wù)  
  17.   BOOL bRet = ControlService(hSCService, SERVICE_CONTROL_STOP, &ServiceStatus);  
  18.   if ( bRet == TRUE )  
  19.   {  
  20.     m_ServiceList.SetItemText(nSelect, 2, "停止");  
  21.   }  
  22.   else  
  23.   {  
  24.     AfxMessageBox("停止失敗!");  
  25.   }  
  26.   CloseServiceHandle(hSCService);  
  27.   CloseServiceHandle(hSCM);  

5. 啟動(dòng)與停止服務(wù)相關(guān)API函數(shù)解釋

打開指定服務(wù)的函數(shù)定義如下: 

  1. SC_HANDLE OpenService(  
  2.  SC_HANDLE hSCManager, // handle to SCM database  
  3.  LPCTSTR lpServiceName, // service name  
  4.  DWORD dwDesiredAccess // access  
  5. ); 

參數(shù)說明如下。

hSCManager:指定由 OpenSCManager()函數(shù)打開的服務(wù)句柄。

lpServiceName:指定要打開的服務(wù)的名稱。

dwDesiredAccess:對(duì)要打開服務(wù)的訪問權(quán)限,這里為了方便,指定為 SC_MANAGER_ALL_ACCESS。

啟動(dòng)服務(wù)的函數(shù)定義如下: 

  1. BOOL StartService(  
  2.  SC_HANDLE hService, // handle to service  
  3.  DWORD dwNumServiceArgs, // number of arguments  
  4.  LPCTSTR *lpServiceArgVectors // array of arguments  
  5. ); 

參數(shù)說明如下。

hService:指定要啟動(dòng)服務(wù)的句柄,該句柄由 OpenService()返回。

dwNumServiceArgs:指向啟動(dòng)服務(wù)所需的參數(shù)個(gè)數(shù)。

lpServiceArgVectors:指向啟動(dòng)服務(wù)的參數(shù)。

停止服務(wù)的函數(shù)定義如下: 

  1. BOOL ControlService(  
  2.  SC_HANDLE hService, // handle to service  
  3.  DWORD dwControl, // control code 
  4.  LPSERVICE_STATUS lpServiceStatus // status information  
  5. ); 

參數(shù)說明如下。

hService:指定一個(gè)由 OpenService()打開的服務(wù)句柄。

dwControl:指定要發(fā)送的控制碼。

lpServiceStatus:返回服務(wù)的狀態(tài)。

ControlService()可以對(duì)服務(wù)進(jìn)行多種控制操作,每種控制操作對(duì)應(yīng)一種控制碼。當(dāng)要停止服務(wù)時(shí),使用的控制碼為 SERVICE_CONTROL_STOP。一定要注意,停止服務(wù)不要想當(dāng)然的使用 StopService()這樣的函數(shù),因?yàn)闆]有這個(gè) API 函數(shù)。 

 

責(zé)任編輯:龐桂玉 來源: 計(jì)算機(jī)與網(wǎng)絡(luò)安全
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)