日期:2014-05-16  浏览次数:21118 次

【GamingAnywhere源码分析之知识补充五】Windows模拟用户session完成存储权限控制

        GA的存储挂载其实在上周三外围工作基本已经完成了,但是在后续这几天开发工作中遇到了一个很大的问题,是关于GA的捕捉模式,很可能有违我们修改GA的初衷。这里具体碰到哪些问题就先不说了,还是先介绍完GA存储实现的方式,等到下一篇文章中我们的研究方向可能会有改变,不过GA的源码分析总会坚持下去的。

1. Windows session机制

2. 以模拟域帐号的身份启动应用进程

     1> 模拟用户身份

     2> 多字节到宽字节的转换

3. Powershell执行mount和dismount操作

4. GA服务器端添加存储模块

一、Windows session机制

        为什么会提到windows的session机制呢?我们来分析一下,GamingAnywhere的服务端是运行在win8系统上的,该系统是以域帐号管理员的身份登录的,一旦服务端启动我们就不会手动去切换用户,基于视频流捕捉的机制,客户端连接过来后它所看到的窗口是在服务端实际运行的一个进程,而你所看到的以及你所拥有的权限都取决于运行在服务器上的该进程的权限。还记得我们分析GamingAnywhere的初衷吗?就是想利用它的这种方式来启动一个应用程序,比如:Unity,用户在启动后进行编辑势必要将自己编辑的内容保存下来,那么保存在哪?就是我们需要解决的问题,这必须面临着不同用户的权限控制。还记得以RDP登录的方式吧?它就是利用windows的session机制,每一个用户利用RDP登录后,实际上在windows上就会新建出一个session,windows就是利用它来完成不同用户的权限控制的(当然还要依赖其它方式的辅助)。那我们既要避开使用RDP这种方式,又要实现权限控制,如何实现呢?答案就是:以模拟用户的身份启动进程,那么改进程拥有的身份及权限就是那个模拟用户的。下面就先来了解一下Windows的session机制吧(先来一幅图):

                                                                                       

         现在我们知道,每一个用户登录windows系统后(利用域控可以允许多用户同时登录),都会产生一个标识他身份的session,它可以启动它自己的应用程序(进程),打开任意的窗口等。每个进程都唯一属于它的启动用户,同时也拥有一个session。也就是说,session是由代表单个用户登录会话的所有进程和系统对象组成的。其中的对象包括所有的窗口,桌面和windows stations。windows station基本上可以被描述为包含特定桌面和进程的安全边界,一个session可以包含多个windows station,而每个windows station又可拥有多个桌面。

        在多个windows station中,只有被称为winsta0的windows station才被允许与用户交互。在winsta0下共被载入三个桌面:winlogon(登录界面),default(缺省,即用户桌面)和ScreenSaver(屏幕保护桌面)。它们三个都有各自的显存,这就是为什么当你锁定工作站时你的主桌面会消失。当你锁定工作站时,屏幕由用户界面切换到登录界面,并且两者之间并没有交互。

        基于上面的原理,我们不会实际创建出一个session出来,在同一个session下模拟出另一个用户

二、以模拟域帐号的身份启动应用进程

        通过模拟不同域帐号的身份启动不同的应用程序,就好像每个用户都登录了启动各自的应用程序,然后将创作的文件保存在各自的存储下一样,这里我们用的存储是Linux利用samba共享出来的用户目录,平台用户每注册一个,就自动生成该目录,并设置磁盘配额,这样既能限制用户最大磁盘使用量又可以保存在各自的目录下互不可见,从而完成权限控制。

        1> 利用Windows API:CreateProcessWithLogonW模拟不同用户的身份

              关于:CreateProcessWithLogonW函数,MSDN上是这样描述的:“Creates a new process and its primary thread. Then the new process runs the specified executable file in the security context of the specified credentials(user , domain , and password). It can optionally load the user profile for a specified user. This function is similar to the CreateProcessAsUser and CreateProcessWithTokenW functions , except that the caller does not need to call the LogonUser function to authenticate the user and get a token.”,这句话是说“该函数用来创建一个新的进程和它的主线程。新建的进程以指定凭证(用户名、密码、域)的安全上下文运行exe文件。它可以可选择地加载指定用户的配置文件。这个函数和CreateProcessAsUser和CreateProcessWithTokenW函数很像,除了调用者无需通过调用LogonUser函数来验证一个用户并获得一个标识。” , 它的基本语法为:

BOOL WINAPI CreateProcessWithLogonW(
  _In_         LPCWSTR lpUsername,
  _In_opt_     LPCWSTR lpDomain,
  _In_         LPCWSTR lpPassword,
  _In_         DWORD dwLogonFlags,
  _In_opt_     LPCWSTR lpApplicationName,
  _Inout_opt_  LPWSTR lpCommandLine,
  _In_         DWORD dwCreationFlags,
  _In_opt_     LPVOID lpEnvironment,
  _In_opt_     LPCWSTR lpCurrentDirectory,
  _In_         LPSTARTUPINFOW lpStartupInfo,
  _Ou