螢幕監控是遠控軟體的基本功能之一。
現在很多遠控程式的服務端通常為dll形式,通過遠端執行緒注入等方法插入到services、svchost等system許可權的程序中去,而此時常規的螢幕監控就會失效(這是因為與system許可權程序關聯的視窗站、桌面與普通程序不同)。
如何才能在system許可權下實現螢幕監控呢?
一、 螢幕監控的基本原理
螢幕監控簡單說就是對程序的當前桌面進行截圖存成點陣圖,然後將此位圖資料傳輸到遠端。
對桌面進行截圖需要通過一系列windows gdi api來完成的。
首先通過createdc,createcompatibledc,createcompatiblebitmap,selectobject等api將「display」驅動器的裝置上下文與點陣圖控制代碼關聯起來。
然後通過getstockobject,getdc,selectpalette等api處理調色盤。
最後在乙個迴圈中通過getdibits將所有水平線畫素資料存入到緩衝區中去。
這個緩衝區就是我們想要的點陣圖資料,只要將這些資料組織一下,就可以當成位圖顯示出來了。通過連續傳輸位圖,就可以實時對遠端螢幕進行監控了。這個過程比較簡單,就不浪費文字了。
二、視窗站與桌面
首先必須了解幾個重要的概念:
視窗站(windowsstation)和桌面(desktop)是windows作業系統底層暴露給windows api的執行體物件(windows內部有兩種型別的物件:執行體物件和核心物件。執行體物件指由執行體的各種元件如程序管理器、記憶體管理器等等所實現的物件。核心物件是由windows核心實現的一組更基本的物件)。
其中,視窗站物件包含了乙個剪貼簿、一組全域性原子和一組桌面物件。桌面物件是乙個被包含在視窗站內部的物件,桌面物件有乙個邏輯顯示器表面,其中包含了視窗、選單和鉤子。
0號視窗站(winsta0)和預設的桌面物件(default desktop)是有winlogon程序建立的。視窗站是會話(session)的下一層組織結構。乙個會話可以有多個視窗站,但同一時刻只能有乙個視窗站可以與使用者進行互動。每個視窗站有自己的剪貼簿,可以有多個桌面。winlogon程序呼叫ntusercreatewindowsstation函式建立視窗站,再呼叫ntusercreatedesktop來建立桌面。它首先會建立乙個名為winlogon的桌面供自己使用(windows登入介面就屬於屬於這個桌面),然後再建立乙個名為default的桌面給應用程式使用。建立完桌面後,winlogon呼叫setactivedesktop函式將winlogon桌面設定為當前的活動桌面。
之後,winlogon會建立用於管理系統服務的服務管理器(service.exe)和本地安全認證子系統(lsass.exe)。使用者登陸資訊被驗證後,winlogon會將應用程式桌面啟用,啟動userinit程式,userinit會執行登錄檔中定義的登入指令碼,然後啟動作業系統外殼程式(shell-預設是explorer.exe)。這是system許可權程序和普通使用者程序邏輯顯示器桌面分離的開始。在以後程序建立createprocess的過程中,如果沒有指定桌面,那麼程序就會與呼叫者的當前桌面關聯在一起。
在實際測試中,發現services、svchost這些程序似乎沒有關聯任何桌面(截的屏都是黑屏)。普通的程序都是default桌面,登入介面是winlogon桌面。所以,當dll插入到service.exe等程序中的時候,要想實現截圖必須將程序與default桌面關聯,使用者登出、離開或未登入時就要將程序與winlogon桌面關聯。
windows給我們提供的一些api允許我們幹這些事。
首先可以通過openwindowstation開啟乙個視窗站物件,然後通過setprocesswindowstation將程序與視窗站關聯,通過opendesktop開啟乙個桌面物件,再通過setthreaddesktop將執行緒與這個桌面關聯。這樣service.exe就可以實現截圖了。但如何才能知道當前使用者在哪個桌面呢?可以通過下列函式實現:
openinputdesktop(df_allowotheraccounthook, false, maximum_allowed);//開啟輸入桌面
getuserobjectinformation(hactivedesktop, uoi_name, pvinfo, sizeof(pvinfo), &dwlen); //獲取指定桌面物件的資訊,一般情況和屏保狀態為default,登陸介面為winlogon
pvinfo緩衝區包含的就是當前桌面。這樣就可以放心的呼叫opendesktop開啟它了。
完整**如下:
bool opendesktop(lpcwstr szname)
;wchar tmp[1024] = ;
if(szname != null)
lstrcpy(pvinfo, szname);
else
//獲取指定桌面物件的資訊,一般情況和屏保狀態為default,登陸介面為winlogon
getuserobjectinformation(hactivedesktop, uoi_name, pvinfo, sizeof(pvinfo), &dwlen);
if(dwlen==0)//獲取失敗
closedesktop(hactivedesktop);
//開啟winsta0
m_hwinsta = openwindowstation(_t("winsta0"), false,
winsta_accessclipboard |
winsta_accessglobalatoms |
winsta_createdesktop |
winsta_enumdesktops |
winsta_enumerate |
winsta_exitwindows |
winsta_readattributes |
winsta_readscreen |
winsta_writeattributes);
if (m_hwinsta == null)
if (!setprocesswindowstation(m_hwinsta))
//開啟desktop
m_hdesk = opendesktop(pvinfo, 0, false,
desktop_createmenu |
desktop_createwindow |
desktop_enumerate |
desktop_hookcontrol |
desktop_journalplayback |
desktop_journalrecord |
desktop_readobjects |
desktop_switchdesktop |
desktop_writeobjects);
if (m_hdesk == null)
setthreaddesktop(m_hdesk);
return true;
}**有點亂,將就一下!
三、後記
上面的**只是針對service.exe這樣的程序,要想做的通用還要再加些**。
如何在SYSTEM許可權下實現螢幕監控
螢幕監控是遠控軟體的基本功能之一。現在很多遠控程式的服務端通常為dll形式,通過遠端執行緒注入等方法插入到services svchost等system許可權的程序中去,而此時常規的螢幕監控就會失效 這是因為與system許可權程序關聯的視窗站 桌面與普通程序不同 如何才能在system許可權下實現...
如何在docker容器內使用systemctl
docker版本 root localhost gae proxy docker version client version 1.10.3 api version 1.22 package version docker common 1.10.3 46.el7.centos.10.x86 64 g...
如何用程式刪除win 7下SYSTEM許可權的目錄
win7系統由於安裝程式等操作,可能會在系統中留下一些所有許可權是system角色的目錄,例如我的系統以前在c盤的qq解除安裝後的遺留檔案 下圖 system是windows系統中最高許可權角色 組 比administrator使用者許可權高,這樣的目錄無法手工刪除。網上給的方法是右鍵點選資料夾 屬...