屏幕监控是远控软件的基本功能之一。
版权声明
作者:iprowq
现在很多远控程序的服务端通常为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打开它了。

 進行桌面切換需要有System權限,如果是以服務啟動的話就是了,也可以用注入或其它的方式。

附资料:(转自:http://topic.csdn.net/t/20050825/14/4231020.html)

在winlogon注册了SAS后,就调用GINA生成3个桌面系统,在用户需要的时候使用,它们分别为: 
 ◇Winlogon   桌面用户在进入登录界面时,就进入了Winlogon桌面。而我们看到的登录对话框,只是GINA负责显示的。如果用户取消以“欢迎屏幕”方式登录,在进入   WindowsXP中任何时候按下“Ctrl-Alt-Delete”,都会激活Winlogon桌面,并显示图5的“Windows安全”对话框。(注意,Winlogon桌面并不等同对话框,对话框只是Winlogon调用其他程序来显示的) 
 ◇用户桌面   用户桌面就是我们日常操作的桌面,它是系统最主要的桌面系统。用户需要提供正确的帐号和密码,成功登录后才能显示“用户桌面”。而且,不同的用户,winlogon会根据注册表中的信息和用户配置文件来初始化用户桌面。 
 ◇   屏幕保护桌面屏幕保护桌面就是屏幕保护,包括“系统屏幕保护”和“用户屏幕保护”。在启用了“系统屏幕保护”的前提下,用户未进行登录并且长时间无操作,系统就会进入   “系统屏幕保护”;而对于“用户屏幕保护”来说,用户要登录后才能访问,不同的用户可以设置不同的“用户屏幕保护”。

我们使用用户帐户登录以后,看到的桌面,是WinSta0下的Default桌面
WinSta0下有3个桌面:
WinLogon :当用户登录以后,WinLogon.exe切换到Default桌面.
Default :这是Explorer.exe和所有用户程序窗口出现的地方,也就是我们通常使用windows看见的地方.应用程序就运行在这个桌面上
Screen saver :系统空闲的时候,运行屏保的桌面.
你们每个用户都有各自的Default桌面,但是WinLogon.exe是运行在winlogon桌面下的系统级进程。
win32k.sys里有对winlogon名字桌面的引用。
Winlogon.exe被所有用户共享一份实例,跟你的普通进程是不同的,你的普通进程只是自己的Default桌面下的各自的进程。

1.会话问题
ProcessIdToSessionId获得自己的会话Id
可以把内核对象强制指定为全局内核对象,就可以在不同会话直接共享了。
创建命名内核对象时加global前缀,CreateXXX(XXX, XXX, "Global\\内核对象名")
内核对象能共享了,进程就可以随意通信了。
2.另一个问题是权限问题
两个会话权限不同的话,低权限没办法打开高权建立的内核对象,即使是全局的
给一个函数,高权限降权内核对象的,调用后低权限打开高权限的对象,之后开始随意共享吧

LPCWSTR LOW_INTEGRITY_SDDL_SACL_W = TEXT("S:(ML;;NW;;;LW)");
BOOL SetObjectToLowIntegrity (HANDLE hObject, SE_OBJECT_TYPE type = SE_KERNEL_OBJECT)
{
BOOL bRet = FALSE;
DWORD dwErr = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL;
BOOL fSaclPresent = FALSE;
BOOL fSaclDefaulted = FALSE;
if (ConvertStringSecurityDescriptorToSecurityDescriptor(LOW_INTEGRITY_SDDL_SACL_W,
SDDL_REVISION_1,
&pSD,
NULL))
{
if (GetSecurityDescriptorSacl(pSD,
&fSaclPresent,
&pSacl,  
&fSaclDefaulted))
{
dwErr = SetSecurityInfo (hObject,  
type,
LABEL_SECURITY_INFORMATION,
NULL,
NULL,
NULL,
pSacl);
bRet = (ERROR_SUCCESS == dwErr);
}
LocalFree(pSD);
}
return bRet;
}
3.这么做有个问题,就是每个会话里都要有一个你的进程,不太爽
楼上说的方法没试过,学习了,不过看起来也是要在每个会话里都拉进程起来

转自:http://topic.csdn.net/u/20101201/08/0DFD70DD-F5C6-4B5D-96BD-C36E175FC6FD.html

完整代码如下:
BOOL OpenDesktop(LPCWSTR szName)
{
    WCHAR pvInfo[128] = {0};
    WCHAR tmp[1024] = {0};

if(szName != NULL)
        lstrcpy(pvInfo, szName);
    else
    {

HDESK hActiveDesktop;
        DWORD dwLen;
        hActiveDesktop = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, MAXIMUM_ALLOWED);
        if(!hActiveDesktop)//打开失败
        {
             return FALSE;
        }
        //获取指定桌面对象的信息,一般情况和屏保状态为default,登陆界面为winlogon
        GetUserObjectInformation(hActiveDesktop, UOI_NAME, pvInfo, sizeof(pvInfo), &dwLen);
        if(dwLen==0)//获取失败
        {
            return FALSE;
        }
        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){
        return FALSE;
       }

if (!SetProcessWindowStation(m_hwinsta)){
          return FALSE;
       }

//打开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){
           return FALSE;
       }

