[Win32] UAC用户账户控制(提权+降权)

本文由CSDN用户zuishikonghuan所作,转载请注明出处: http://blog.csdn.net/zuishikonghuan/article/details/46965159 

首先必须澄清一下:UAC不是Vista才有的东西!我反正知道XP就有了,2000不知道,XP上也有UAC,只不过默认没有开启,你要是愿意可以自己开启,只不过太不人性化了,和Linux上的switch user一样不人性化,没次提权必须输入管理员用户的密码。(见下面图)

所以Vista的UAC根本就不是什么新鲜玩意,如果当时完全按照微软的规范编程,升级到Vista以后UAC带来的兼容性问题虽然有但不会这么大。至少不会出现程序运行后什么也干不成,程序也没提权,用户也不知道要右键管理员身份,至少程序可以弹一个框“请切换到管理员用户再使用本程序”或者“本程序必须由管理员用户运行”之类的。

说起UAC,真是个让人又爱又恨的东西,爱他能给系统带来很大的安全性,恨他让我们的程序不能轻易获得管理员权限来尽情的做一些见不得光的事。

基本概念:

1。进程的权限是继承的,也就是说,有管理员权限的程序创建的进程也有管理员权限,没有管理员权限的程序创建进程就没有管理员权限(但高权限进程创建进程必须是高权限不是绝对的)

2。Windows Shell进程explorer本身没有管理员权限,如果explorer有管理员权限,大家可以想一下,那么它创建的进程都有管理员权限,那UAC不就形同虚设了吗

3。没有权限的进程不能创建有权限的进程!是的,你没有听错,就是不能,这是Windows操作系统规定的。但你可能会问“那么如何提权?你不是说连explorer都没有权限吗?”,答案是:Windows系统中有一个开机自启的AppInfo服务,它直接以系统权限运行,在一个管理员用户登录时,系统会保留一份当前用户的高权限令牌并传给AppInfo服务,提权的过程本身就是一个进程通过进程通信把要提权的程序传给AppInfo服务,AppInfo服务会运行一个UI进程,UI进程会接收用户响应,如果用户同意这次提权,AppInfo服务就使用高权限令牌在当前用户会话的交互窗口站的当前桌面创建管理员权限的进程,创建时将进程的父进程替换为请求提权的进程。这样我们看起来就好像是“没权限进程创建有权限进程”了,其实高权限进程不是它创建的。

[Win32] UAC用户账户控制(提权+降权)_第1张图片

图:UAC提权的AppInfo服务创建的与用户交互的UI进程

[Win32] UAC用户账户控制(提权+降权)_第2张图片

来看看如何通过UAC让程序获得管理员权限吧:

方法1。利用manifest,VS工程属性里面可以直接设置:

编译后程序图标会出现一个UAC盾牌,就像这一样:[Win32] UAC用户账户控制(提权+降权)_第3张图片

运行时UAC会弹出一个框,用户点是就可以获取管理员权限运行了。

方法2。动态提权(推荐)

所谓动态提权,就是一个没有管理员权限的程序进程在他认为合适的时候创建一个有管理员权限的程序进程,代码很简单:

ShellExecute(0,"runas",程序路径,"命令行(可空)","工作目录(可空)",SW_SHOWNORMAL);

同样这么做会弹出提权确认框

[Win32] UAC用户账户控制(提权+降权)_第4张图片

xp下:不管当前程序是否拥有管理员权限,都弹出以下框:

[Win32] UAC用户账户控制(提权+降权)_第5张图片

返回值:返回值大于32表示执行成功,返回值小于32表示执行错误(2或者3表示是文件不存在)

方法3。利用提权漏洞直接提权

可以参考一些这方面的文章,黑防就有一些,不过公开的漏洞微软都会想办法补的。

判断是否有管理员权限:

很简单,只需要调用IsUserAnAdmin即可。

再看看如何降权:

其实微软没有提供方法可以让一个有管理员权限程序创建一个没有管理员权限的程序。不过我想的了几种方法,理论上是可行的:

1。打开 explorer 的令牌

UAC开启时,explorer之所以创建管理员权限的程序时系统会弹框警告用户,是因为explorer本身就没有管理员权限!我们可以使用 OpenProcessToken 打开explorer的令牌,然后用这个令牌创建进程(CreateProcessAsUser)。

当然,我们还可以把dll远程注入到explorer中,再创建的进程就没有管理员权限了。但有一个致命缺点:因为注入explorer这一个动作本身就是病毒木马经常干的事,所以我们要注入的时候,那些杀软就弹框了“发现程序正在远程线程注入”。。

但不管打开explorer的令牌还是把dll远程注入到explorer中,都有严重缺陷,那就是,explorer不存在的问题。Windows 的 Shell 可以是自定义的,这些第三方 Shell 不一定能符合标准,极端情况下用户会话中没有 Shell 程序工作。

但我想这应该是最好的方法。

2。守护进程法

程序运行时动态提权,然后没有权限的程序一直后台运行,创建没有权限的程序时通过进程通信告知没有权限的程序创建进程。

缺点:一旦守护程序被关闭了,就全玩完了。这还好解决,直接弹框说错误就是了。关键是如果用户运行程序时直接右键->管理员身份运行 就操蛋了,创建的守护进程也是有权限的,这招就失灵了。

3。创建低权限令牌

自己创建一个低权限的令牌,然后用这个令牌创建进程(CreateProcessAsUser)。

缺点:麻烦。同时可能有一些隐形的问题或将来的兼容性问题。

关于降低完整性“降权”:(错误的方法)

网上有的人说是可以打开、复制自身的令牌,然后修改完整性级别,再用这个令牌创建进程。虽然说包括核心编程在内的主流资料都说了管理员权限的程序完整性为高,管理员以标准用户身份运行时和标准用户权限的进程完整性为中或低,但这个弄颠倒了(用到的API:OpenProcessToken、DuplicateTokenEx、SetTokenInformation、GetLengthSid等)。但经过我的测试后,这样做虽然程序并不能做一些特权的操作,但是进程的权限依旧是高!!在任务管理器中仍然可以看到特权为高,UAC虚拟化被禁用!!因此这种方法是完全错误的!!

这种方法只降低了完整性,并没有降低权限,一定不易这么做,切记!特别是目的是为了降权运行第三方程序,极易引起程序工作不正常!

这就是这样做的结果,我想我不用多说什么了:

[Win32] UAC用户账户控制(提权+降权)_第6张图片

4。计划任务降权

利用计划任务启动程序,可以设置权限。

缺点:计划任务服务被禁用后(或者没有运行时)是不能工作的。

5。使用 Safer API 

我从stackoverflow上看到的,并没有做验证

6。用 WTSQueryUserToken 得到低权限令牌

这种方法只能在服务程序中使用。因此需要编写、安装、运行服务

你可能感兴趣的:(Win32SDK)