From 9be76adb2317e1da5b01169201886753541679bc Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Sun, 17 Sep 2023 21:33:14 +0100 Subject: [PATCH] [*] Further drop required symbols from OLE (COM) and SHELL32 (NT Shell) [*] Optimize NT file and URI opener --- Source/AuProcAddresses.NT.cpp | 8 ++ Source/AuProcAddresses.NT.hpp | 68 +++++++++++++---- Source/CmdLine/AuCmdLinePlatform.cpp | 7 +- Source/IO/FS/Resources.cpp | 47 +++++++++--- Source/Processes/AuOpen.Win32.cpp | 110 +++++++++++++++++---------- 5 files changed, 170 insertions(+), 70 deletions(-) diff --git a/Source/AuProcAddresses.NT.cpp b/Source/AuProcAddresses.NT.cpp index d0b83876..8d5ce010 100644 --- a/Source/AuProcAddresses.NT.cpp +++ b/Source/AuProcAddresses.NT.cpp @@ -36,6 +36,7 @@ namespace Aurora ADD_LOAD_LIB(DbgHelper); ADD_LOAD_LIB(WinTrust); ADD_LOAD_LIB(IPHelper); + ADD_LOAD_LIB(COM); #define ADD_GET_PROC(name, proc) \ if (h ## name) \ @@ -156,8 +157,15 @@ namespace Aurora ADD_GET_PROC(BCrypt, BCryptGenRandom) ADD_GET_PROC(Theme, SetWindowTheme) + + ADD_GET_PROC(COM, CoInitializeEx) + ADD_GET_PROC(COM, CoUninitialize) + ADD_GET_PROC(COM, CoTaskMemFree) ADD_GET_PROC(Shell, SHGetKnownFolderPath) + ADD_GET_PROC(Shell, SHGetFolderPathA) + ADD_GET_PROC(Shell, CommandLineToArgvW) + ADD_GET_PROC(Shell, ShellExecuteW) if (pNtCreateKeyedEvent && diff --git a/Source/AuProcAddresses.NT.hpp b/Source/AuProcAddresses.NT.hpp index 8f6be85d..63126ec4 100644 --- a/Source/AuProcAddresses.NT.hpp +++ b/Source/AuProcAddresses.NT.hpp @@ -51,6 +51,7 @@ namespace Aurora static const wchar_t *kDbgHelperDllName { L"dbghelp.dll" }; static const wchar_t *kWinTrustDllName { L"WINTRUST.dll" }; static const wchar_t *kIPHelperDllName { L"IPHLPAPI.dll" }; + static const wchar_t *kCOMDllName { L"ole32.dll" }; struct WIN32_MEMORY_RANGE_ENTRY2 { @@ -411,13 +412,6 @@ namespace Aurora HANDLE hThread ); - inline HRESULT(__stdcall *pSHGetKnownFolderPath)( - const GUID & rfid, - DWORD dwFlags, - HANDLE hToken, - PWSTR * ppszPath - ); - // dbghelp inline DWORD(__stdcall *pUnDecorateSymbolName)( @@ -507,18 +501,62 @@ namespace Aurora // IP Helper inline ULONG(__stdcall *pGetAdaptersAddresses)( - ULONG Family, - ULONG Flags, - PVOID Reserved, - IP_ADAPTER_ADDRESSES *AdapterAddresses, - PULONG SizePointer + ULONG Family, + ULONG Flags, + PVOID Reserved, + IP_ADAPTER_ADDRESSES * AdapterAddresses, + PULONG SizePointer ); inline ULONG(__stdcall *pGetAdaptersInfo)( - _IP_ADAPTER_INFO * AdapterInfo, - PULONG SizePointer + _IP_ADAPTER_INFO * AdapterInfo, + PULONG SizePointer ); - + + // COM + + inline HRESULT(__stdcall *pCoInitializeEx)( + LPVOID pvReserved, + DWORD dwCoInit + ); + + inline void(__stdcall *pCoTaskMemFree)( + LPVOID pv + ); + + inline void(__stdcall *pCoUninitialize)(); + + // Shell + + inline HRESULT(__stdcall *pSHGetKnownFolderPath)( + const GUID &rfid, + DWORD dwFlags, + HANDLE hToken, + PWSTR *ppszPath + ); + + inline HINSTANCE(__stdcall *pShellExecuteW)( + HWND hwnd, + LPCWSTR lpOperation, + LPCWSTR lpFile, + LPCWSTR lpParameters, + LPCWSTR lpDirectory, + INT nShowCmd + ); + + inline HRESULT(__stdcall *pSHGetFolderPathA)( + HWND hwnd, + int csidl, + HANDLE hToken, + DWORD dwFlags, + LPSTR pszPath + ); + + inline LPWSTR *(__stdcall *pCommandLineToArgvW)( + LPCWSTR lpCmdLine, + int * pNumArgs + ); + inline bool gUseNativeWaitMutex {}; inline bool gUseNativeWaitCondvar {}; inline bool gUseNativeWaitSemapahore {}; diff --git a/Source/CmdLine/AuCmdLinePlatform.cpp b/Source/CmdLine/AuCmdLinePlatform.cpp index 2dd0458e..4bad65f0 100644 --- a/Source/CmdLine/AuCmdLinePlatform.cpp +++ b/Source/CmdLine/AuCmdLinePlatform.cpp @@ -77,8 +77,13 @@ namespace Aurora::CmdLine #if defined(AURORA_PLATFORM_WIN32) + if (!pCommandLineToArgvW) + { + return {}; + } + int count {}; - auto temp = CommandLineToArgvW(cmd, &count); + auto temp = pCommandLineToArgvW(cmd, &count); for (int i = 0; i < count; i++) { diff --git a/Source/IO/FS/Resources.cpp b/Source/IO/FS/Resources.cpp index bc3c949c..bf2f9915 100644 --- a/Source/IO/FS/Resources.cpp +++ b/Source/IO/FS/Resources.cpp @@ -140,32 +140,55 @@ namespace Aurora::IO::FS return {}; } + + static AuString GetSpecialDirOldOS(REFKNOWNFOLDERID rfid) + { + if (!pSHGetFolderPathA) + { + return ""; + } + + if (auto opt = GUIDTOCISL(rfid)) + { + AuString temp(MAX_PATH, '\x00'); + if (pSHGetFolderPathA(0, *opt, 0, 0, temp.data()) == S_OK) + { + return temp; + } + } + else + { + return ""; + } + } + static AuString GetSpecialDir(REFKNOWNFOLDERID rfid) { PWSTR directory; if (!pSHGetKnownFolderPath) - { - if (auto opt = GUIDTOCISL(rfid)) - { - AuString temp(MAX_PATH, '\x00'); - if (SHGetFolderPathA(0, *opt, 0, 0, temp.data()) == S_OK) - { - return temp; - } - } - - return ""; + { + return GetSpecialDirOldOS(rfid); } if (pSHGetKnownFolderPath(rfid, KF_FLAG_DEFAULT, NULL, &directory) != S_OK) { + AuString str; + if ((str = GetSpecialDirOldOS(rfid)).size()) + { + return str; + } + SysPanic("Couldn't get known special directory path of [MS:{}-{}-{}-{}{}{}{}{}{}{}{}] with a NULL access token", rfid.Data1, rfid.Data2, rfid.Data3, rfid.Data4[0], rfid.Data4[1], rfid.Data4[2], rfid.Data4[3], rfid.Data4[4], rfid.Data4[5], rfid.Data4[6], rfid.Data4[7]); } auto ret = Locale::ConvertFromWChar(directory); - CoTaskMemFree(directory); + if (pCoTaskMemFree) + { + pCoTaskMemFree(directory); + } + return ret; } diff --git a/Source/Processes/AuOpen.Win32.cpp b/Source/Processes/AuOpen.Win32.cpp index 6320eb67..dee81fd6 100644 --- a/Source/Processes/AuOpen.Win32.cpp +++ b/Source/Processes/AuOpen.Win32.cpp @@ -8,17 +8,14 @@ #include #include "AuProcesses.hpp" #include "AuOpen.Win32.hpp" - -#include -#include - #include -#include "Objbase.h" -#include "shellapi.h" + +#define COINIT_APARTMENTTHREADED 0x2 +#define COINIT_DISABLE_OLE1DDE 0x4 namespace Aurora::Processes { - static AuList gOpenItems; + static AuList> gOpenItems; static AuThreadPrimitives::ConditionMutex gCondMutex; static AuThreadPrimitives::ConditionVariable gCondVariable(AuUnsafeRaiiToShared(gCondMutex.AsPointer())); static AuThreads::ThreadUnique_t gOpenerThread; @@ -31,17 +28,61 @@ namespace Aurora::Processes { try { - for (const auto &open : gOpenItems) + for (const auto &[uri, type] : gOpenItems) { - if (open.empty()) continue; // [*1] + bool bDirExists {}; + bool bFileExists {}; - ShellExecuteW(nullptr, - AuIOFS::DirExists(open) ? L"explore" : L"open", - Locale::ConvertFromUTF8(open).c_str(), - nullptr, - nullptr, - SW_SHOWNORMAL); + if (uri.empty()) + { + continue; + } + + if (!pShellExecuteW) + { + SysPushErrorUninitialized("Cannot open URIs yet"); + continue; + } + + bFileExists = AuIOFS::FileExists(uri); + + if (!type) + { + bDirExists = AuIOFS::DirExists(uri); + + if (!bFileExists && + !bDirExists) + { + SysPushErrorGeneric("Exploit attempt? Attempted to open non-existent file/directory. (request: {})", uri); + continue; + } + + if (bFileExists) + { + if (!AuFS::IsFileBlocked(uri)) + { + SysPushErrorGeneric("Exploit attempt? Attempted to open untrusted file/directory. (request: {})", uri); + continue; + } + } + } + else + { + if (bFileExists) + { + SysPushErrorGeneric("Exploit attempt? Attempted to open existing file/directory via URI ({})", uri); + continue; + } + } + + pShellExecuteW(nullptr, + bDirExists ? L"explore" : L"open", + Locale::ConvertFromUTF8(uri).c_str(), + nullptr, + nullptr, + SW_SHOWNORMAL); } + gOpenItems.clear(); gCondVariable->WaitForSignal(); } @@ -55,9 +96,17 @@ namespace Aurora::Processes static void OpenerThread() { - (void)CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (pCoInitializeEx) + { + (void)pCoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + } + RunTasks(); - CoUninitialize(); + + if (pCoUninitialize) + { + pCoUninitialize(); + } } void InitWin32Opener() @@ -81,21 +130,14 @@ namespace Aurora::Processes AUKN_SYM void OpenUri(const AuString &uri) { - if (AuFS::FileExists(uri)) - { - SysPushErrorGeneric("Exploit attempt? Attempted to open existing file/directory via URI ({})", uri); - return; - } - AU_LOCK_GUARD(gCondMutex); - AuTryInsert(gOpenItems, uri); + AuTryInsert(gOpenItems, AuMakePair(uri, true)); gCondVariable->Signal(); } AUKN_SYM void OpenFile(const AuString &file) { auto path = AuIOFS::NormalizePathRet(file); - bool bFileExists {}; if (path.empty()) { @@ -103,25 +145,9 @@ namespace Aurora::Processes return; } - if (!(bFileExists = AuFS::FileExists(path)) && - !AuFS::DirExists(path)) - { - SysPushErrorGeneric("Exploit attempt? Attempted to open non-existent file/directory. (request: {})", file); - return; - } - - if (bFileExists) - { - if (!AuFS::IsFileBlocked(path)) - { - SysPushErrorGeneric("Exploit attempt? Attempted to open untrusted file/directory. (request: {})", file); - return; - } - } - { AU_LOCK_GUARD(gCondMutex); - AuTryInsert(gOpenItems, AuMove(path)); + AuTryInsert(gOpenItems, AuMove(AuMakePair(AuMove(path), false))); gCondVariable->Signal(); } }