📜 ⬆️ ⬇️

Moving beyond the boundaries of the Windows 8 Modern-Application container

Back in the Windows Vista operating system, Microsoft added a sandbox creation tool, the so-called Integrity Levels :
Untrusted <Low <Medium <High <System .

Everything in the operating system (files, registry branches, synchronization objects, pipes, processes, threads) has its Integrity Level. A process that has, for example, Low Integrity Level cannot open a file from a disk that has a Medium Integrity Level (the default level).

It is on this mechanism that UAC and Run as administrator work, increasing the Integrity Level of the process being launched. The sandbox in Google Chrome works on this technology: all tab processes have the lowest Integrity Level - Untrusted, which makes it impossible for the process to interact with any files, processes, registry branches, etc. at all.
')


This is one of the strengths of Chrome security - after all, even if you find in it some stack overflow, you will be rested against the OS security system, which will not allow you to go beyond the boundaries of the process. By the way, Microsoft itself applied such a browser sandboxing mechanism only 4 years later in Win8.1 + IE 11 (it was in the off state in Win8 + IE 10 - but who will go and search and enable it, so it does not count).

With the release of Windows 8, Microsoft needed to make the isolation mechanism of Modern-applications, similar to those used in other mobile operating systems. It was necessary to make it clear to both the user and the developer that the program from the store would not get the user's private data without his consent, would not break his system and would not disrupt other applications, even with his own crash. To implement this idea, the Integrity Levels mechanism was again used. Microsoft came up with such a thing as "AppContainer". Reading the docks on the Internet and even looking at the process description in Process Explorer, you might think that AppContainer is another Integrity Level. True, it is not clear where he is - between Low and Medium? Between Untrusted and Low? What can I say: both the docks on the Internet and the Process Explorer utility are lying . I can’t imagine how marketers should have programmed their heads up so that the data fields from the official structures were intentionally displayed incorrectly, but this is how it is.

The correct state of affairs is shown by the third-party ProcessHacker utility. As we can see from it, AppContainer is not a new Integrity Level. This is just a special label that is added to the process that is running under the Low Integrity Level. At the same time, this label is unique for each application and is used as an additional barrier, restricting access not only to applications with higher Integrity Levels, but even between processes with Low Integrity Levels, but different AppContainer tags.

Up to this point, everything was more or less logical. But from here begins obscurantism.


Obscurantism


For some reason, this default behavior by many (including Microsoft employees) is called the only possible one. Here, for example, a study of Mozilla, to which Microsoft declared that they could not use pipelines between a modern application and a regular desktop. Here is the question on Stackoverflow with the same answer from a Microsoft employee. Here is a report at the BUILD conference, where again the Microsoft employee twice (at 47:20 and 55:00) states that it is impossible to create a complex from the backend in the desktop application and the frontend in the Modern part. And once again about the same thing in a blog on MSDN - again from a Microsoft employee.

All this is nonsense, the default behavior can be changed and from the application in AppContainer we can communicate (via pipes, memory-mapped files, mutexes, etc.) with applications under any higher Integrity Levels.

Spoiler


I’ll say right away that there will not be any “0-day exploit” and “wow, we hacked Windows!”. Everything that I will talk about is in MSDN, is official and works under Win8 and Win 8.1. Just somehow it is difficult to find it, plus from across the sea of ​​obvious misinformation from the links above it’s all that no one is even looking for.

The essence


Yes, the application in the AppContainer (by the way, this is not only the Modern-application, but also the same desktop IE 11) cannot itself go beyond the boundary of its container, the global named operating system objects are not available to it, it cannot open the file from the disk (except your folder). But let's remember our task - to associate a desktop application running at least Medium Integrity Level with an application in AppContainer. And it turns out that an application can create a named object (which by default inherits the Integrity Level process) and give access to it to applications with lower Integrity Levels. Moreover, on this object we can even hang the label of a certain AppContainer or even all AppContainers in the system, which will make it possible to access this object from these processes.

It is possible to draw an analogy with a prisoner in a cell who cannot get out of it himself, but a guard outside the cell may quite willingly communicate with him or even give access to that part of the prison where he can get to.

The starting point for us is the code from this article in MSDN:

