/YY-Thunks

Fix DecodePointer, EncodePointer,RegDeleteKeyEx etc. APIs not found in Windows XP RTM.

Primary LanguageC++MIT LicenseMIT

YY-Thunks——让兼容Windows更轻松

1. 关于YY-Thunks

总众所周知Windows XP每个SP都会新增大量API,而Windows 10每次更新又会新增大量API,这使得兼容不同版本的Windows需要大量的判断。

甚至大量开源代码已经不再兼容一些早期的Windows XP版本,比如 Windows XP RTM。难道就没有一种快速高效的方案解决无法定位程序输入点的问题吗?

YY-Thunks(鸭船),存在的目的就是抹平不同系统的差异,编译时单纯添加一个obj即可自动解决这些兼容性问题。让你兼容Windows更轻松!

[ 鸭船交流群 633710173 ]

1.1. 原理

使用LoadLibrary以及GetProcAddress动态加载API,不存在时做出补偿措施,最大限度模拟原始API行为,让你的程序正常运行。

1.2. 亮点

  • 更快!更安全!鸭船内建2级缓存以及按需加载机制,同时自动加密所有函数指针,防止内存爆破攻击。最大程度减少不需要的、不必要的LoadLibrary以及GetProcAddress调用以及潜在安全风险。
  • 轻松兼容Windows XP,让你安心专注于业务逻辑。
  • 完全的开放代码,广泛的接受用户意见,希望大家能踊跃的 pull requests,为鸭船添砖加瓦。

2. 使用YY-Thunks

  1. 下载YY-Thunks-Binary,然后解压到你的工程目录。
  2. 【链接器】-【输入】-【附加依赖项】,添加objs\$(PlatformShortName)\YY_Thunks_for_WinXP.obj
  3. 重新编译代码。

3. YY-Thunks兼容性

3.1. 支持的编译器

全平台ABI兼容。

  • 所有Visual Studio版本均支持(比如:VC6.0、VS2008、VS2010、VS2015、VS2017、VS2019等等)。
  • 所有运行库模式均支持(比如:/MD/MT/MDd/MTd)。

3.2. Thunks清单

此表展示了YY-Thunks(鸭船)可以解决的函数不存在问题,欢迎大家扩充!

开头带*的函数并不建议使用,仅用于编译通过处理,如果使用可能导致老版本系统无法充分发挥性能。

