Day 9587 用系统提供的功能绕过UAC以交互方式启动应用程序

饭否@谜厎(就是锐风,太空饭否的合作+主要开发者之一)曾在我吐槽软件限制策略不管用时提到让特定程序(例如Sublime Text)绕过NT 6.0以后的用户账户控制(User Account Control,UAC)来修改hosts的方法,经过搜索和实践,通过系统本身提供的功能、用正常途径(其它高门槛途径还包括注入系统进程绕过UAC等,本文不做讨论)主要包含以下两种方式:

  1. 使用Microsoft Application Compatibility Toolkit为程序打RunAsInvoker的兼容性补丁
  2. 使用「任务计划程序」建立特定计划任务

本文主要展示两种方式如何操作,以及为什么第一种方式实际上对本需求没有效果。

本文操作环境为Windows 7 x64 with SP1。

一、使用「任务计划程序」建立特定的计划任务

  1. 启动「任务计划程序」管理控制台,可通过以下两种方式:在开始菜单中直接查找「任务计划」,或Win+R调用taskschd.msc。
  2. taskschd_001_mainwindow
    浏览到「任务计划程序库」,此时显示的是系统中既有的计划任务,可以发现不少程序使用计划任务来进行更新。
  3. 在任务列表空白处右击,选择「新建任务」,或在右边的「操作」中选择「创建任务」(不是「创建基本任务」)。
  4. taskschd_002_createtask_1
    在「创建任务」的「常规」选项卡中,填写任务的「名称」(后面建立快捷方式时要用,所以可以写短一点少打点字),并选择「只在用户登录时运行」(只有选择此项,程序才能与用户进行交互,否则会运行在后台,文本编辑器运行在后台还编辑个啥)及「使用最高权限运行」(重点,要在当前帐户下绕过UAC必须勾选此选项,否则与通常运行无异)。
  5. taskschd_002_createtask_2
    在「创建任务」的「操作」选项卡中,单击「新建」,输入或浏览确定待运行程序的完整路径。「添加参数」可用于向程序传递参数,后述。
  6. taskschd_002_createtask_3
    在「创建任务」的「条件」选项卡中,系统默认勾选了「只有在计算机使用交流电源时才启动此任务」,此选项是否修改对于台式机没有影响,但如果是用电池的笔记本「可能」会导致任务无法启动,这一点没有进行验证,如果出现上述情况,请取消对其的勾选。
  7. 单击「确定」,任务即建立完毕。
  8. taskschd_003_shortcut
    在需要的地方(如:桌面)建立快捷方式,程序路径输入:schtasks /run /tn:”任务计划名称”(此处任务计划名称即为前面新建任务时写的ED3-UAC)。schtasks是系统内置的工具,用于从命令行对任务计划进行创建、删除、查询、更改、运行和中止。
  9. 以后双击这个快捷方式就可以在不激活UAC提示的情况下以管理员权限启动所需的程序(此处为EditPlus 3)了,并且还可以对系统关键部位进行存取(如修改hosts)。

有关这种方法的一些问题:

  1. 以这种方式建立的任务计划程序不能动态传参不能在没有其它方法辅助的情况下动态传参(2015-06-03修改:详见下方hdzz的评论,用到了批处理的for语法从外部文件提取参数,但如何通过右键菜单的一次点击对这个文件进行修改、进而传参就比较深了,个人认为不能说是方便的方法),也就无法变成右键菜单中的【使用提权的EditPlus打开…】之类。在cmd中运行schtasks /change时,可以将环境变量的值导入,但每次都需要输入密码才能进行修改(除非用户没有密码?未试验,不确定),而是用「计划任务程序」的管理控制台时,「添加参数」是不支持%VAR%的环境变量写法的,%VAR%这个字符串会原封不动地传给程序。
  2. 使用这种方式,当前用户必须是Administrator用户组的成员,或持有对应权限。当然这个在单机环境下不成问题,因为单用户自动就是Administrator组的成员。

二、使用Microsoft Application Compatibility Toolkit为程序打RunAsInvoker的兼容性补丁