SetThreadDesktop(m_hdesk);
       return TRUE;
}
代码有点乱,将就一下!

三、后记

上面的代码只是针对service.exe这样的进程,要想做的通用还要再加些代码。

如何在SYSTEM权限下实现屏幕监控相关推荐

  1. 取得system权限

    这几天,无意中看到 strfreedom会员 说用ntsd命令杀掉进程的方法 [url]http://softbbs.pconline.com.cn/topic.jsp?tid=6598431& ...

  2. 奇特的Local System权限(转载)

    转载自:http://mp.weixin.qq.com/s?__biz=MzA3NTM1MzE4Nw==&mid=202597764&idx=1&sn=0cef1a40fb3c ...

  3. win7系统怎么获取system权限?

    日常使用系统中,经常有一些像恶意顽固程序及无法删除文件.需要高权限操作.丢失密码.要求最高私密性的问题.在本文中,将教你如何使用Windows 7最高权限账户system,解决各位TX的所有此类问题! ...

  4. windows 7的SYSTEM权限

    Windows7下MS加强了权限的问题,但这个神秘的无处不在的system居然比administrator还大而又不能登录实在是让人不能理解,特别是很多的目录居然都要system的权限才能删除,真是让 ...

  5. Android7.1update.zip升级在system/bin下新增可执行文件没有可执行权限问题

    Android7.1update.zip升级在system/bin下新增可执行文件没有可执行权限问题 外出的设备,只能通过update.zip方式升级,比如要在设备/system/bin目录下增加lo ...

  6. win10_x64下shellcode提权工具(SYSTEM权限)

    之前写过一篇远线程注入与一篇shellcode编写的文章: Win10_X64远线程注入dll(非CreateRemoteThread) Windows 10_X64环境shellcode编写 上一次 ...

  7. system权限实现屏幕截屏

    首先必须了解几个重要的概念: 窗口站(WindowsStation)和桌面(Desktop)是Windows操作系统底层暴露给Windows API的执行体对象(Windows内部有两种类型的对象:执 ...

  8. android readonly file system,安卓ROOT权限下“Read-only file sytem”解决办法

    今天用安卓模拟器:BlueStacks,打开apk终端模拟器:Terminal,在shell操作命令的时候提示"Read-only file sytem": 第一种方法: 在 An ...

  9. Windows服务器SYSTEM权限Webshell无法添加3389账户情况突破总结

    转自:http://bbs.blackbap.org/thread-2331-1-1.html 近好多Silic的朋友在Windows下SYSTEM权限的php webshell下添加账户,但是却无法 ...

最新文章

  1. c语言多维数组指针地址讲解,C语言入门之多维数组的指针变量
  2. 【Qt开发经验】Qt信号槽连接不成功问题原因汇总
  3. 数据结构之链式队列的优化
  4. Android 横屏启动activity,点击屏幕的单击、双击和长按事件
  5. 解析windows已从异常关机中恢复
  6. 前端学到什么水平就可以去找工作呢?
  7. Redis基础(二)——通用命令和配置
  8. SQL中创建外键约束
  9. python:configparser模块
  10. rem布局下使用背景图片和sprite图
  11. 小米Android OS特别高,干翻小米,最强定制安卓系统诞生?Color OS11表现如何
  12. Chrome浏览器直接下载pdf文件的设置步骤
  13. 仿微信雷达寻好友动画
  14. HTML5移动端手机网站开发流程
  15. C语言中的半角字符,java全角、半角字符的关系以及转换详解
  16. python lncrna_超简便的国产lncRNA预测工具LGC
  17. 电脑QQ正常上网但浏览器无法上网解决办法
  18. 每天5分钟,定投聊通透-学习笔记01
  19. 美国西北大学 计算机工程专业排名,[转载]美国西北大学计算机工程研究生最新专业排名...
  20. vivo 低代码平台【后羿】的探索与实践

热门文章

  1. 网易2017校园招聘笔试题 优雅的点
  2. 如何用div+css布局页面
  3. 完全数,丰沛数,不足数
  4. 安卓AndroidManifast
  5. mysql定时任务自动备份
  6. python-import自己的写的文件
  7. php最短路径tsp,最短路径tsp算法
  8. python操作手机app超详细步骤
  9. linux开机自启动程序设置方法
  10. linux开机自启服务