Skip to content

Commit

Permalink
Fea, 添加OpenProcess、OpenThread、GetTokenInformation不支持的参数模拟
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed Oct 19, 2024
1 parent 5ea65f0 commit 187a8fb
Show file tree
Hide file tree
Showing 3 changed files with 324 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
| EventWriteString | 不存在时,返回ERROR_NOT_SUPPORTED。
| GetDynamicTimeZoneInformationEffectiveYears| 不存在时,直接读取`Time Zones`注册表。
| AddMandatoryAce | 不存在时,调用RtlCopySid。
| GetTokenInformation | 返回假装的 TokenVirtualizationAllowed、TokenAppContainerSid等。

## bcrypt.dll
| 函数 | Fallback
Expand Down Expand Up @@ -543,6 +544,7 @@
| Wow64GetThreadContext | 不存在时,调用GetThreadContext或者返回ERROR_INVALID_PARAMETER。
| SetDefaultDllDirectories | 不存在时,手工控制LoadLibrary加载顺序。
| GetCurrentPackageFullName | 返回 APPMODEL_ERROR_NO_PACKAGE。
| OpenProcess | 额外处理 PROCESS_QUERY_LIMITED_INFORMATION、PROCESS_SET_LIMITED_INFORMATION。

## mfplat.dll
| 函数 | Fallback
Expand Down
90 changes: 90 additions & 0 deletions src/Thunks/api-ms-win-core-processthreads.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1210,4 +1210,94 @@ namespace YY ::Thunks
return CreateRemoteThread(_hProcess, _pThreadAttributes, _uStackSize, _pStartAddress, _pParameter, _fCreationFlags, _pThreadId);
}
#endif


#if (YY_Thunks_Target < __WindowsNT6)

// 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用]
// 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用]
// Windows XP无法支持 PROCESS_QUERY_LIMITED_INFORMATION等权限。
__DEFINE_THUNK(
kernel32,
12,
HANDLE,
WINAPI,
OpenProcess,
_In_ DWORD _fDesiredAccess,
_In_ BOOL _bInheritHandle,
_In_ DWORD _uProcessId
)
{
const auto _pfnOpenProcess = try_get_OpenProcess();
if (!_pfnOpenProcess)
{
SetLastError(ERROR_FUNCTION_FAILED);
return nullptr;
}

if (internal::GetSystemVersion() < internal::MakeVersion(6, 0))
{
if (PROCESS_QUERY_LIMITED_INFORMATION & _fDesiredAccess)
{
_fDesiredAccess |= PROCESS_QUERY_INFORMATION;
}

if (PROCESS_SET_LIMITED_INFORMATION & _fDesiredAccess)
{
_fDesiredAccess |= PROCESS_SET_INFORMATION;
}

// Vista以上最高为 0xFFFF
// Windows XP最高只有 0x0FFF
_fDesiredAccess &= ~(0xFFFFu ^ 0x0FFF);
}

return _pfnOpenProcess(_fDesiredAccess, _bInheritHandle, _uProcessId);
}
#endif


#if (YY_Thunks_Target < __WindowsNT6)

// 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用]
// 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用]
// Windows XP无法支持 PROCESS_QUERY_LIMITED_INFORMATION等权限。
__DEFINE_THUNK(
kernel32,
12,
HANDLE,
WINAPI,
OpenThread,
_In_ DWORD _fDesiredAccess,
_In_ BOOL _bInheritHandle,
_In_ DWORD _uThreadId
)
{
const auto _pfnOpenThread = try_get_OpenThread();
if (!_pfnOpenThread)
{
SetLastError(ERROR_FUNCTION_FAILED);
return nullptr;
}

if (internal::GetSystemVersion() < internal::MakeVersion(6, 0))
{
if (THREAD_QUERY_LIMITED_INFORMATION & _fDesiredAccess)
{
_fDesiredAccess |= THREAD_QUERY_INFORMATION;
}

if (THREAD_SET_LIMITED_INFORMATION & _fDesiredAccess)
{
_fDesiredAccess |= THREAD_SET_INFORMATION;
}

// Vista以上最高为 0xFFFF
// Windows XP最高只有 0x03FF
_fDesiredAccess &= ~(0xFFFFu ^ 0x03FFu);
}

return _pfnOpenThread(_fDesiredAccess, _bInheritHandle, _uThreadId);
}
#endif
} //namespace YY::Thunks
232 changes: 232 additions & 0 deletions src/Thunks/api-ms-win-security-base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,236 @@
return TRUE;
}
#endif


