system权限实现屏幕截屏



首先必须了解几个重要的概念:
窗口站(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 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;
}

上面的代码针对的是system权限这样的进程。如果是其他的可能还要作下提权等操作,相对复杂一些。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Python中可以使用第三方库来实现远程监控电脑屏幕的功能,其中最常用的是`PIL`(Python Imaging Library)和`paramiko`(一个用于SSH连接的Python库)。以下是一个基本的步骤: 1. **安装必要的库**:首先,你需要安装`PIL`(如果还没有安装)和`paramiko`库,可以使用pip命令: ``` pip install pillow paramiko ``` 2. **设置SSH连接**:如果要从远程服务器访问,需要确保目标电脑开启了SSH服务,并且你可以通过用户名和密码或者密钥对成功登录。 3. **获取屏幕截图**:使用`paramiko`库创建一个SSH客户端,然后调用`invoke_shell()`方法获取一个shell会话。接着,你可以通过发送特定的命令(如`import os; os.system('import mss; sct = mss.mss(); img = sct.grab(sct.monitors)')`),利用`mss`库来截取屏幕截图。 4. **接收和保存截图**:在本地服务器上,创建一个文件接收来自远程服务器的截图数据,通常是一个字节流。然后,将接收到的数据写入文件,例如: ```python ssh.exec_command('import os; import io; img_data = io.BytesIO(); os.system("your_screenshot_command_here"); img_data.seek(0);', get_pty=True) local_file = open("received_screenshot.png", "wb") local_file.write(img_data.read()) local_file.close() ``` 5. **定期执行**:如果你想定期监控,可以将上述代码封装到一个定时任务或者循环中运行。 注意:这只是一个基础示例,实际操作可能需要处理更多的网络异常、权限问题以及安全考虑。另外,由于跨设备权限限制,这个方法并不适用于所有情况,比如在没有root权限的用户账户下。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值