From 42f1ad36ef93c98542f9899ada57bd55396a99f5 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Fri, 16 Sep 2016 01:08:49 +0300 Subject: .hpp instead of .h for C++ headers --- CMakeLists.txt | 2 +- error.h | 26 --------- error.hpp | 26 +++++++++ handle.h | 64 --------------------- handle.hpp | 64 +++++++++++++++++++++ main.cpp | 10 ++-- os.h | 30 ---------- os.hpp | 30 ++++++++++ process.h | 40 ------------- process.hpp | 40 +++++++++++++ sid.h | 68 ---------------------- sid.hpp | 68 ++++++++++++++++++++++ token.h | 175 --------------------------------------------------------- token.hpp | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 409 insertions(+), 409 deletions(-) delete mode 100644 error.h create mode 100644 error.hpp delete mode 100644 handle.h create mode 100644 handle.hpp delete mode 100644 os.h create mode 100644 os.hpp delete mode 100644 process.h create mode 100644 process.hpp delete mode 100644 sid.h create mode 100644 sid.hpp delete mode 100644 token.h create mode 100644 token.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1da2b43..d01997b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(privilege_test) file(GLOB ${PROJECT_NAME}_source_files "*.cpp") -file(GLOB ${PROJECT_NAME}_header_files "*.h") +file(GLOB ${PROJECT_NAME}_header_files "*.h" "*.hpp") file(GLOB ${PROJECT_NAME}_resource_files "*.rc") add_executable(${PROJECT_NAME} WIN32 ${${PROJECT_NAME}_source_files} diff --git a/error.h b/error.h deleted file mode 100644 index 2ea7f85..0000000 --- a/error.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include - -typedef std::system_error Error; - -namespace error -{ - inline void raise(const char* function_name) - { - const auto ec = GetLastError(); - throw std::system_error(ec, std::system_category(), function_name); - } - - void report(const Error& e) - { - MessageBoxA(NULL, e.what(), NULL, MB_OK); - } - - int get_code(const Error& e) - { - return e.code().value(); - } -} diff --git a/error.hpp b/error.hpp new file mode 100644 index 0000000..2ea7f85 --- /dev/null +++ b/error.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +typedef std::system_error Error; + +namespace error +{ + inline void raise(const char* function_name) + { + const auto ec = GetLastError(); + throw std::system_error(ec, std::system_category(), function_name); + } + + void report(const Error& e) + { + MessageBoxA(NULL, e.what(), NULL, MB_OK); + } + + int get_code(const Error& e) + { + return e.code().value(); + } +} diff --git a/handle.h b/handle.h deleted file mode 100644 index 5f83f24..0000000 --- a/handle.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include - -class Handle -{ -public: - Handle() = default; - - explicit Handle(HANDLE raw) - : impl{raw} - { } - - Handle(Handle&& other) noexcept - { - swap(other); - } - - Handle& operator=(Handle other) noexcept - { - swap(other); - return *this; - } - - void swap(Handle& other) noexcept - { - using std::swap; - swap(impl, other.impl); - } - - operator HANDLE() const - { - return impl.get(); - } - -private: - struct Close - { - void operator()(HANDLE raw) const - { - if (raw == NULL || raw == INVALID_HANDLE_VALUE) - return; - const auto ret = CloseHandle(raw); - assert(ret); - } - }; - - std::unique_ptr impl; - - Handle(const Handle&) = delete; -}; - -namespace std -{ - void swap(Handle& a, Handle& b) noexcept - { - a.swap(b); - } -} diff --git a/handle.hpp b/handle.hpp new file mode 100644 index 0000000..5f83f24 --- /dev/null +++ b/handle.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include + +#include + +#include +#include + +class Handle +{ +public: + Handle() = default; + + explicit Handle(HANDLE raw) + : impl{raw} + { } + + Handle(Handle&& other) noexcept + { + swap(other); + } + + Handle& operator=(Handle other) noexcept + { + swap(other); + return *this; + } + + void swap(Handle& other) noexcept + { + using std::swap; + swap(impl, other.impl); + } + + operator HANDLE() const + { + return impl.get(); + } + +private: + struct Close + { + void operator()(HANDLE raw) const + { + if (raw == NULL || raw == INVALID_HANDLE_VALUE) + return; + const auto ret = CloseHandle(raw); + assert(ret); + } + }; + + std::unique_ptr impl; + + Handle(const Handle&) = delete; +}; + +namespace std +{ + void swap(Handle& a, Handle& b) noexcept + { + a.swap(b); + } +} diff --git a/main.cpp b/main.cpp index cbb77cf..1777d79 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,9 @@ -#include "error.h" -#include "os.h" -#include "process.h" +#include "error.hpp" +#include "os.hpp" +#include "process.hpp" #include "resource_ids.h" -#include "sid.h" -#include "token.h" +#include "sid.hpp" +#include "token.hpp" #include #include diff --git a/os.h b/os.h deleted file mode 100644 index e4ba71c..0000000 --- a/os.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "error.h" - -#include - -namespace os -{ - OSVERSIONINFOW get_version_info() - { - OSVERSIONINFOW info; - ZeroMemory(&info, sizeof(info)); - info.dwOSVersionInfoSize = sizeof(info); - - if (!GetVersionExW(&info)) - error::raise("GetVersionExW"); - - return info; - } - - bool is_vista_or_later(const OSVERSIONINFOW& info) - { - return info.dwMajorVersion >= 6; - } - - bool is_vista_or_later() - { - return is_vista_or_later(get_version_info()); - } -} diff --git a/os.hpp b/os.hpp new file mode 100644 index 0000000..1a3c52d --- /dev/null +++ b/os.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "error.hpp" + +#include + +namespace os +{ + OSVERSIONINFOW get_version_info() + { + OSVERSIONINFOW info; + ZeroMemory(&info, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + + if (!GetVersionExW(&info)) + error::raise("GetVersionExW"); + + return info; + } + + bool is_vista_or_later(const OSVERSIONINFOW& info) + { + return info.dwMajorVersion >= 6; + } + + bool is_vista_or_later() + { + return is_vista_or_later(get_version_info()); + } +} diff --git a/process.h b/process.h deleted file mode 100644 index 9aaf319..0000000 --- a/process.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "error.h" - -#include -#include - -#include -#include - -namespace process -{ - std::wstring get_executable_path() - { - static constexpr DWORD max_path = MAX_PATH; - - std::array buf; - - const auto ret = GetModuleFileNameW(NULL, buf.data(), max_path); - - if (GetLastError() != ERROR_SUCCESS) - error::raise("GetModuleFileNameW"); - - return buf.data(); - } - - void runas(const std::wstring& exe_path, HWND hwnd = NULL, int nShow = SW_NORMAL) - { - SHELLEXECUTEINFOW info; - ZeroMemory(&info, sizeof(info)); - info.cbSize = sizeof(info); - info.lpVerb = L"runas"; - info.lpFile = exe_path.c_str(); - info.hwnd = hwnd; - info.nShow = nShow; - - if (!ShellExecuteExW(&info)) - error::raise("ShellExecuteExW"); - } -} diff --git a/process.hpp b/process.hpp new file mode 100644 index 0000000..864d452 --- /dev/null +++ b/process.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "error.hpp" + +#include +#include + +#include +#include + +namespace process +{ + std::wstring get_executable_path() + { + static constexpr DWORD max_path = MAX_PATH; + + std::array buf; + + const auto ret = GetModuleFileNameW(NULL, buf.data(), max_path); + + if (GetLastError() != ERROR_SUCCESS) + error::raise("GetModuleFileNameW"); + + return buf.data(); + } + + void runas(const std::wstring& exe_path, HWND hwnd = NULL, int nShow = SW_NORMAL) + { + SHELLEXECUTEINFOW info; + ZeroMemory(&info, sizeof(info)); + info.cbSize = sizeof(info); + info.lpVerb = L"runas"; + info.lpFile = exe_path.c_str(); + info.hwnd = hwnd; + info.nShow = nShow; + + if (!ShellExecuteExW(&info)) + error::raise("ShellExecuteExW"); + } +} diff --git a/sid.h b/sid.h deleted file mode 100644 index 5da8da7..0000000 --- a/sid.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include "error.h" - -#include -#include - -#include -#include -#include - -constexpr DWORD max_sid_size = SECURITY_MAX_SID_SIZE; -typedef std::array SidBuffer; - -namespace sid -{ - SidBuffer well_known(WELL_KNOWN_SID_TYPE type) - { - SidBuffer buffer; - DWORD cb = static_cast(buffer.size()); - - if (!CreateWellKnownSid(type, NULL, buffer.data(), &cb)) - error::raise("CreateWellKnownSid"); - - return buffer; - } - - SidBuffer builtin_administrators() - { - /* - void* sid = nullptr; - SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY; - - if (!AllocateAndInitializeSid( - &authority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &sid)) - { - error::raise("AllocateAndInitializeSid"); - } - - return std::unique_ptr{sid}; - */ - - return well_known(WinBuiltinAdministratorsSid); - } - - struct DeleteSidString - { - void operator()(wchar_t* s) const - { - LocalFree(s); - } - }; - - std::wstring to_string(const SidBuffer& sid) - { - wchar_t* s = nullptr; - - if (!ConvertSidToStringSidW(const_cast(sid.data()), &s)) - error::raise("ConvertSidToStringSidW"); - - return std::unique_ptr{s}.get(); - } -} diff --git a/sid.hpp b/sid.hpp new file mode 100644 index 0000000..15ce73b --- /dev/null +++ b/sid.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "error.hpp" + +#include +#include + +#include +#include +#include + +constexpr DWORD max_sid_size = SECURITY_MAX_SID_SIZE; +typedef std::array SidBuffer; + +namespace sid +{ + SidBuffer well_known(WELL_KNOWN_SID_TYPE type) + { + SidBuffer buffer; + DWORD cb = static_cast(buffer.size()); + + if (!CreateWellKnownSid(type, NULL, buffer.data(), &cb)) + error::raise("CreateWellKnownSid"); + + return buffer; + } + + SidBuffer builtin_administrators() + { + /* + void* sid = nullptr; + SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY; + + if (!AllocateAndInitializeSid( + &authority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &sid)) + { + error::raise("AllocateAndInitializeSid"); + } + + return std::unique_ptr{sid}; + */ + + return well_known(WinBuiltinAdministratorsSid); + } + + struct DeleteSidString + { + void operator()(wchar_t* s) const + { + LocalFree(s); + } + }; + + std::wstring to_string(const SidBuffer& sid) + { + wchar_t* s = nullptr; + + if (!ConvertSidToStringSidW(const_cast(sid.data()), &s)) + error::raise("ConvertSidToStringSidW"); + + return std::unique_ptr{s}.get(); + } +} diff --git a/token.h b/token.h deleted file mode 100644 index 66dac28..0000000 --- a/token.h +++ /dev/null @@ -1,175 +0,0 @@ -#pragma once - -#include "error.h" -#include "handle.h" -#include "os.h" -#include "sid.h" - -#include - -#include -#include -#include -#include - -namespace token -{ - namespace permissions - { - constexpr DWORD query() { return TOKEN_QUERY; } - - constexpr DWORD duplicate() { return TOKEN_DUPLICATE; } - } - - constexpr DWORD default_permissions = permissions::query(); - - // Current thread's primary impersonation token. - Handle dumb() { return Handle{NULL}; } - - Handle open_for_process( - const Handle& process, - DWORD permissions = default_permissions) - { - HANDLE raw; - - if (!OpenProcessToken(process, permissions, &raw)) - error::raise("OpenProcessToken"); - - return Handle{raw}; - } - - Handle open_for_current_process( - DWORD permissions = default_permissions) - { - return open_for_process(Handle{GetCurrentProcess()}, permissions); - } - - Handle get_linked(Handle&& token) - { - if (!os::is_vista_or_later()) - return std::move(token); - - auto type = TokenElevationTypeDefault; - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &cb)) - error::raise("GetTokenInformation"); - - if (type != TokenElevationTypeLimited) - return std::move(token); - - HANDLE raw; - - if (!GetTokenInformation(token, TokenLinkedToken, &raw, sizeof(raw), &cb)) - error::raise("GetTokenInformation"); - - return Handle{raw}; - } - - Handle impersonate(const Handle& token) - { - HANDLE raw; - - if (!DuplicateToken(token, SecurityIdentification, &raw)) - error::raise("DuplicateToken"); - - return Handle{raw}; - } - - // - // FUNCTION: query_integrity_level() - // - // RETURN VALUE: Returns the integrity level of the current process. It is - // usually one of these values: - // - // SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) - // Means untrusted level. It is used by processes started by the - // Anonymous group. Blocks most write access. - // - // SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) - // Means low integrity level. It is used by Protected Mode Internet - // Explorer. Blocks write acess to most objects (such as files and - // registry keys) on the system. - // - // SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) - // Means medium integrity level. It is used by normal applications - // being launched while UAC is enabled. - // - // SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) - // Means high integrity level. It is used by administrative applications - // launched through elevation when UAC is enabled, or normal - // applications if UAC is disabled and the user is an administrator. - // - // SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) - // Means system integrity level. It is used by services and other - // system-level applications (such as Wininit, Winlogon, Smss, etc.) - // - DWORD query_integrity_level(const Handle& token) - { - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &cb)) - { - switch (GetLastError()) - { - case ERROR_INSUFFICIENT_BUFFER: - break; - default: - error::raise("GetTokenInformation"); - } - } - - std::vector buf(cb); - const auto token_level = reinterpret_cast(buf.data()); - - if (!GetTokenInformation(token, TokenIntegrityLevel, token_level, cb, &cb)) - error::raise("GetTokenInformation"); - - // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. - // S-1-16-0x1000 stands for low integrity level SID). There is one and - // only one subauthority. - return *GetSidSubAuthority(token_level->Label.Sid, 0); - } - - std::wstring integrity_level_to_string(DWORD level) - { - static const std::unordered_map names = - { - {SECURITY_MANDATORY_UNTRUSTED_RID, L"Untrusted"}, - {SECURITY_MANDATORY_LOW_RID, L"Low"}, - {SECURITY_MANDATORY_MEDIUM_RID, L"Medium"}, - {SECURITY_MANDATORY_HIGH_RID, L"High"}, - {SECURITY_MANDATORY_SYSTEM_RID, L"System"}, - }; - - static constexpr auto unknown_name = L"Unknown"; - - const auto it = names.find(level); - - if (it == names.cend()) - return unknown_name; - - return it->second; - } - - bool belongs(const Handle& token, const SidBuffer& sid) - { - BOOL b = FALSE; - - if (!CheckTokenMembership(token, const_cast(sid.data()), &b)) - error::raise("CheckTokenMembership"); - - return b != FALSE; - } - - bool is_elevated(const Handle& token) - { - TOKEN_ELEVATION elevation; - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &cb)) - error::raise("GetTokenInformation"); - - return elevation.TokenIsElevated != 0; - } -} diff --git a/token.hpp b/token.hpp new file mode 100644 index 0000000..5669970 --- /dev/null +++ b/token.hpp @@ -0,0 +1,175 @@ +#pragma once + +#include "error.hpp" +#include "handle.hpp" +#include "os.hpp" +#include "sid.hpp" + +#include + +#include +#include +#include +#include + +namespace token +{ + namespace permissions + { + constexpr DWORD query() { return TOKEN_QUERY; } + + constexpr DWORD duplicate() { return TOKEN_DUPLICATE; } + } + + constexpr DWORD default_permissions = permissions::query(); + + // Current thread's primary impersonation token. + Handle dumb() { return Handle{NULL}; } + + Handle open_for_process( + const Handle& process, + DWORD permissions = default_permissions) + { + HANDLE raw; + + if (!OpenProcessToken(process, permissions, &raw)) + error::raise("OpenProcessToken"); + + return Handle{raw}; + } + + Handle open_for_current_process( + DWORD permissions = default_permissions) + { + return open_for_process(Handle{GetCurrentProcess()}, permissions); + } + + Handle get_linked(Handle&& token) + { + if (!os::is_vista_or_later()) + return std::move(token); + + auto type = TokenElevationTypeDefault; + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &cb)) + error::raise("GetTokenInformation"); + + if (type != TokenElevationTypeLimited) + return std::move(token); + + HANDLE raw; + + if (!GetTokenInformation(token, TokenLinkedToken, &raw, sizeof(raw), &cb)) + error::raise("GetTokenInformation"); + + return Handle{raw}; + } + + Handle impersonate(const Handle& token) + { + HANDLE raw; + + if (!DuplicateToken(token, SecurityIdentification, &raw)) + error::raise("DuplicateToken"); + + return Handle{raw}; + } + + // + // FUNCTION: query_integrity_level() + // + // RETURN VALUE: Returns the integrity level of the current process. It is + // usually one of these values: + // + // SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) + // Means untrusted level. It is used by processes started by the + // Anonymous group. Blocks most write access. + // + // SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) + // Means low integrity level. It is used by Protected Mode Internet + // Explorer. Blocks write acess to most objects (such as files and + // registry keys) on the system. + // + // SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) + // Means medium integrity level. It is used by normal applications + // being launched while UAC is enabled. + // + // SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) + // Means high integrity level. It is used by administrative applications + // launched through elevation when UAC is enabled, or normal + // applications if UAC is disabled and the user is an administrator. + // + // SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) + // Means system integrity level. It is used by services and other + // system-level applications (such as Wininit, Winlogon, Smss, etc.) + // + DWORD query_integrity_level(const Handle& token) + { + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &cb)) + { + switch (GetLastError()) + { + case ERROR_INSUFFICIENT_BUFFER: + break; + default: + error::raise("GetTokenInformation"); + } + } + + std::vector buf(cb); + const auto token_level = reinterpret_cast(buf.data()); + + if (!GetTokenInformation(token, TokenIntegrityLevel, token_level, cb, &cb)) + error::raise("GetTokenInformation"); + + // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. + // S-1-16-0x1000 stands for low integrity level SID). There is one and + // only one subauthority. + return *GetSidSubAuthority(token_level->Label.Sid, 0); + } + + std::wstring integrity_level_to_string(DWORD level) + { + static const std::unordered_map names = + { + {SECURITY_MANDATORY_UNTRUSTED_RID, L"Untrusted"}, + {SECURITY_MANDATORY_LOW_RID, L"Low"}, + {SECURITY_MANDATORY_MEDIUM_RID, L"Medium"}, + {SECURITY_MANDATORY_HIGH_RID, L"High"}, + {SECURITY_MANDATORY_SYSTEM_RID, L"System"}, + }; + + static constexpr auto unknown_name = L"Unknown"; + + const auto it = names.find(level); + + if (it == names.cend()) + return unknown_name; + + return it->second; + } + + bool belongs(const Handle& token, const SidBuffer& sid) + { + BOOL b = FALSE; + + if (!CheckTokenMembership(token, const_cast(sid.data()), &b)) + error::raise("CheckTokenMembership"); + + return b != FALSE; + } + + bool is_elevated(const Handle& token) + { + TOKEN_ELEVATION elevation; + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &cb)) + error::raise("GetTokenInformation"); + + return elevation.TokenIsElevated != 0; + } +} -- cgit v1.2.3