From d44dd0334d442423799b0f2056189674f00a05bb Mon Sep 17 00:00:00 2001 From: mingkuang Date: Tue, 3 Mar 2020 19:19:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9Btry=5Fget=5Ffunction=E6=80=A7?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E5=90=8C=E6=97=B6=E5=A2=9E=E5=BC=BAYY-Thunks?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ReadMe.md | 3 +- src/Build.cmd | 2 +- src/YY_Thunks.cpp | 27 ++++++----- src/YY_Thunks.h | 114 ++++++++++++++++++++++++++++------------------ 4 files changed, 86 insertions(+), 60 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 1a46ee3..a417995 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -331,7 +331,7 @@ YY-Thunks(鸭船),存在的目的就是抹平不同系统的差异,编 * 添加 CreateSymbolicLinkW(A) * 添加 ReOpenFile -### 1.0.2.3 - 扩充实现(2020-02-26 22:00) +### 1.0.2.4 - 扩充实现(2020-03-03 19:00) * 添加 CompareStringEx * 添加 CompareStringOrdinal * 添加 SetFilePointerEx(Windows 2000模式) @@ -344,3 +344,4 @@ YY-Thunks(鸭船),存在的目的就是抹平不同系统的差异,编 * 添加 QueryDepthSList(Windows 2000模式) * 添加 InterlockedPushEntrySList(Windows 2000模式) * 添加 InterlockedPopEntrySList(Windows 2000模式) +* 优化实现,改进YY-Thunks性能与体积 diff --git a/src/Build.cmd b/src/Build.cmd index 1e23566..cbe0824 100644 --- a/src/Build.cmd +++ b/src/Build.cmd @@ -22,7 +22,7 @@ goto:eof cl /O1 /Os /Oi /GS- /arch:IA32 /Z7 /MT /Fo"objs\\%Platform%\\%1" /Zl /c /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" "%~dp0YY_Thunks.cpp" ::½øÐк¯ÊýÃû³ƽøÐÐÐÞÕý __imp__%s_%u -> __imp__%s@%u -LibMaker.exe FixObj "%~dp0..\\objs\\%Platform%\\%1" /WeakExternFix:__security_cookie=%PointType% +LibMaker.exe FixObj "%~dp0..\\objs\\%Platform%\\%1" /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__YY_Thunks_Process_Terminating=4 LibMaker.exe AppendWeak /MACHINE:%Platform% /DEF:"%~dp0def\\%Platform%\\PSAPI2Kernel32.def" /OUT:"%~dp0..\\objs\\%Platform%\\%1" diff --git a/src/YY_Thunks.cpp b/src/YY_Thunks.cpp index 481c140..65a935e 100644 --- a/src/YY_Thunks.cpp +++ b/src/YY_Thunks.cpp @@ -3,18 +3,18 @@ -#define _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) \ - _APPLY(ntdll, "ntdll" ) \ - _APPLY(kernel32, "kernel32" ) \ - _APPLY(psapi, "psapi" ) \ - _APPLY(version, "version" ) \ - _APPLY(advapi32, "advapi32" ) \ - _APPLY(user32, "user32" ) \ - _APPLY(ws2_32, "ws2_32" ) \ - _APPLY(shell32, "shell32" ) \ - _APPLY(shlwapi, "shlwapi" ) \ - _APPLY(api_ms_win_core_winrt_l1_1_0, "api-ms-win-core-winrt-l1-1-0" ) \ - _APPLY(api_ms_win_core_winrt_string_l1_1_0, "api-ms-win-core-winrt-string-l1-1-0" ) +#define _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) \ + _APPLY(ntdll, "ntdll" , USING_UNSAFE_LOAD ) \ + _APPLY(kernel32, "kernel32" , USING_UNSAFE_LOAD ) \ + _APPLY(psapi, "psapi" , 0 ) \ + _APPLY(version, "version" , 0 ) \ + _APPLY(advapi32, "advapi32" , 0 ) \ + _APPLY(user32, "user32" , 0 ) \ + _APPLY(ws2_32, "ws2_32" , 0 ) \ + _APPLY(shell32, "shell32" , 0 ) \ + _APPLY(shlwapi, "shlwapi" , 0 ) \ + _APPLY(api_ms_win_core_winrt_l1_1_0, "api-ms-win-core-winrt-l1-1-0" , 0 ) \ + _APPLY(api_ms_win_core_winrt_string_l1_1_0, "api-ms-win-core-winrt-string-l1-1-0", 0 ) //ȫ¾ֿÉÄÜʹÓõ½µĺ¯Êý @@ -90,8 +90,7 @@ return reinterpret_cast(try_get_function( \ &_CRT_CONCATENATE( pFun_ ,_FUNCTION), \ _CRT_STRINGIZE(_FUNCTION), \ - _CRT_CONCATENATE(try_get_module_, _MODULE)(), \ - _CRT_CONCATENATE(module_name_, _MODULE))); \ + &_CRT_CONCATENATE(try_get_module_, _MODULE))); \ } #include "YY_Thunks_List.hpp" diff --git a/src/YY_Thunks.h b/src/YY_Thunks.h index 07ac9ae..8a17b99 100644 --- a/src/YY_Thunks.h +++ b/src/YY_Thunks.h @@ -49,12 +49,35 @@ else */ EXTERN_C const DWORD __YY_Thunks_Installed = YY_Thunks_Support_Version; +/* +导出一个外部弱符号,指示当前是否处于强行卸载模式。 + +EXTERN_C BOOL __YY_Thunks_Process_Terminating; + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + swtich(dwReason) + { + case DLL_PROCESS_DETACH: + //我们可以通过 lpReserved != NULL 判断,当前是否处于强行卸载模式。 + __YY_Thunks_Process_Terminating = lpReserved != NULL; + + …… + break; + …… +*/ +#if (YY_Thunks_Support_Version < NTDDI_WINXP) +//Windows 2000不支持RtlDllShutdownInProgress,因此依然引入__YY_Thunks_Process_Terminating +EXTERN_C extern BOOL __YY_Thunks_Process_Terminating; +#endif + #if (YY_Thunks_Support_Version < NTDDI_WIN6) static HANDLE _GlobalKeyedEventHandle; #endif +static uintptr_t __security_cookie_yy_thunks; -#define _APPLY(_SYMBOL, _NAME) \ +#define _APPLY(_SYMBOL, _NAME, ...) \ constexpr const wchar_t* _CRT_CONCATENATE(module_name_, _SYMBOL) = _CRT_WIDE(_NAME); _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) #undef _APPLY @@ -110,8 +133,8 @@ static PVOID __fastcall __CRT_DecodePointer( { return reinterpret_cast( __crt_rotate_pointer_value( - reinterpret_cast(Ptr) ^ __security_cookie, - __security_cookie % __crt_maximum_pointer_shift + reinterpret_cast(Ptr) ^ __security_cookie_yy_thunks, + __security_cookie_yy_thunks % __crt_maximum_pointer_shift ) ); } @@ -121,8 +144,8 @@ static PVOID __fastcall __CRT_EncodePointer(PVOID const Ptr) return reinterpret_cast( __crt_rotate_pointer_value( reinterpret_cast(Ptr), - __crt_maximum_pointer_shift - (__security_cookie % __crt_maximum_pointer_shift) - ) ^ __security_cookie + __crt_maximum_pointer_shift - (__security_cookie_yy_thunks % __crt_maximum_pointer_shift) + ) ^ __security_cookie_yy_thunks ); } @@ -237,6 +260,9 @@ static HMODULE __fastcall try_load_library_from_system_directory(wchar_t const* } +#define USING_UNSAFE_LOAD 0x00000001 + +template static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_t* module_name) noexcept { // First check to see if we've cached the module handle: @@ -253,7 +279,7 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_ // If we haven't yet cached the module handle, try to load the library. If // this fails, cache the sentinel handle value INVALID_HANDLE_VALUE so that // we don't attempt to load the module again: - HMODULE const new_handle = try_load_library_from_system_directory(module_name); + HMODULE const new_handle = (Flags & USING_UNSAFE_LOAD) ? LoadLibraryW(module_name) : try_load_library_from_system_directory(module_name); if (!new_handle) { if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(pModule, INVALID_HANDLE_VALUE)) @@ -277,23 +303,23 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_ return new_handle; } -#define _APPLY(_MODULE, _NAME) \ - static volatile HMODULE* __fastcall _CRT_CONCATENATE(try_get_module_, _MODULE)() noexcept \ +#define _APPLY(_MODULE, _NAME, _FLAGS) \ + static volatile HMODULE __fastcall _CRT_CONCATENATE(try_get_module_, _MODULE)() noexcept \ { \ __declspec(allocate(".YYThu$AAA")) static volatile HMODULE hModule; \ - return &hModule; \ + return try_get_module<_FLAGS>(&hModule, _CRT_CONCATENATE(module_name_, _MODULE)); \ } _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) #undef _APPLY +typedef volatile HMODULE (__fastcall* try_get_module_fun)(); static __forceinline void* __fastcall try_get_proc_address_from_first_available_module( - volatile HMODULE* pModule, - const wchar_t* module_name, + try_get_module_fun get_module, char const* const name ) noexcept { - HMODULE const module_handle = try_get_module(pModule, module_name); + HMODULE const module_handle = get_module(); if (!module_handle) { return nullptr; @@ -308,18 +334,13 @@ static __forceinline void* __cdecl invalid_function_sentinel() noexcept return reinterpret_cast(static_cast(-1)); } -static int __cdecl _YY_initialize_winapi_thunks(); static void* __fastcall try_get_function( void** ppFunAddress, char const* const name, - volatile HMODULE* pModule, - const wchar_t* module_name + try_get_module_fun get_module ) noexcept { - //尝试初始化YY-Thunks,避免还未初始化问题。 - _YY_initialize_winapi_thunks(); - // First check to see if we've cached the function pointer: { void* const cached_fp = __crt_fast_decode_pointer( @@ -339,7 +360,7 @@ static void* __fastcall try_get_function( // If we haven't yet cached the function pointer, try to import it from any // of the modules in which it might be defined. If this fails, cache the // sentinel pointer so that we don't attempt to load this function again: - void* const new_fp = try_get_proc_address_from_first_available_module(pModule, module_name, name); + void* const new_fp = try_get_proc_address_from_first_available_module(get_module, name); if (!new_fp) { void* const cached_fp = __crt_fast_decode_pointer( @@ -382,8 +403,7 @@ static void* __fastcall try_get_function( return reinterpret_cast<_CRT_CONCATENATE(_FUNCTION, _pft)>(try_get_function( \ &_CRT_CONCATENATE( pFun_ ,_FUNCTION), \ _CRT_STRINGIZE(_FUNCTION), \ - _CRT_CONCATENATE(try_get_module_, _MODULE)(), \ - _CRT_CONCATENATE(module_name_, _MODULE))); \ + &_CRT_CONCATENATE(try_get_module_, _MODULE))); \ } _YY_APPLY_TO_LATE_BOUND_FUNCTIONS(_APPLY) #undef _APPLY @@ -392,8 +412,20 @@ static void* __fastcall try_get_function( static void __cdecl __YY_uninitialize_winapi_thunks() { //当DLL被强行卸载时,我们什么都不做。 - if (pRtlDllShutdownInProgress && pRtlDllShutdownInProgress()) - return; + if (pRtlDllShutdownInProgress) + { + if(pRtlDllShutdownInProgress()) + return; + } + __if_exists(__YY_Thunks_Process_Terminating) + { + else + { + if (__YY_Thunks_Process_Terminating) + return; + } + } + auto pModule = (HMODULE*)__YY_THUNKS_MODULE_START; auto pModuleEnd = (HMODULE*)__YY_THUNKS_FUN_START; @@ -468,33 +500,27 @@ InitOnceExecuteOnceDownlevel( static int __cdecl _YY_initialize_winapi_thunks() { - //为了防止多线程同时初始化,我们还是加个锁 - static INIT_ONCE InitOnce; - - InitOnceExecuteOnceDownlevel(&InitOnce, [](PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) -> BOOL - { - if (auto hNtdll = GetModuleHandleW(L"ntdll")) - { + if (auto hNtdll = try_get_module_ntdll()) + { #if defined(_X86_) || defined(_M_IX86) - pRtlWow64EnableFsRedirectionEx = (decltype(RtlWow64EnableFsRedirectionEx)*)GetProcAddress(hNtdll, "RtlWow64EnableFsRedirectionEx"); + pRtlWow64EnableFsRedirectionEx = (decltype(RtlWow64EnableFsRedirectionEx)*)GetProcAddress(hNtdll, "RtlWow64EnableFsRedirectionEx"); #endif - pRtlDllShutdownInProgress = (decltype(RtlDllShutdownInProgress)*)GetProcAddress(hNtdll,"RtlDllShutdownInProgress"); - } + pRtlDllShutdownInProgress = (decltype(RtlDllShutdownInProgress)*)GetProcAddress(hNtdll, "RtlDllShutdownInProgress"); + } - if (auto hKernel32 = GetModuleHandleW(L"kernel32")) - { - bSupportSafe = GetProcAddress(hKernel32, "AddDllDirectory") != nullptr; - } + if (auto hKernel32 =try_get_module_kernel32()) + { + bSupportSafe = GetProcAddress(hKernel32, "AddDllDirectory") != nullptr; + } - void* const encoded_nullptr = __crt_fast_encode_pointer((void*)nullptr); + __security_cookie_yy_thunks = __security_cookie; - for (auto p = __YY_THUNKS_FUN_START; p != __YY_THUNKS_FUN_END; ++p) - { - *p = encoded_nullptr; - } + void* const encoded_nullptr = __crt_fast_encode_pointer((void*)nullptr); - return TRUE; - }, nullptr, nullptr); + for (auto p = __YY_THUNKS_FUN_START; p != __YY_THUNKS_FUN_END; ++p) + { + *p = encoded_nullptr; + } return 0; }