这是@谜厎一开始给出的文章中说明的方法,首先来看其操作步骤:

  1. 下载并安装Microsoft Application Compatibility Toolkit(以下简称MACT):http://www.microsoft.com/en-us/download/details.aspx?id=7352

  2. mact_001_startmenu
    程序在Microsoft Application Compatibility Toolkit程序组下,如果目标程序是32位的,则启动32位的版本,否则启动64位的版本。本文以EditPlus 3为例,这是一个32位的程序,所以打开32位版的MACT。
  3. mact_002_main
    单击工具栏上的「Fix」按钮。
  4. mact_003_createfix_1
    输入程序的基本信息,其中Name of the program和Name of the vendor可以随便写,但建议与程序实际情况保持一致以方便查询,Program file location选择程序的主执行文件,然后点击下一步。
  5. mact_003_createfix_2
    在下一屏中的Additional compatibility modes中,找到RunAsInvoker并打勾,然后点击下一步。
  6. mact_003_createfix_3
    在下一屏的列表中确认RunAsInvoker已经打勾,然后单击下一步(原文要求点击Test Run,这里没有必要)。
  7. 在下一屏中直接点击「完成」(原文要求点击Auto Generate,这里没有必要)。
  8. 单击工具栏上的「Save」按钮,会提示为新的兼容性修补数据库起一个名字,建议输入程序自身的名称,在Database name后输入数据库名称,然后点击OK,将兼容性修补数据库保存到程序目录下
  9. 单击File菜单下的Install,将兼容性修补数据库安装到系统中。
  10. 如果程序在开始菜单或其它位置有快捷方式,右键单击打开其属性窗口,如果没有,现建立一个。在快捷方式的属性窗口「快捷方式」选项卡中,单击「高级」,取消选定「用管理员身份运行」,单击「确定」返回前一窗口,然后在「兼容性」选项卡中单击最下方的「更改所有用户的设置」,在新弹出的窗口中将「以管理员身份运行此程序」打勾,确定再确定关闭所有的窗口即可。
  11. 下次使用这个程序时,只要使用这个快捷方式打开就可以绕过UAC提升权限的提示了。

那么这个方法能不能让程序绕过UAC、并对系统关键部位的文件进行修改操作呢?答案是——不能。

以本文做实验用的EditPlus 3为例,尝试打开hosts文件(系统盘\Windows\System32\Drivers\etc\hosts),加一个回车,然后按下保存……咦,为啥弹出了另存为的对话框?按照原名保存一下试试吧,结果提示「This is a read-only document」(这是一个只读文件),实际上和拒绝访问是一个意思的。

再以另一个本来就需要提升权限才能运行的GPU-Z为例,按照上述方式对其进行处理后,程序会直接无法启动,提示Unable to access service manager:拒绝访问。

还是回到问题的本质上,来看看官方对于RunAsInvoker这个兼容性补丁的解释吧,其中最重要的一句话是:

此修补程序指定应用程序不需要提升。

所以答案就是:使用了RunAsInvoker兼容性补丁的程序在告诉系统:我不需要特权。UAC只会在程序要求提升权限的时候才会提示,所以UAC提示消失了,但也理所应当并且正确地没有给予程序任何特权,所以这个功能和传说中的UAC白名单是两码事,不能被称为UAC bypass,顶多是Bypass incorrect UAC prompt。

那么为什么方法一就可以呢?这需要从UAC的机制说起。

自从Windows系统引入了UAC,默认用户虽然也叫管理员,但拥有两组安全令牌(或者通俗地称作钥匙),一组叫filtered token(过滤访问令牌,或者叫受限令牌),另一组是full token(完整权限令牌)。我们通常操作电脑时创建的进程,一般都是用filtered token创建的,这个令牌的权限是受限的,一些比较危险的操作,如安装新程序(前提是安装程序是按照标准的安装程序规范编写的)、更改系统设置等。Full token一方面被有特权的程序使用,另一方面,我们所熟知的「以管理员身份运行」就是调用了这个令牌。

而创建计划任务时的「使用最高权限运行」就使用了叫做full token的后者,而这个设置能成功完成,也是因为当前登录的账户在Administrators(管理员)用户组中,同时拥有filtered token和full token两组令牌所致,如果开一个Guests组的账户来尝试创建,恐怕是做不到的。

以上就是对使用计划任务程序和MACT来绕过UAC提示、并以管理员权限启动特定程序的两种方法的解释说明。

如果还没有满足,可以继续阅读如何通过注入系统进程真正绕过UAC,这就属于对系统漏洞的利用了。

 

Comments

  1. 闲来无事,搜索下editplus的UAC支持什么样了。
    就因为它对uac的支持有问题,so弃用了。
    计划任务中动态传参是可以的。
    我之前的一个例子
    启动程序hideexec
    参数 cmd /c FOR /F “usebackq delims=” %i IN (“%tmp%\path.txt”) DO (start /d %i)
    可以看到指定的参数是在%tmp%\path.txt中的,
    思路就是参数固定到一个位置,外部程序写入到此位置,然后计划任务中的程序读取此文本中的内容作为参数执行。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

 剩余字数 ( Characters available )

Your comment will be available after auditing.
您的评论将在通过审核后显示。

Please DO NOT add any links in your comment, otherwise it would be identified as SPAM automatically and never be audited.
请不要在评论中插入任何链接,否则将被自动归类为垃圾评论,且永远不会被提交给博主进行复审。

*