From aeb1d7ae1ba3ca210240728b5146531cf1c5d0c6 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 1 Nov 2016 03:36:32 -0700 Subject: [PATCH] win-capture: Add ability to open UWP named kernel objects The only way to open named kernel objects within a UWP "app" is to get the AppContainer SID, and then open the objects with their full system namespace names via undocumented NT functions. --- plugins/win-capture/CMakeLists.txt | 3 + plugins/win-capture/app-helpers.c | 77 ++++++++++++++++++++++++ plugins/win-capture/app-helpers.h | 9 +++ plugins/win-capture/nt-stuff.h | 94 ++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 plugins/win-capture/app-helpers.c create mode 100644 plugins/win-capture/app-helpers.h create mode 100644 plugins/win-capture/nt-stuff.h diff --git a/plugins/win-capture/CMakeLists.txt b/plugins/win-capture/CMakeLists.txt index 8c0e4bfa3..a0965bd93 100644 --- a/plugins/win-capture/CMakeLists.txt +++ b/plugins/win-capture/CMakeLists.txt @@ -1,7 +1,9 @@ project(win-capture) set(win-capture_HEADERS + nt-stuff.h obfuscate.h + app-helpers.h hook-helpers.h inject-library.h cursor-capture.h @@ -12,6 +14,7 @@ set(win-capture_HEADERS set(win-capture_SOURCES dc-capture.c obfuscate.c + app-helpers.c inject-library.c cursor-capture.c game-capture.c diff --git a/plugins/win-capture/app-helpers.c b/plugins/win-capture/app-helpers.c new file mode 100644 index 000000000..27a48639e --- /dev/null +++ b/plugins/win-capture/app-helpers.c @@ -0,0 +1,77 @@ +#include +#include +#include "app-helpers.h" +#include "nt-stuff.h" + +WINADVAPI WINAPI ConvertSidToStringSidW(PSID sid, LPWSTR *str); + +bool is_app(HANDLE process) +{ + DWORD size_ret; + DWORD ret = 0; + HANDLE token; + + if (OpenProcessToken(process, TOKEN_QUERY, &token)) { + BOOL success = GetTokenInformation(token, TokenIsAppContainer, + &ret, sizeof(ret), &size_ret); + if (!success) { + DWORD error = GetLastError(); + int test = 0; + } + + CloseHandle(token); + } + return !!ret; +} + +wchar_t *get_app_sid(HANDLE process) +{ + wchar_t *ret = NULL; + DWORD size_ret; + BOOL success; + HANDLE token; + + if (OpenProcessToken(process, TOKEN_QUERY, &token)) { + DWORD info_len = GetSidLengthRequired(12) + + sizeof(TOKEN_APPCONTAINER_INFORMATION); + + PTOKEN_APPCONTAINER_INFORMATION info = malloc(info_len); + + success = GetTokenInformation(token, TokenAppContainerSid, + info, info_len, &size_ret); + if (success) + ConvertSidToStringSidW(info->TokenAppContainer, &ret); + + free(info); + CloseHandle(token); + } + + return ret; +} + +static const wchar_t *path_format = + L"\\Sessions\\%lu\\AppContainerNamedObjects\\%s\\%s"; + +HANDLE open_app_mutex(const wchar_t *sid, const wchar_t *name) +{ + wchar_t path[MAX_PATH]; + DWORD session_id = WTSGetActiveConsoleSessionId(); + _snwprintf(path, MAX_PATH, path_format, session_id, sid, name); + return nt_open_mutex(path); +} + +HANDLE open_app_event(const wchar_t *sid, const wchar_t *name) +{ + wchar_t path[MAX_PATH]; + DWORD session_id = WTSGetActiveConsoleSessionId(); + _snwprintf(path, MAX_PATH, path_format, session_id, sid, name); + return nt_open_event(path); +} + +HANDLE open_app_map(const wchar_t *sid, const wchar_t *name) +{ + wchar_t path[MAX_PATH]; + DWORD session_id = WTSGetActiveConsoleSessionId(); + _snwprintf(path, MAX_PATH, path_format, session_id, sid, name); + return nt_open_map(path); +} diff --git a/plugins/win-capture/app-helpers.h b/plugins/win-capture/app-helpers.h new file mode 100644 index 000000000..4688ff5af --- /dev/null +++ b/plugins/win-capture/app-helpers.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +extern bool is_app(HANDLE process); +extern wchar_t *get_app_sid(HANDLE process); +extern HANDLE open_app_mutex(const wchar_t *sid, const wchar_t *name); +extern HANDLE open_app_event(const wchar_t *sid, const wchar_t *name); +extern HANDLE open_app_map(const wchar_t *sid, const wchar_t *name); diff --git a/plugins/win-capture/nt-stuff.h b/plugins/win-capture/nt-stuff.h new file mode 100644 index 000000000..03171bc3d --- /dev/null +++ b/plugins/win-capture/nt-stuff.h @@ -0,0 +1,94 @@ +#pragma once + +#include + +#ifndef NT_SUCCESS +#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0) +#endif + +#define init_named_attribs(o, name) \ + do { \ + (o)->Length = sizeof(*(o)); \ + (o)->ObjectName = name; \ + (o)->RootDirectory = NULL; \ + (o)->Attributes = 0; \ + (o)->SecurityDescriptor = NULL; \ + (o)->SecurityQualityOfService = NULL; \ + } while (false) + +typedef void (WINAPI *RTLINITUNICODESTRINGFUNC)(PCUNICODE_STRING pstr, const wchar_t *lpstrName); +typedef NTSTATUS (WINAPI *NTOPENFUNC)(PHANDLE phandle, ACCESS_MASK access, POBJECT_ATTRIBUTES objattr); + +static FARPROC get_nt_func(const char *name) +{ + static bool initialized = false; + static HANDLE ntdll = NULL; + if (!initialized) { + ntdll = GetModuleHandleW(L"ntdll"); + initialized = true; + } + + return GetProcAddress(ntdll, name); +} + +static void nt_set_last_error(NTSTATUS status) +{ + static bool initialized = false; + static RTLNTSTATUSTODOSERRORFUNC func = NULL; + + if (!initialized) { + func = (RTLNTSTATUSTODOSERRORFUNC)get_nt_func( + "RtlNtStatusToDosError"); + initialized = true; + } + + if (func) + SetLastError(func(status)); +} + +static void rtl_init_str(UNICODE_STRING *unistr, const wchar_t *str) +{ + static bool initialized = false; + static RTLINITUNICODESTRINGFUNC func = NULL; + + if (!initialized) { + func = (RTLINITUNICODESTRINGFUNC)get_nt_func( + "RtlInitUnicodeString"); + initialized = true; + } + + if (func) + func(unistr, str); +} + +#define MAKE_NT_OPEN_FUNC(func_name, nt_name, access) \ +static HANDLE func_name(const wchar_t *name) \ +{ \ + static bool initialized = false; \ + static NTOPENFUNC open = NULL; \ + HANDLE handle; \ + NTSTATUS status; \ + UNICODE_STRING unistr; \ + OBJECT_ATTRIBUTES attr; \ +\ + if (!initialized) { \ + open = (NTOPENFUNC)get_nt_func(#nt_name); \ + initialized = true; \ + } \ +\ + if (!open) \ + return NULL; \ +\ + rtl_init_str(&unistr, name); \ + init_named_attribs(&attr, &unistr); \ +\ + status = open(&handle, access, &attr); \ + if (NT_SUCCESS(status)) \ + return handle; \ + nt_set_last_error(status); \ + return NULL; \ +} + +MAKE_NT_OPEN_FUNC(nt_open_mutex, NtOpenMutant, SYNCHRONIZE) +MAKE_NT_OPEN_FUNC(nt_open_event, NtOpenEvent, EVENT_MODIFY_STATE | SYNCHRONIZE) +MAKE_NT_OPEN_FUNC(nt_open_map, NtOpenSection, FILE_MAP_READ | FILE_MAP_WRITE)