#if (YY_Thunks_Target < __WindowsNT6)

// 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用]
// 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用]
__DEFINE_THUNK(
advapi32,
20,
BOOL,
WINAPI,
GetTokenInformation,
_In_ HANDLE _hTokenHandle,
_In_ TOKEN_INFORMATION_CLASS _eTokenInformationClass,
_Out_writes_bytes_to_opt_(_cbTokenInformationLength,*_puReturnLength) LPVOID _pTokenInformation,
_In_ DWORD _cbTokenInformationLength,
_Out_ PDWORD _puReturnLength
)
{
const auto _pfnGetTokenInformation = try_get_GetTokenInformation();
if (!_pfnGetTokenInformation)
{
SetLastError(ERROR_FUNCTION_FAILED);
return FALSE;
}

if (internal::GetSystemVersion() < internal::MakeVersion(6, 0))
{
switch (_eTokenInformationClass)
{
case TokenVirtualizationAllowed:
{
// 如果令牌允许虚拟化,则缓冲区会收到一个非零的 DWORD 值。
// 假装不允许虚拟化。
using ValueType = DWORD;
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}

*_pValue = 0;
return TRUE;
}
case TokenVirtualizationEnabled:
{
// 如果为令牌启用了虚拟化,则缓冲区会收到一个非零的 DWORD 值。
// 假装没有启动虚拟化。
using ValueType = DWORD;
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}

*_pValue = 0;
return TRUE;
}
case TokenIntegrityLevel:
{
// 缓冲区接收指定令牌完整性级别的 TOKEN_MANDATORY_LABEL 结构。
// 我们假装当前进程是高完整性。
struct ValueType : public TOKEN_MANDATORY_LABEL
{
SID SidBuffer;
};
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}

static constexpr SID kHighLevel =
{
SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_HIGH_RID}
};

_pValue->SidBuffer = kHighLevel;
_pValue->Label.Sid == &_pValue->SidBuffer;
_pValue->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
return TRUE;
}
case TokenUIAccess:
{
// 如果令牌设置了 UIAccess 标志,缓冲区将收到非零的 DWORD 值。
// XP没有 TokenUIAccess的说法,假装自己没有这个权限。
using ValueType = DWORD;
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}
*_pValue = 0;
return TRUE;
}
case TokenAppContainerSid:
{
// 缓冲区接收包含与令牌关联的 AppContainerSid 的 TOKEN_APPCONTAINER_INFORMATION 结构。
// 如果令牌未与应用容器关联,则TOKEN_APPCONTAINER_INFORMATION结构的 TokenAppContainer 成员指向 NULL。
// 假装自己不是AppContainer

using ValueType = TOKEN_APPCONTAINER_INFORMATION;
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}

_pValue->TokenAppContainer = nullptr;
return TRUE;
}
case TokenIsAppContainer:
{
// 如果令牌是应用容器令牌,则缓冲区接收非零 的 DWORD 值。
// 检查 TokenIsAppContainer 并使其返回 0 的任何调用方还应验证调用方令牌是否不是标识级别模拟令牌。
// 如果当前令牌不是应用容器,而是标识级令牌,则应返回 AccessDenied。
// 假装自己不是 AppContainer
using ValueType = DWORD;
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}

*_pValue = 0;
return TRUE;
}
case TokenAppContainerNumber:
{
// 缓冲区接收包含令牌的应用容器号的 DWORD 值。 对于不是应用容器令牌的令牌,此值为零。
// 假装自己不是AppContainer
using ValueType = DWORD;
auto _pValue = (ValueType*)_pTokenInformation;
if (_puReturnLength)
{
*_puReturnLength = sizeof(ValueType);
}

if (_cbTokenInformationLength < sizeof(ValueType))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}

if (!_pValue)
{
SetLastError(ERROR_NOACCESS);
return FALSE;
}

*_pValue = 0;
return TRUE;
}
}
}

return _pfnGetTokenInformation(_hTokenHandle, _eTokenInformationClass, _pTokenInformation, _cbTokenInformationLength, _puReturnLength);
}
#endif

} // namespace YY::Thunks

0 comments on commit 187a8fb

Please sign in to comment.