#include "../main.h" #include "ModuleBase.hpp" #include #include #include "../wine_winternl.h" #include #include class AdminImpersonate : public ModuleBase { inline static decltype(&IsUserAnAdmin) TrueIsUserAnAdmin; inline static decltype(&CheckTokenMembership) TrueCheckTokenMembership; inline static decltype(&NtOpenFile) TrueNtOpenFile; inline static decltype(&NtCreateFile) TrueNtCreateFile; inline static decltype(&NtAccessCheck) TrueNtAccessCheck; inline static decltype(&NtAccessCheckAndAuditAlarm) TrueNtAccessCheckAndAuditAlarm; inline static decltype(&NtPrivilegeCheck) TrueNtPrivilegeCheck; static BOOL __stdcall DetourIsUserAnAdmin() { return TRUE; } static BOOL APIENTRY DetourCheckTokenMembership(_In_opt_ HANDLE TokenHandle, _In_ PSID SidToCheck, _Out_ PBOOL IsMember) { // fetch and allocate the local admin structure static SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; static PSID LocalAdministratorsGroup = NULL; AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &LocalAdministratorsGroup); // get the real value of the function - return if failure BOOL bRealResult = TrueCheckTokenMembership(TokenHandle, SidToCheck, IsMember); if (bRealResult == 0) return bRealResult; // check if the local admin group is being requested if (EqualSid(SidToCheck, LocalAdministratorsGroup)) { // unconditionally say this user is running as an admin *IsMember = TRUE; } return bRealResult; } static NTSTATUS NTAPI DetourNtOpenFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions) { DWORD iStatus = TrueNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, ShareAccess, OpenOptions); if (iStatus == STATUS_SHARING_VIOLATION || iStatus == STATUS_ACCESS_DENIED) { return STATUS_NO_SUCH_FILE; } return iStatus; } static NTSTATUS NTAPI DetourNtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength) { NTSTATUS iStatus = TrueNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength); if (iStatus == STATUS_SHARING_VIOLATION || iStatus == STATUS_ACCESS_DENIED) { return STATUS_DISK_FULL; } return iStatus; } static NTSTATUS NTAPI DetourNtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN HANDLE Handle, IN ACCESS_MASK AccessMask, IN PGENERIC_MAPPING pGenericMapping, IN PPRIVILEGE_SET PrivilegeSet, PULONG Unk1, PULONG Unk2, OUT NTSTATUS* Result) { TrueNtAccessCheck(SecurityDescriptor, Handle, AccessMask, pGenericMapping, PrivilegeSet, Unk1, Unk2, Result); *Result = STATUS_SUCCESS; return STATUS_SUCCESS; } static NTSTATUS NTAPI DetourNtAccessCheckAndAuditAlarm(PUNICODE_STRING A, HANDLE B, PUNICODE_STRING C, PUNICODE_STRING D, PSECURITY_DESCRIPTOR E, ACCESS_MASK F, PGENERIC_MAPPING G, BOOLEAN H, PACCESS_MASK I , PBOOLEAN J, PBOOLEAN K) { auto res = MessageBoxA(nullptr, "Unsupported NT function called: NtAccessCheckAndAuditAlarm" , "Policy Tool Warning", MB_CANCELTRYCONTINUE); switch (res) { case IDCANCEL: return STATUS_NOT_IMPLEMENTED; case IDTRYAGAIN: return STATUS_SUCCESS; case IDCONTINUE: return TrueNtAccessCheckAndAuditAlarm(A, B, C, D, E, F, G, H, I, J, K); default: abort(); } } static NTSTATUS NTAPI DetourNtPrivilegeCheck(IN HANDLE, PRIVILEGE_SET, OUT PBOOLEAN Result) { *Result = TRUE; return STATUS_SUCCESS; } public: AdminImpersonate() { TrueIsUserAnAdmin = IsUserAnAdmin; TrueCheckTokenMembership = CheckTokenMembership; TrueNtOpenFile = reinterpret_cast(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtOpenFile")); TrueNtCreateFile = reinterpret_cast(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtCreateFile")); TrueNtAccessCheck = reinterpret_cast(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtAccessCheck")); TrueNtAccessCheckAndAuditAlarm = reinterpret_cast(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtAccessCheckAndAuditAlarm")); TrueNtPrivilegeCheck = reinterpret_cast(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtPrivilegeCheck")); DetourAttach(&reinterpret_cast(TrueNtOpenFile), reinterpret_cast(DetourNtOpenFile)); DetourAttach(&reinterpret_cast(TrueNtCreateFile), reinterpret_cast(DetourNtCreateFile)); DetourAttach(&reinterpret_cast(TrueIsUserAnAdmin), reinterpret_cast(DetourIsUserAnAdmin)); DetourAttach(&reinterpret_cast(TrueCheckTokenMembership), reinterpret_cast(DetourCheckTokenMembership)); DetourAttach(&reinterpret_cast(TrueNtAccessCheck), reinterpret_cast(DetourNtAccessCheck)); DetourAttach(&reinterpret_cast(TrueNtAccessCheckAndAuditAlarm), reinterpret_cast(DetourNtAccessCheckAndAuditAlarm)); DetourAttach(&reinterpret_cast(TrueNtPrivilegeCheck), reinterpret_cast(DetourNtPrivilegeCheck)); } ~AdminImpersonate() { DetourDetach(&reinterpret_cast(TrueNtOpenFile), reinterpret_cast(DetourNtOpenFile)); DetourDetach(&reinterpret_cast(TrueNtCreateFile), reinterpret_cast(DetourNtCreateFile)); DetourDetach(&reinterpret_cast(TrueIsUserAnAdmin), reinterpret_cast(DetourIsUserAnAdmin)); DetourDetach(&reinterpret_cast(TrueCheckTokenMembership), reinterpret_cast(DetourCheckTokenMembership)); DetourDetach(&reinterpret_cast(TrueNtAccessCheck), reinterpret_cast(DetourNtAccessCheck)); DetourDetach(&reinterpret_cast(TrueNtAccessCheckAndAuditAlarm), reinterpret_cast(DetourNtAccessCheckAndAuditAlarm)); DetourDetach(&reinterpret_cast(TrueNtPrivilegeCheck), reinterpret_cast(DetourNtPrivilegeCheck)); } };