今天在学习BypassUAC的时候看到了一个DLL劫持,觉得很有意思,就来深入研究一下。

基础知识

DLL

DLL是一个包含代码和数据的库,可以同时由多个程序使用。

Windows应用程序可以使用某一个LoadLibrary*函数来利用DLL中的功能。应用程序可以引用为该应用程序自定义创建的DLL,也可以引用位于System32路径下的已有DLL。开发人员可以定义应用程序从System32加载DLL,以使用Windows中已实现的功能,这样就不必再自行编写特定功能。

例如,如果应用程序需要发出HTTP请求,那么开发人员就可以利用WinHTTP库(winhttp.dll),而不需要再使用原始套接字实现HTTP请求。

安全DLL搜索模式

regedit路径:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode

这个模式在XP SP2之后默认开启,程序会以特定的顺序依次在指定路径下搜索待加载的DLL:

  1. 加载应用程序的目录;
  2. 系统目录,使用GetSystemDirectory函数获取该目录的路径;
  3. 16位系统目录,没有获取该目录路径的函数,但会对该目录进行搜索;
  4. Windows目录,使用GetWindowsDirectory函数获取该目录的路径;
  5. 当前目录;
  6. PATH环境变量中列出的目录,这里不包括App Paths注册表项指定的每个应用程序路径,在计算DLL搜索路径是不会使用到App Paths键。

系统允许程序自动提升权限的三个条件

第一:解析autoElevate属性字段的值,需要其为True

autoElevate属性的值可以用以下两个工具来获取

sigcheckhttps://docs.microsoft.com/zh-cn/sysinternals/downloads/sigcheck】

查看ComputerDefaults.exe的autoElevate属性

1
sigcheck.exe /accepteula -m C:\Windows\System32\ComputerDefaults.exe | findstr /i autoElevate

image-20230409170355376

stringshttps://docs.microsoft.com/en-us/sysinternals/downloads/strings】

查看目录下所有exe的autoElevate属性

1
strings.exe /accepteula -s C:\Windows\System32\*.exe | findstr /i "autoElevate"

image-20230409195010057

Manifestohttps://link.zhihu.com/?target=https%3A//github.com/g3rzi/Manifesto】

个人感觉这个最顶,图形化很方便

第二:检查可执行文件的签名

意味着无法通过传递Manifest信息或冒充可执行文件名来实现自动权限提升

第三:检查可执行文件是否位于系统可信任目录中

可信任目录如C:\Windows\System32

系统检查可信任目录时,相关函数会自动去掉可执行文件路径中的空格。

模拟可信任目录

我们根据基础知识里的:

  1. 系统会先加载应用程序的目录里的DLL
  2. 系统会检查可执行文件是否位于系统可信任目录中如C:\Windows\System32
  3. 系统检查可信任目录时,相关函数会自动去掉可执行文件路径中的空格

我们可以构造”C:\Windows \System32”【Windiws后面有一个空格】,系统检查时会自动去除空格,即可通过最后一个检查同时满足2.条件。
同时我们可以在”C:\Windows \System32”目录下放置恶意DLL,根据系统会先加载应用程序的目录里的DLL成功加载恶意DLL。

总结一下,我们可以构造一个路径带有尾空格的可信任目录,将一个autoElevate属性为True的白名单程序复制到构造好的模拟可信任目录。接着构造恶意DLL放入该目录下来实现BypassUAC。

实战

靶机:Windows 7 Professional

当前权限:

image-20230409173138678

我们先确定HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode是否已经开启

1
reg query "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode"

image-20230409173826129

好家伙,还真没有。

那我们自己加上去:

1
reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager" /v SafeDllSearchMode /t REG_DWORD /d "1" /f

image-20230409174544036

哎呀,失败了,这个应该是要管理员权限,那我们为了环境的搭建我们先作个弊,用管理员权限把这个键值加上去

image-20230409174653264

image-20230409174715983

接着我们来构造模拟可信任目录:

1
2
md "\\?\C:\Windows "
md "\\?\C:\Windows \System32"

寻找一个

1
sigcheck.exe /accepteula -m C:\Windows\System32\WinSAT.exe | findstr /i autoElevate
1
strings.exe /accepteula -s C:\Windows\System32\*.exe | findstr /i "autoElevate"

我们选择这个dfrgui:

image-20230409222634651

我们打开process monitor,增加这两条过滤【最新版的process monitor不支持win7,需要用旧版的】

image-20230409222918820

我们把dfrgui.exe放到我们之前创建的模拟可信任目录

image-20230409223512072

我们在这里打开dfrgui.exe,查看process monitor,确认下这次要劫持的dll【VirDisk.dll】

image-20230409223810541

我们使用ExportsToC++工具获取原DLL文件的导出函数并且生成C++代码:

直接运行会报错:

image-20230409224301783

我们找到Visual Studio Tools里面点开这个命令行运行ExportsToC++.exe

image-20230409203849283

image-20230409204016588

image-20230409224440712

我们到visual studio里创建一个DLL项目,在生成的代码之前加入一行劫持代码:

image-20230409225805467

获得的dll放入之前的模拟可信任目录

image-20230409230212382

点击dfrgui.exe:

我们看到这里已经成功执行了我们的恶意dll,但还是没有成功弹出管理员权限的CMD !!!!!

image-20230409230347569