Skip to content

Commit

Permalink
Fea #145, 改善跨模块边界安全性
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed Feb 23, 2025
1 parent 603173a commit 0b4abf4
Show file tree
Hide file tree
Showing 8 changed files with 7,586 additions and 7,484 deletions.
48 changes: 24 additions & 24 deletions ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,33 @@
## api-ms-win-core-threadpool-l1-2-0.dll
| 函数 | Fallback
| ---- | -----------
| CreateThreadpoolWork | 内部实现。
| CloseThreadpoolWork | 内部实现。
| TrySubmitThreadpoolCallback | 调用QueueUserWorkItem。
| SubmitThreadpoolWork | 调用QueueUserWorkItem。
| WaitForThreadpoolWorkCallbacks | 内部实现。
| CreateThreadpoolTimer | 内部实现。
| CloseThreadpoolTimer | 调用DeleteTimerQueueTimer。
| SetThreadpoolTimer | 调用CreateTimerQueueTimer。
| WaitForThreadpoolTimerCallbacks | 调用WaitForSingleObject。
| CreateThreadpoolWork | 内部实现。警告,此函数请勿跨模块使用!!!
| CloseThreadpoolWork | 内部实现。警告,此函数请勿跨模块使用!!!
| TrySubmitThreadpoolCallback | 调用QueueUserWorkItem。警告,此函数请勿跨模块使用!!!
| SubmitThreadpoolWork | 调用QueueUserWorkItem。警告,此函数请勿跨模块使用!!!
| WaitForThreadpoolWorkCallbacks | 内部实现。警告,此函数请勿跨模块使用!!!
| CreateThreadpoolTimer | 内部实现。警告,此函数请勿跨模块使用!!!
| CloseThreadpoolTimer | 调用DeleteTimerQueueTimer。警告,此函数请勿跨模块使用!!!
| SetThreadpoolTimer | 调用CreateTimerQueueTimer。警告,此函数请勿跨模块使用!!!
| WaitForThreadpoolTimerCallbacks | 调用WaitForSingleObject。警告,此函数请勿跨模块使用!!!
| SetEventWhenCallbackReturns | 内部实现。
| ReleaseSemaphoreWhenCallbackReturns | 内部实现。
| ReleaseMutexWhenCallbackReturns | 内部实现。
| LeaveCriticalSectionWhenCallbackReturns | 内部实现。
| FreeLibraryWhenCallbackReturns | 内部实现。
| CreateThreadpoolWait | 内部实现。
| CloseThreadpoolWait | 调用UnregisterWait。
| SetThreadpoolWait | 调用RegisterWaitForSingleObject。
| WaitForThreadpoolWaitCallbacks | 调用WaitForSingleObject。
| CreateThreadpoolIo | 调用BindIoCompletionCallback。
| CloseThreadpoolIo | 内部实现。
| StartThreadpoolIo | 内部实现。
| CancelThreadpoolIo | 内部实现。
| WaitForThreadpoolIoCallbacks | 调用WaitForSingleObject。
| CreateThreadpool | 内部实现。
| CloseThreadpool | 内部实现。
| SetThreadpoolThreadMaximum | 内部实现,自己控制最大并行数量。
| SetThreadpoolThreadMinimum | 忽略,并总是返回成功。
| CloseThreadpoolWait | 调用UnregisterWait。警告,此函数请勿跨模块使用!!!
| SetThreadpoolWait | 调用RegisterWaitForSingleObject。警告,此函数请勿跨模块使用!!!
| WaitForThreadpoolWaitCallbacks | 调用WaitForSingleObject。警告,此函数请勿跨模块使用!!!
| CreateThreadpoolIo | 调用BindIoCompletionCallback。警告,此函数请勿跨模块使用!!!
| CloseThreadpoolIo | 内部实现。警告,此函数请勿跨模块使用!!!
| StartThreadpoolIo | 内部实现。警告,此函数请勿跨模块使用!!!
| CancelThreadpoolIo | 内部实现。警告,此函数请勿跨模块使用!!!
| WaitForThreadpoolIoCallbacks | 调用WaitForSingleObject。警告,此函数请勿跨模块使用!!!
| CreateThreadpool | 内部实现。警告,此函数请勿跨模块使用!!!
| CloseThreadpool | 内部实现。警告,此函数请勿跨模块使用!!!
| SetThreadpoolThreadMaximum | 内部实现,自己控制最大并行数量。警告,此函数请勿跨模块使用!!!
| SetThreadpoolThreadMinimum | 忽略,并总是返回成功。警告,此函数请勿跨模块使用!!!
| CallbackMayRunLong | 自己估算系统剩余可用线程数。