函数 Fallback
DecodePointer 不存在时,返回指针本身。
EncodePointer 不存在时,返回指针本身。
RegDeleteKeyExW(A) 不存在时,调用RegDeleteKeyW(A)。
Wow64DisableWow64FsRedirection 不存在时,返回FALSE,并设置 LastError = ERROR_INVALID_FUNCTION。
Wow64RevertWow64FsRedirection 不存在时,返回FALSE,并设置 LastError = ERROR_INVALID_FUNCTION。
Wow64EnableWow64FsRedirection 不存在时,返回FALSE,并设置 LastError = ERROR_INVALID_FUNCTION。
IsWow64Process 不存在时,返回TRUE,并设置 *Wow64Process = FALSE
IsWow64Message 不存在时,返回FALSE。
RegSetKeyValueW(A) 调用RegCreateKeyExW(A)以及RegSetValueExW(A)。
RegDeleteKeyValueW(A) 调用RegOpenKeyExW(A)以及RegDeleteValueW(A)。
RegDeleteTreeW(A) 调用SHDeleteKeyW(A)。
RegGetValueW(A) 不存在时,调用RegQueryValueExW(A)。
IsWow64Process2 不存在时,调用IsWow64Process。
IsWow64GuestMachineSupported 不存在时,调用GetNativeSystemInfo。
GetTickCount64 不存在时,调用GetTickCount。
GetSystemTimePreciseAsFileTime 不存在时,调用GetSystemTimeAsFileTime。
InitializeCriticalSectionEx 不存在时,调用InitializeCriticalSectionAndSpinCount。
InitOnceExecuteOnce 不存在时,调用InterlockedCompareExchange。
LocaleNameToLCID 不存在时,查LocaleNameToLcidTable。
LCIDToLocaleName 不存在时,查LcidToLocaleNameTable。
GetLocaleInfoEx 不存在时,调用GetLocaleInfoW。
GetDateFormatEx 不存在时,调用GetDateFormatW。
GetTimeFormatEx 不存在时,调用GetTimeFormatW。
GetNumberFormatEx 不存在时,调用GetNumberFormatW。
GetCurrencyFormatEx 不存在时,调用GetCurrencyFormatW。
GetUserDefaultLocaleName 不存在时,调用LCIDToLocaleName。
GetSystemDefaultLocaleName 不存在时,调用LCIDToLocaleName。
EnumCalendarInfoExEx 不存在时,调用EnumCalendarInfoExW。
EnumDateFormatsExEx 不存在时,调用EnumDateFormatsExW。
GetFileInformationByHandleEx 不存在时,调用NtQueryInformationFile 或者 NtQueryDirectoryFile。
SetFileInformationByHandle 不存在时,调用NtSetInformationFile。
GetFinalPathNameByHandleW(A) 不存在时,调用NtQueryObject以及NtQueryInformationFile。
GetLogicalProcessorInformation 不存在时,返回FALSE,并设置 LastError = ERROR_INVALID_FUNCTION。
GetLogicalProcessorInformationEx 不存在时,调用GetLogicalProcessorInformation。
InetPtonW(inet_pton) 不存在时,类似于sscanf手工分析字符串。
InetNtopW(inet_ntop) 不存在时,类似于sprintf手工生成字符串。
GetNumaHighestNodeNumber 不存在时,返回0。
RaiseFailFastException 不存在时,调用TerminateProcess。
GetThreadId 不存在时,调用NtQueryInformationThread。
GetProcessIdOfThread 不存在时,调用NtQueryInformationThread。
GetProcessId 不存在时,调用NtQueryInformationProcess。
QueryThreadCycleTime 不存在时,调用GetThreadTimes。
QueryProcessCycleTime 不存在时,调用GetProcessTimes。
K32EnumProcessModules 调用EnumProcessModules。
K32EnumProcessModulesEx 调用EnumProcessModulesEx。
K32GetModuleBaseNameW(A) 调用GetModuleBaseNameW(A)。
K32GetModuleFileNameExW(A) 调用K32GetModuleFileNameExW(A)。
K32EmptyWorkingSet 调用EmptyWorkingSet。
K32QueryWorkingSet 调用QueryWorkingSet。
K32QueryWorkingSetEx 调用QueryWorkingSetEx。
K32InitializeProcessForWsWatch 调用InitializeProcessForWsWatch。
K32GetWsChanges 调用GetWsChanges。
K32GetWsChangesEx 调用GetWsChangesEx。
K32GetMappedFileNameW(A) 调用GetMappedFileNameW(A)。
K32EnumDeviceDrivers 调用EnumDeviceDrivers。
K32GetDeviceDriverBaseNameW(A) 调用GetDeviceDriverBaseNameW(A)。
K32GetDeviceDriverFileNameW(A) 调用GetDeviceDriverFileNameW(A)。
K32GetPerformanceInfo 调用GetPerformanceInfo。
K32EnumPageFilesW(A) 调用EnumPageFilesW(A)。
K32GetProcessImageFileNameW(A) 调用GetProcessImageFileNameW(A)。
EnumProcessModulesEx 不存在时,调用EnumProcessModules。
GetWsChangesEx 不存在时,调用GetWsChanges。
QueryFullProcessImageNameW(A) 不存在时,调用GetProcessImageFileNameW(A) 或者 GetModuleFileNameExW(A)。
CreateFile2 不存在时,调用CreateFileW。
CreateEventExW(A) 不存在时,调用CreateEventW(A)。
CreateMutexExW(A) 不存在时,调用CreateMutexW(A)。
CreateSemaphoreExW 不存在时,调用CreateSemaphoreW。
CreateWaitableTimerExW 不存在时,调用CreateWaitableTimerW。
GetFileVersionInfoExW(A) 不存在时,调用GetFileVersionInfoW(A)。
GetFileVersionInfoSizeExW(A) 不存在时,调用GetFileVersionInfoSizeW(A)。
InterlockedCompareExchange64 调用内部函数_InterlockedCompareExchange64。
SetThreadErrorMode 不存在时,调用SetErrorMode。
GetThreadErrorMode 不存在时,调用GetErrorMode。
GetErrorMode 不存在时,调用NtQueryInformationProcess。
InitializeSRWLock 初始化为 RTL_SRWLOCK_INIT。
AcquireSRWLockExclusive 不存在时,调用InterlockedBitTestAndSet(64)。
TryAcquireSRWLockExclusive 不存在时,调用InterlockedBitTestAndSet(64)。
ReleaseSRWLockExclusive 不存在时,调用InterlockedCompareExchange。
AcquireSRWLockShared 不存在时,调用InterlockedCompareExchange。
TryAcquireSRWLockShared 不存在时,调用InterlockedCompareExchange。
ReleaseSRWLockShared 不存在时,调用InterlockedCompareExchange。
*GetCurrentProcessorNumber 不存在时,返回0。
*GetCurrentProcessorNumberEx 不存在时,调用GetCurrentProcessorNumber。
*GetNumaNodeProcessorMask 不存在时,返回FALSE,并设置 LastError = ERROR_INVALID_PARAMETER。
*GetNumaNodeProcessorMaskEx 不存在时,调用GetNumaNodeProcessorMask。
*SetThreadGroupAffinity 不存在时,调用SetThreadAffinityMask。
*CancelIoEx 不存在时,调用CancelIo(会把此句柄的所有IO操作取消掉!)。

Changes

1.0.0.1 - 第一版(2018-05-17 19:00)

  • YY-Thunks第一版

1.0.0.2 - 补充API支持(2018-06-01 18:30)

  • 添加RegSetKeyValueW(A)
  • 添加RegDeleteKeyValueW(A)
  • 添加RegDeleteTreeW(A)

