[原创]PsExec 在当前会话下启动系统权限进程原理
事情的起因是这样的,前两天去xxx公司面试,被问道这样一个问题:PsExec是怎么以系统权限运行程序的?PsExec确实是用过的,记得在看windows internals这本书的时候,比着书上的例子启动了个系统权限注册表程序。当时也没答上来,回来后想来想去那么就分析一下它到底是怎么实现的,于是就有了这篇文章。
首先在当前Session下以系统权限运行一个程序的命令行如下:
psexec -i -d -s regedit.exe
打开IDA先从参数入手,看一下这几个参数是怎么处理的



可以看到它们被记录到了三个个全局变量里面,通过ida的交叉引用发现一处使用的地方

简单分析sub_404920函数后,开头内容如下:

通过这些信息,明确了一点,PsExec从资源文件中提取出了一个服务,并创建且运行了该服务程序。也就是说PsExec是通过服务程序获得系统权限的。下图分别是释放服务程序文件和创建启动服务程序的


我们知道,服务程序是运行在session0下的,而待运行程序(regedit.exe)是要运行在当前session下的,如果只是简单的在服务中运行这个程序,那肯定是行不通的,必然是经过了某个步骤,之后又创建了待运行的程序,继续分析,看这个程序究竟是怎么被创建起来的。
接下来函数创建了一个跟服务程序通信的命名管道

在通信的数据中保存了PsExec接收的命令行参数,包括传入的-d i s 和待运行的程序等。如下图


发送函数SendToPsExeSrv内部实现如下:

通过WriteFile函数把参数等信息发送给了服务程序,下面转到服务程序,看这个过程是如何实现的
由前面的分析可以知道,-d s i 被分别放到了传给szSendBuf的17952,17953,17954处。先看下-s 选项的处理

调用DuplicateTokenEx复制了当前服务程序的token。下面看-i选项的处理

函数掉用了ChangeSessionId来改变token的SessionID

通过-i 参数发现服务程序改变了Token的SessionId为当前活动的Session。而这个关键的函数就是SetTokenInformation,这个函数的解释如下:

也就是说,要改变token的信息,必须有相应的权限,那SeTcbPrivilege权限应该就是要改变session ID必须具备的权限了,看下SeTcbPrivilege权限的描述:

大意是说,允许程序像用户一样认证和获得资源的访问权限。
再来看下-d选项

最后就是启动程序了

由此得到如下答案,服务是通过改变token中的sessionID来改变程序运行的session,最终在当前session下启动了系统全权限的进程。
最后总结下在当前session下启动系统权限程序经历的过程
1. 运行一个系统权限的服务程序
2. DuplicateTokenEx当前服务程序的token
3. 提升“SeTcbPrivilege”权限
4. SetTokenInformation改变token的sessionID
5. CreateProcessAsUserW启动待运行程序