## api-ms-win-core-winrt-l1-1-0.dll
Expand Down Expand Up @@ -428,9 +428,9 @@
| InitializeSynchronizationBarrier | 调用CreateEvent。
| EnterSynchronizationBarrier | 调用WaitForSingleObject。
| DeleteSynchronizationBarrier | 调用CloseHandle。
| WaitOnAddress | 调用NtWaitForKeyedEvent。警告,此函数请勿跨模块使用!!!
| WakeByAddressSingle | 调用NtReleaseKeyedEvent。警告,此函数请勿跨模块使用!!!
| WakeByAddressAll | 调用NtReleaseKeyedEvent。警告,此函数请勿跨模块使用!!!
| WaitOnAddress | 调用NtWaitForKeyedEvent。
| WakeByAddressSingle | 调用NtReleaseKeyedEvent。
| WakeByAddressAll | 调用NtReleaseKeyedEvent。
| GetCurrentProcessorNumber | 调用cpuid。
| GetCurrentProcessorNumberEx | 调用GetCurrentProcessorNumber。
| GetNumaNodeProcessorMask | 假定所有CPU都在当前Numa。
Expand Down
95 changes: 95 additions & 0 deletions src/Thunks/YY_Thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1541,3 +1541,98 @@ static __forceinline void* __fastcall try_get_proc_address_from_first_available_

return try_get_proc_address_from_dll(_ProcInfo);
}

_Ret_notnull_ static YY_ThunksSharedData* __fastcall GetYY_ThunksSharedData() noexcept
{
if (auto _pData = s_pYY_ThunksSharedData)
return _pData;

wchar_t _szYY_ThunksSharedDataMapNameBuffer[MAX_PATH] = {};
YY::Thunks::internal::StringBuffer<wchar_t> _szBuffer(_szYY_ThunksSharedDataMapNameBuffer, _countof(_szYY_ThunksSharedDataMapNameBuffer));
_szBuffer.AppendString(L"YY_ThunksSharedData_53302349-F6BE-49C4-AC98-DA275C0CE653_");

_szBuffer.AppendUint32(GetCurrentProcessId());
#if defined(_X86_)
_szBuffer.AppendString(L"_x86");
#elif defined(_AMD64_)
_szBuffer.AppendString(L"_amd64");
#elif defined(_ARM_)
_szBuffer.AppendString(L"_arm");
#elif defined(_ARM64_)
_szBuffer.AppendString(L"_arm64");
#else
#error "未知CPU架构"
#endif

SYSTEM_INFO _SystemInfo;
GetSystemInfo(&_SystemInfo);
const auto _cbSharedData = max(_SystemInfo.dwPageSize * 2, 4096 * 2);

YY_ThunksSharedData* _pData = nullptr;

auto _hSharedData = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, _cbSharedData, _szYY_ThunksSharedDataMapNameBuffer);
if (_hSharedData)
{
_pData = (YY_ThunksSharedData*)MapViewOfFile(_hSharedData, FILE_MAP_WRITE, 0, 0, _cbSharedData);

// 首次创建时不关闭 FileMapping,这是为了保证进程生命周期内其中的数据不被销毁,意外导致数据丢失
if (_pData == nullptr || InterlockedBitTestAndSet(&_pData->fYY_ThunksInitFlags, 0))
{
// CloseHandle 内部也会调用GetYY_ThunksSharedData。主动获取CloseHandle,避免无限递归。
// /~https://github.com/Chuyu-Team/YY-Thunks/issues/147
__if_exists(YY::Thunks::try_get_CloseHandle)
{
const auto CloseHandle = YY::Thunks::try_get_CloseHandle();
}
CloseHandle(_hSharedData);
}
}

if (!_pData)
{
_pData = &s_DefaultSharedData;
}

auto _pLastSharedData = (YY_ThunksSharedData*)InterlockedCompareExchangePointer((void**)&s_pYY_ThunksSharedData, _pData, NULL);
if (_pLastSharedData)
{
if (_pData != &s_DefaultSharedData)
{
UnmapViewOfFile(_pData);
}

return _pLastSharedData;
}
else
{
return _pData;
}
}

static void __fastcall FreeYY_ThunksSharedData(YY_ThunksSharedData* _pSharedData) noexcept
{
if (!_pSharedData)
return;

#if (YY_Thunks_Target < __WindowsNT5_1_SP1)
YY::Thunks::internal::UnicodeStringFree(_pSharedData->sDllDirectory);
#endif

#if YY_Thunks_Target < __WindowsNT6_2
auto _pItem = _pSharedData->DllDirectoryList.pFirst;
_pSharedData->DllDirectoryList.pFirst = nullptr;
_pSharedData->DllDirectoryList.pLast = nullptr;

while (_pItem)
{
auto _pNext = _pItem->pNext;
YY::Thunks::internal::Free(_pNext);
_pItem = _pNext;
}
#endif

#if (YY_Thunks_Target < __WindowsNT6)
if (_pSharedData->hGlobalKeyedEventHandle)
CloseHandle(_pSharedData->hGlobalKeyedEventHandle);
#endif
}
Loading

0 comments on commit 0b4abf4

Please sign in to comment.