1.0.0.3 - 让兼容Windows ARM64更轻松(2018-06-18 11:30)

  • 添加IsWow64Process2
  • 添加IsWow64GuestMachineSupported
  • 添加GetTickCount64
  • 添加GetSystemTimePreciseAsFileTime
  • 添加InitializeCriticalSectionEx
  • 添加InitOnceExecuteOnce
  • 添加GetCurrentProcessorNumber
  • 添加GetCurrentProcessorNumberEx
  • 添加GetNumaNodeProcessorMask
  • 添加GetNumaNodeProcessorMaskEx
  • 添加SetThreadGroupAffinity

1.0.0.4 - 兼容性更新(2018-09-08 18:00)

  • 解决Bug,将初始化时机推迟到.CRT$XID,避免VC2008下过早初始化导致atexit崩溃(感谢 死田鸡)。

1.0.0.7 - 功能更新(2019-01-02 15:10)

  • 添加RegGetValueW(A)
  • 添加LocaleNameToLCID
  • 添加LCIDToLocaleName
  • 添加GetLocaleInfoEx
  • 添加GetDateFormatEx
  • 添加GetTimeFormatEx
  • 添加GetNumberFormatEx
  • 添加GetCurrencyFormatEx
  • 添加GetUserDefaultLocaleName
  • 添加GetSystemDefaultLocaleName
  • 重新编译,解决潜在符号修饰问题。

1.0.1.1 - 功能更新(2019-04-01 17:00)

  • 添加EnumCalendarInfoExEx
  • 添加EnumDateFormatsExEx
  • 添加GetFileInformationByHandleEx
  • 添加SetFileInformationByHandle
  • 添加GetFinalPathNameByHandleW(A)
  • 解决Bug,1.0.0.10版意外引入ntdll.lib问题(感谢 小古)。
  • 添加GetLogicalProcessorInformation
  • 添加GetLogicalProcessorInformationEx
  • 添加InetPtonW(inet_pton)
  • 添加InetNtopW(inet_ntop)
  • 添加GetNumaHighestNodeNumber

1.0.1.5 - 功能更新(2019-05-26 19:00)

  • 添加RaiseFailFastException(感谢 过客)
  • 添加GetThreadId(感谢 过客)
  • 添加GetProcessIdOfThread
  • 添加QueryThreadCycleTime(感谢 过客)
  • 添加QueryProcessCycleTime
  • 添加K32EnumProcessModules
  • 添加K32EnumProcessModulesEx
  • 添加K32GetModuleBaseNameW(A)
  • 添加K32GetModuleFileNameExW(A)
  • 添加K32EmptyWorkingSet
  • 添加K32QueryWorkingSet
  • 添加K32QueryWorkingSetEx
  • 添加K32InitializeProcessForWsWatch
  • 添加K32GetWsChanges
  • 添加K32GetWsChangesEx
  • 添加K32GetMappedFileNameW(A)
  • 添加K32EnumDeviceDrivers
  • 添加K32GetDeviceDriverBaseNameW(A)
  • 添加K32GetDeviceDriverFileNameW(A)
  • 添加K32GetPerformanceInfo
  • 添加K32EnumPageFilesW(A)
  • 添加K32GetProcessImageFileNameW(A)
  • 添加EnumProcessModulesEx
  • 添加GetWsChangesEx
  • 添加QueryFullProcessImageNameW(A)
  • 添加CreateFile2
  • 添加CreateEventExW(A)
  • 添加CreateMutexExW(A)
  • 添加CreateSemaphoreExW
  • 添加CreateWaitableTimerExW
  • 添加GetFileVersionInfoExW(A)
  • 添加GetFileVersionInfoSizeExW(A)
  • 添加QueryFullProcessImageNameW(A)
  • 添加InterlockedCompareExchange64
  • 添加GetProcessId
  • 添加SetThreadErrorMode
  • 添加GetThreadErrorMode
  • 添加GetErrorMode
  • 添加CancelIoEx

1.0.1.7 - 功能更新(2019-06-04 13:00)

  • 添加InitializeSRWLock
  • 添加AcquireSRWLockExclusive
  • 添加ReleaseSRWLockExclusive
  • 添加AcquireSRWLockShared
  • 添加ReleaseSRWLockShared
  • 添加TryAcquireSRWLockExclusive
  • 添加TryAcquireSRWLockShared

1.0.1.8 - 优化实现(2019-06-18 16:00)

  • 优化代码结构,减少不必要的全局对象引入。
  • 内部函数采用__fastcall约定,减少栈操作。
  • 增加YY-Thunks版本互斥。
  • 改进与联想一键影音的兼容性,由于联想一键影音错会乱Hook,导致LoadLibraryExW行为异常。这样将导致YY-Thunks等在没有安装KB2533623的系统上无法正常使用问题。
  • 改进Windows 7 RTM以及以下系统的兼容性,由于这些老版本系统由于在LoadLibraryExW期间不会恢复重定向,因此当目标线程关闭重定向时可能导致YY-Thunks无法正常工作。