随着最近 KeePass2 有争议的 CVE-2023-24055 以及围绕它的所有大惊小怪,它激励我完成我去年开始的一个小项目。
我的目标是看看我是否能找到一种方法来拦截KeePass2数据库的主密码。
为了好玩和学习ofc。
在本文中,我们将介绍:
- DLL 劫持
- 挂钩窗口 API
介绍
想象一下这个。
您正在参与,工作站上的管理员,刚刚检索到数据库。KeePass2
让我们找到另一种方法来获得它.Master Password
目录
DLL 劫持
是史蒂夫达斯吗?
DLL 劫持是一种攻击类型,您可以在其中利用应用程序的搜索顺序来加载动态链接库。
当应用程序尝试加载 DLL 文件时,它将按特定顺序搜索该文件。顺序如下:
- 从中加载应用程序的目录
- 系统目录:
C:\Windows\System32
- 16 位系统目录:
C:\Windows\System
- 视窗目录:
C:\Windows
- 当前目录
- 环境变量中指定的目录
PATH
如果攻击者能够将恶意 DLL 文件放置在与合法 DLL 文件同名的其中一个目录中,则应用程序将加载恶意 DLL 而不是合法 DLL,从而允许攻击者在此过程中执行任意代码。
这也适用于KeePass吗?
目标 DLL
查找潜在可劫持 DLL 的最简单方法是使用 promon 进行搜索。在返回错误 的 DLL 上搜索,例如此处的:CreateFile
NAME NOT FOUND
发生了什么事情?
在这里,KeePass 尝试访问名为 的 DLL,但尝试将其加载到自己的安装文件夹中。
但是,这通常是系统 DLL,存在于 :UxTheme.dll
C:\Program Files\KeePass Password Safe 2
C:\Windows\System32
因此,此 DLL 可能是劫持的良好候选项。
让我们编译一个 DLL,并尝试查看如果我们重命名它是否会加载它。我们将使用此代码:KeePass2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
BOOL APIENTRY <strong>DllMain</strong>( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { WPP_INIT_TRACING(L"Test"); <strong>switch</strong> (ul_reason_for_call) { <strong>case</strong> DLL_PROCESS_ATTACH: TraceEvents(TRACE_LEVEL_VERBOSE, GENERAL, "[+ dllmain] DLL_PROCESS_ATTACH\n"); } <strong>return</strong> TRUE; } |
请注意调用 而不是 .这是因为当我们使用 DLL 时,没有简单的方法来获取其输出。TraceEvents
printf
TraceEvents
使用 Windows 软件跟踪预处理器 (WPP),它是 ETW 的一个组件。
我们将能够在 TraceView 中看到我们的事件。
现在我们有了 DLL,让我们将其移动到并将其重命名为 :C:\Program Files\KeePass Password Safe 2
UxTheme.dll
并运行KeePass:
是的!!成功了。我们在 TraceView 中有一个日志,显示我们的 DLL 加载在 .KeePass2
这很容易。现在怎么办?
挂钩窗口 API
挂钩允许您拦截和/或修改给定程序调用的函数的行为。在我们的例子中,我们希望能够记录参数并返回Windows API调用的值。
在下图中,您可以看到正常的 API 调用(绿色)与挂钩的 API 调用(红色):
有趣的是,这也是用户空间AV / EDR监控API调用的方式。
我开始研究一个自定义钩子引擎,然后偶然发现了微软自己的库来做到这一点: 绕道而行
我不会详细介绍钩子的实现,因为文档可在线获得。
消息框示例
让我们从简单的通话开始。MessageBoxW
1 2 3 4 5 6 7 |
MessageBoxW( NULL, TEXT("Hello Twitter!"), TEXT("SimpleEXE"), MB_OK ); |
如果我们看一下 MSDN 上的 MessageBoxW 文档,我们会得到这个函数原型:
1 2 3 4 5 6 7 |
<strong>int</strong> <strong>MessageBoxW</strong>( [in, optional] HWND hWnd, [in, optional] LPCWSTR lpText, [in, optional] LPCWSTR lpCaption, [in] UINT uType ); |
我们记录 and 参数的钩子函数看起来像这样:lpText
lpCaption
1 2 3 4 5 6 7 |
<strong>int</strong> (<strong>*</strong>real_MessageBoxW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) <strong>=</strong> MessageBoxW; <strong>int</strong> <strong>hook_MessageBoxW</strong>(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) { TraceEvents(TRACE_LEVEL_VERBOSE, GENERAL, "[+ Hook] MessageBoxW(lpText=%ls, lpCaption=%ls, uType=%u)", lpText, lpCaption, uType); <strong>return</strong> real_MessageBoxW(hWnd, lpText, lpCaption, uType); } |
这段代码非常简单。当被调用时,它将首先记录参数使用,然后再恢复执行到“real”。MessageBoxW
TraceEvents
MessageBoxW
让我们试试吧!
钩住盒子
这是使用自定义加载程序进行测试的,该加载程序在启动进程时注入 DLL。当出现时:MessageBox
函数调用记录在跟踪视图中!有了论据和所有。
现在,想象一下能够在敏感进程中运行代码并能够拦截处理敏感数据的函数。
自动代码生成
但首先,代码生成。
现在我们有了第一个钩子的工作示例,我们必须扩大它。Windows API中有很多功能。请记住,我们的目标是在键入数据库时截获数据库的主密码。
我显然不是自己为每个Windows API函数编写代码。不是没有人有时间这样做。我使用了一个 Python 脚本和一个 Json 文件来生成挂钩 dll 的代码。
MSDN 是文档的最佳朋友,或者您也可以在 Visual Studio 中检查头文件。
以下是 json 文件的快速选择:
而这一代:
默认代码生成调用以记录函数调用和参数。下面是生成的代码的示例:TraceEvents
它看起来很像我们第一个示例中的代码,但只要将函数添加到 json 文件中,它就会自动生成。我还添加了自定义代码片段,以在必要时扩展功能。这样我们就可以记录返回值,以特定方式打印参数等。
就这样,我们有工作代码生成。我们可以通过将原型添加到 json 文件中来监控我们想要的任何 Windows API 函数!
当一切都走到一起
在测试时,我将搜索范围缩小到处理字符串和剪贴板活动的函数。经过一些研究,我为我们的用例发现了两个有趣的 API 调用:
- 设置剪贴板数据:以指定的剪贴板格式将数据放在剪贴板上
HANDLE SetClipboardData( [in] UINT uFormat, [in, optional] HANDLE hMem );
- ToUnicodeEx:将指定的虚拟键代码和键盘状态转换为相应的一个或多个 Unicode 字符
int ToUnicodeEx( [in] UINT wVirtKey, [in] UINT wScanCode, [in] const BYTE *lpKeyState, [out] LPWSTR pwszBuff, [in] int cchBuff, [in] UINT wFlags, [in, optional] HKL dwhkl );
为这两个函数生成钩子后,我们将 DLL 复制到并将其重命名为 .C:\Program Files\KeePass Password Safe 2
UxTheme.dll
现在,让我们再次运行并键入密码以解锁数据库:KeePass2
这有多酷?密码记录在跟踪视图中!
数据库中的条目也可以在按下时被拦截,这要归功于钩子:CTRL+C
SetClipboardData
结论
我还有一些工作要做才能将密码写入文件,但你明白了。希望你喜欢你今天读到的东西并学到了一些新东西。
我没有评论部分,但在平台消失之前在Twitter上给我发了一条消息哈哈。
有用的链接
https://learn.microsoft.com/en-us/sysinternals/
https://github.com/microsoft/Detours
https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/traceview https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/wpp-software-tracing
原文链接:https://skr1x.github.io/keepass-dll-hijacking/