DLL劫持-模拟可信任目录
今天在学习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:
- 加载应用程序的目录;
- 系统目录,使用
GetSystemDirectory
函数获取该目录的路径; - 16位系统目录,没有获取该目录路径的函数,但会对该目录进行搜索;
- Windows目录,使用
GetWindowsDirectory
函数获取该目录的路径; - 当前目录;
- PATH环境变量中列出的目录,这里不包括
App Paths
注册表项指定的每个应用程序路径,在计算DLL搜索路径是不会使用到App Paths
键。
系统允许程序自动提升权限的三个条件
第一:解析autoElevate
属性字段的值,需要其为True
autoElevate
属性的值可以用以下两个工具来获取
sigcheck【https://docs.microsoft.com/zh-cn/sysinternals/downloads/sigcheck】
查看ComputerDefaults.exe的autoElevate
属性
1 | sigcheck.exe /accepteula -m C:\Windows\System32\ComputerDefaults.exe | findstr /i autoElevate |
strings【https://docs.microsoft.com/en-us/sysinternals/downloads/strings】
查看目录下所有exe的autoElevate
属性
1 | strings.exe /accepteula -s C:\Windows\System32\*.exe | findstr /i "autoElevate" |
Manifesto【https://link.zhihu.com/?target=https%3A//github.com/g3rzi/Manifesto】
个人感觉这个最顶,图形化很方便
第二:检查可执行文件的签名
意味着无法通过传递Manifest信息或冒充可执行文件名来实现自动权限提升
第三:检查可执行文件是否位于系统可信任目录中
可信任目录如C:\Windows\System32
系统检查可信任目录时,相关函数会自动去掉可执行文件路径中的空格。
模拟可信任目录
我们根据基础知识里的:
- 系统会先加载应用程序的目录里的DLL
- 系统会检查可执行文件是否位于系统可信任目录中如
C:\Windows\System32
- 系统检查可信任目录时,相关函数会自动去掉可执行文件路径中的空格
我们可以构造”C:\Windows \System32”【Windiws后面有一个空格】,系统检查时会自动去除空格,即可通过最后一个检查同时满足2.条件。
同时我们可以在”C:\Windows \System32”目录下放置恶意DLL,根据系统会先加载应用程序的目录里的DLL成功加载恶意DLL。
总结一下,我们可以构造一个路径带有尾空格的可信任目录,将一个autoElevate
属性为True的白名单程序复制到构造好的模拟可信任目录。接着构造恶意DLL放入该目录下来实现BypassUAC。
实战
靶机:Windows 7 Professional
当前权限:
我们先确定HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode
是否已经开启
1 | reg query "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode" |
好家伙,还真没有。
那我们自己加上去:
1 | reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager" /v SafeDllSearchMode /t REG_DWORD /d "1" /f |
哎呀,失败了,这个应该是要管理员权限,那我们为了环境的搭建我们先作个弊,用管理员权限把这个键值加上去
接着我们来构造模拟可信任目录:
1 | md "\\?\C:\Windows " |
寻找一个
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:
我们打开process monitor,增加这两条过滤【最新版的process monitor不支持win7,需要用旧版的】
我们把dfrgui.exe放到我们之前创建的模拟可信任目录
我们在这里打开dfrgui.exe,查看process monitor,确认下这次要劫持的dll【VirDisk.dll】
我们使用ExportsToC++工具获取原DLL文件的导出函数并且生成C++代码:
直接运行会报错:
我们找到Visual Studio Tools里面点开这个命令行运行ExportsToC++.exe
我们到visual studio里创建一个DLL项目,在生成的代码之前加入一行劫持代码:
获得的dll放入之前的模拟可信任目录
点击dfrgui.exe:
我们看到这里已经成功执行了我们的恶意dll,但还是没有成功弹出管理员权限的CMD !!!!!