Code
#pragma comment(lib, "advapi32.lib") #include <windows.h> #include <stdio.h> #include <aclapi.h> #include <tchar.h> int main(void) { BOOL GetLogonSid (HANDLE hToken, PSID *ppsid) { BOOL bSuccess = FALSE; DWORD dwLength = 0; PTOKEN_GROUPS ptg = NULL; // Verify the parameter passed in is not NULL. if (NULL == ppsid) goto Cleanup; // Get required buffer size and allocate the TOKEN_GROUPS buffer. if (!GetTokenInformation( hToken, // handle to the access token TokenLogonSid, // get information about the token's groups (LPVOID) ptg, // pointer to TOKEN_GROUPS buffer 0, // size of buffer &dwLength // receives required buffer size )) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto Cleanup; ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (ptg == NULL) goto Cleanup; } // Get the token group information from the access token. if (!GetTokenInformation( hToken, // handle to the access token TokenLogonSid, // get information about the token's groups (LPVOID) ptg, // pointer to TOKEN_GROUPS buffer dwLength, // size of buffer &dwLength // receives required buffer size ) || ptg->GroupCount != 1) { goto Cleanup; } // Found the logon SID; make a copy of it. dwLength = GetLengthSid(ptg->Groups[0].Sid); *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (*ppsid == NULL) goto Cleanup; if (!CopySid(dwLength, *ppsid, ptg->Groups[0].Sid)) { HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); goto Cleanup; } bSuccess = TRUE; Cleanup: // Free the buffer for the token groups. if (ptg != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); return bSuccess; } BOOL CreateObjectSecurityDescriptor(PSID pLogonSid, PSECURITY_DESCRIPTOR* ppSD) { BOOL bSuccess = FALSE; DWORD dwRes; PSID pAllAppsSID = NULL; PACL pACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea[2]; SID_IDENTIFIER_AUTHORITY ApplicationAuthority = SECURITY_APP_PACKAGE_AUTHORITY; // Create a well-known SID for the all appcontainers group. if(!AllocateAndInitializeSid(&ApplicationAuthority, SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, 0, 0, 0, 0, 0, 0, &pAllAppsSID)) { wprintf(L"AllocateAndInitializeSid Error %u\n", GetLastError()); goto Cleanup; } // Initialize an EXPLICIT_ACCESS structure for an ACE. // The ACE will allow LogonSid generic all access ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance= NO_INHERITANCE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; ea[0].Trustee.ptstrName = (LPTSTR) pLogonSid; // Initialize an EXPLICIT_ACCESS structure for an ACE. // The ACE will allow the all appcontainers execute permission ea[1].grfAccessPermissions = STANDARD_RIGHTS_READ | STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTEX_MODIFY_STATE; ea[1].grfAccessMode = SET_ACCESS; ea[1].grfInheritance= NO_INHERITANCE; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[1].Trustee.ptstrName = (LPTSTR) pAllAppsSID; // Create a new ACL that contains the new ACEs. dwRes = SetEntriesInAcl(2, ea, NULL, &pACL); if (ERROR_SUCCESS != dwRes) { wprintf(L"SetEntriesInAcl Error %u\n", GetLastError()); goto Cleanup; } // Initialize a security descriptor. pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (NULL == pSD) { wprintf(L"LocalAlloc Error %u\n", GetLastError()); goto Cleanup; } if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { wprintf(L"InitializeSecurityDescriptor Error %u\n", GetLastError()); goto Cleanup; } // Add the ACL to the security descriptor. if (!SetSecurityDescriptorDacl(pSD, TRUE, // bDaclPresent flag pACL, FALSE)) // not a default DACL { wprintf(L"SetSecurityDescriptorDacl Error %u\n", GetLastError()); goto Cleanup; } *ppSD = pSD; pSD = NULL; bSuccess = TRUE; Cleanup: if (pAllAppsSID) FreeSid(pAllAppsSID); if (pACL) LocalFree(pACL); if (pSD) LocalFree(pSD); return bSuccess; }   PSID pLogonSid = NULL; PSECURITY_DESCRIPTOR pSd = NULL; SECURITY_ATTRIBUTES SecurityAttributes; HANDLE hToken = NULL; HANDLE hMutex = NULL;   //Allowing LogonSid and all appcontainers. if (GetLogonSid(hToken, &pLogonSid) && CreateObjectSecurityDescriptor(pLogonSid, &pSd) ) { SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = pSd; hMutex = CreateMutex( &SecurityAttributes, // default security descriptor FALSE, // mutex not owned TEXT("NameOfMutexObject")); // object name } return 0; } 



This is where a mutex is created, shared between this process and all AppContainers of the current user of the system. A mutex created in this way can be quietly opened from the process of any Modern-application or desktop application running in AppContainer.

Couple of moments




Good luck in the development and less believe when you say "it can not be done in any way."

Source: https://habr.com/ru/post/186812/


All Articles