Monday, May 4, 2015

In-Console-Able

Posted by James Forshaw, giving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security community a shoulder to cry on.


TL;DR; this blog post describes an unfixed bug in Windows 8.1 which allows you to escape restrictive job objects in order to help to develop a sandbox escape chain in Chrome or similar sandboxes.

If you’re trying to develop a secure application sandbox in user-mode you’re at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mercies of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying operating system. While you can try and use every available security feature, sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS developer ends up subverting your efforts. This was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 topic of my presentation at Shmoocon and Nullcon, focusing on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 difficulty of securing a user-mode sandbox on Windows.

Exploiting a modern sandboxed application typically requires a chain of bugs to fully compromise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application and escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox. Some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se bugs might not in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves seem very serious, but chained togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y lead to a complete compromise. This blog post will focus on a specific issue that Microsoft decided not to fix, and which has an impact on sandboxes such as that used in Chrome. I wasn’t able to present it at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conference, so I’ll go into some depth here on how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug works, how much it compromised sandbox security and how to practically exploit it.

Windows Job Objects


Let’s first describe what a Job object on Windows actually is and what Chrome uses it for. Strictly speaking, a Job object isn’t a security feature at all; instead, it is a way of grouping related processes togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r and restricting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type and amount of common resources cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processes are allowed to use. If you’re from a Unix background it’s similar to ulimit, but in many ways more powerful. In certain circumstances you can use it to restrict what a process can do; for example, Chrome renderers have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following Job object set:

job_object.PNG

This Job object restricts access to various UI features, such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 clipboard, but it also limits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of active processes to 1. This means that even if it wanted to, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 renderer would be blocked from creating any new child processes, and this restriction is enforced in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. This is only much of a barrier when running with a restrictive token. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, when running as a normal user you can use system services such as WMI or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Task Scheduler to escape.

There are some vulnerabilities which benefit from being able to create new processes (for example this) so while breaking out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object wouldn’t be an immediate sandbox escape it’d be useful as part of a chain of exploits. So now let’s go into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability which allows you to break out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job object.

Console Driver Vulnerability


In early versions of Windows (that is, XP and earlier) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 console window was actually handled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Client Server Runtime Subsystem, better known as CSRSS. This subsystem implements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user-mode components of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Win32 windowing system. But this had disadvantages, not least of which you couldn’t apply cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mes to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 window correctly, which is why cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 console window always looked out of place on XP. So in later versions of Windows a new process, conhost.exe, was introduced, which would be spawned on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s desktop to handle cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 console window. However, CSRSS was still involved in creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new instance of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost process.

That all changed in Windows 8.1. Instead of CSRSS being responsible, a new kernel driver, condrv.sys was introduced. The driver exposes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device object \Device\ConDrv, which is accessible from any user context, even one as seriously locked down as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome renderer. In fact cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no known way of removing access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver. Commands are sent to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver using device IO control codes. The command of interest is CdpLaunchServerProcess which is responsible for creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost executable. Calling this directly is a bit involved, especially on 64-bit versions of Windows, so instead we can just call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows API AllocConsole and it will do it for us.

Let’s look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code that CdpLaunchServerProcess calls to create a new instance of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost.exe process.

NTSTATUS CdpCreateProcess(PHANDLE handle,
                         HANDLE token_handle,
                         PRTL_USER_PROCESS_PARAMETERS pp) {  
 HANDLE thread_handle;
 NTSTATUS result;    
 PROCESS_ATTRIBUTE_LIST attrib_list;

 SetProcessExecutable(&attrib_list, L"\\SystemRoot\\System32\\Conhost.exe");
 SetProcessToken(&attrib_list, token_handle);
 
 result = ZwCreateUserProcess(
            handle,
            &thread_handle,
            ...,
            PROCESS_BREAKAWAY_JOB,  // Process Flags
            CREATE_SUSPENDED,       // Thread Flags
     ...,                         
            &attrib_list);
 
 if ( result < 0 )
   *handle = NULL;
 else
   ObCloseHandle(thread_handle, 0);    
 
 return result;
}

There are two very important things to note in this snippet of code which is directly related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability. First, it’s calling a Zw form of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call NtCreateUserProcess. This prefix indicates that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call will be dispatched as if it was a system call coming from kernel mode as opposed to user mode. This is important as it means that any security checks are bypassed within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process creation. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 normal Nt form, it wouldn’t be possible to escape from something like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome renderer as without this cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost.exe file cannot be opened (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open would result in access denied) making this function fail pretty quickly.

The second important thing is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 passing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PROCESS_BREAKAWAY_JOB flag for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process flags. While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function isn’t documented, by reverse engineering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel code you’ll find this flag indicates that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process should not be in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same job as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parent. This means that a restrictive job object can be escaped. During cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processing of this flag in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel a check is made for SeTcbPrivilege; however, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check is running as if coming from kernel mode (again due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Zw function call) this check is bypassed regardless of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller.

The end result is this:
  • File security checks are bypassed leading to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost process being created.
  • The restrictive job is escaped due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 passing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PROCESS_BREAKAWAY_JOB flag.

For some users of restrictive job objects, such as Chrome GPU processes or Adobe Reader, all you need to exploit this issue is to call AllocConsole. But as we’ll see it isn’t quite so simple in Chrome Renderers.

Exploiting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Issue in a Chrome Renderer


We want to try and exploit this from Chrome renderers, which are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most locked down sandboxed processes used in Chrome. The first challenge is to get code running inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 context of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 renderer to test cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit.

Custom Test Code in a Renderer

The obvious thought is to use a DLL injector, unfortunately this is easier said than done. The primary token for a renderer process is so restrictive it’s almost impossible to get it to open a file on disk so while you can inject a new thread to load cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file open will fail.

Now you can just recompile Chromium with a few tweaks to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox policy to allow access to an arbitrary location on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 disk, but from M37 onwards cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a way we can cheat and just use a release build. M37 added support for DirectWrite font rendering, in order to facilitate this a sandbox policy rule was added to allow read access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows font folder. Therefore if we drop our DLL into %windir%\Fonts we can get it to load. A bit hacky sure, but it works. Of course to do this you already need to have code executing as an administrator on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system so it’s not a threat to Chrome’s security. We’ll also need to tweak a few build settings for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL, assuming you’re using Visual Studio, specifically:

  • Removing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 manifest as that doesn’t play nice with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 restrictive sandbox
  • Statically linking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL as you’ll not easily be able to open ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r DLLs once initialized

Testing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Exploit

With a DLL file which can be opened by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome renderer we can inject a thread, call LoadLibrary and get code executing within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process. As a first test let’s try and call AllocConsole and see what happens. If we take a look using Process Monitor we see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost process being created but it never executes, in fact it exits almost immediately with a negative exit status.

Process Monitor.png

If we convert cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exit status to an unsigned integer we get 0xC0000022 which corresponds to STATUS_ACCESS_DENIED. Clearly something isn’t happy and killing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process. To understand what’s going wrong let’s look at some more code after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process creation.

NTSTATUS CdpLaunchServerProcess(
           FILE_OBJECT* ConsoleFile,
           PRTL_USER_PROCESS_PARAMETERS pp) {
   HANDLE hToken;
   HANDLE hProcess;
   NTSTATUS status;
   PACCESS_TOKEN tokenobj = PsReferencePrimaryToken();
   ObOpenObjectByPointer(tokenobj, ..., &hToken);
   
   status = CdpCreateProcess(&hProcess, &hToken, pp);
   if (status >= STATUS_SUCCESS) {
       HANDLE hConsoleFile;
       status = ObOpenObjectByPointer(ConsoleFile,
               0, 0, GENERIC_ALL, IoFileObjectType,
               UserMode, &hConsoleFile);   
       if (status >= STATUS_SUCCESS) {
           // Modify process command line...
           ZwResumeProcess(hProcess);
       }
   }
   
   if (status < STATUS_SUCCESS) {
       ZwTerminateProcess(hProcess, status);
   }
   
   return status;
}

What this code does is create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n it creates a new handle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current console device object so it can pass it on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command line to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost process. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control flow about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only way cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process could be terminated in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way we observed (with ZwTerminateProcess) is if ObOpenObjectByPointer returns STATUS_ACCESS_DENIED when trying to create a new handle. But how can that be, we opened cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device file originally, shouldn’t it also be able to be reopened with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same access rights? Well no, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FILE_OBJECT has an associated Security Descriptor and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DACL doesn’t give our heavily restrictive token GENERIC_ALL access. As we can see in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following screenshot we’re missing an entry for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 renderer’s token restricted SID (S-1-0-0) which would allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 restricted token check to succeed.

condrv_device_security.PNG

Don’t be fooled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RESTRICTED group entry. The RESTRICTED group is just a convention when using restricted tokens, unless cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token is created with that group as a restricted SID it does nothing. So does that mean we can never exploit this bug in Chrome? Of course not, we just need to understand how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FILE_OBJECT’s DACL came to be set.

Unlike files and registry keys which typically inherit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir DACL from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parent container, kernel objects instead get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir default DACL from a special field in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current access token. We can modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current token’s default DACL by passing an appropriate structure to SetTokenInformation with TokenDefaultDacl as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information class. We can do this without needing any special privileges. But what DACL to set? If we look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access token’s enabled groups we only have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current user SID and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logon SID. However as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token is also a restricted token we need to give access to a restricted SID (S-1-0-0, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NULL SID) ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access check will still fail. So let’s change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default DACL to specify full access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logon SID and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NULL SID.

void SetCurrentDacl()
{
   HANDLE hToken;
   if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
   {       
       WCHAR sddl[256];
       PSECURITY_DESCRIPTOR psd = nullptr;
       
       StringCchPrintf(sddl, _countof(sddl),
                   L"D:(A;;GA;;;%ls)(A;;GA;;;S-1-0-0)", GetLogonSid());

       if (ConvertStringSecurityDescriptorToSecurityDescriptor(sddl,
                   SDDL_REVISION_1, &psd, nullptr))
       {
           BOOL present;
           BOOL defaulted;
           PACL dacl;
           GetSecurityDescriptorDacl(psd, &present, &dacl, &defaulted);

           TOKEN_DEFAULT_DACL default_dacl;
           default_dacl.DefaultDacl = dacl;

           SetTokenInformation(hToken, TokenDefaultDacl,
                   &default_dacl, sizeof(default_dacl));               

           LocalFree(psd);
       }       
   }
}

Now after setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current DACL we can try again, but AllocConsole still fails. However looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 error code we’ve at least got past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial problem. Process Monitor shows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process exit code as STATUS_DLL_NOT_FOUND, which tells us what’s happening.

When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process’s first thread runs it doesn’t actually start directly at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process entry point. Instead it runs a special piece of code inside NTDLL to initialize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process, LdrInitializeThunk. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Ldr prefix suggests (it’s short for Loader) this function is responsible for scanning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process’s imported DLLs, loading cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m into memory and calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir initialization functions. In this case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process token is so restrictive we cannot even open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 typical DLL files. Fortunately cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a time window between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process being created and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial thread being resumed with ZwResumeProcess. If we can capture cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process within that window we can just initialize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process as an empty shell. But how can we do this?

Capturing New Process

The obvious way of exploiting this would be to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 timing window cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n call NtSuspendProcess on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handle. This would work because suspend/resume operations are reference counted. The process starts with a suspension count of 1, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel driver created cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial thread with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CREATE_SUSPENDED flag, so if we can call NtSuspendProcess quickly we can increment that to 2. The driver cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n decrements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 count by calling ZwResumeProcess, however this only drops cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 count to 1 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will leave cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread suspended. We can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n manipulate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process to remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initialization code and run outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job object.

But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a big problem with this plan. Normally when you create a new process a handle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process is returned, but this isn’t cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case here as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel driver closes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel-only handle before returning to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller. Therefore we need to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process by its PID, but guessing that could be tricky. Modern versions of Windows do not just keep incrementing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PID, instead reusing old PIDs after a certain period of time. We can just keep guessing but every wrong guess is time wasted. You’ll find that a brute force approach is pretty much impossible to use.

So are we stuck? Of course not, we just need to use furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r undocumented features. The kernel exposes a system call, NtGetNextProcess which as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name suggests gets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next process. But next to what? If you’ve done any Windows internals you’ll know that process objects are chained togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r in a big linked list in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. This system call takes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handle to a process object and finds cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next process in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chain that can be opened by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current user.

Process Chain.png

Turns out by default cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r processes that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process can open in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list, even itself due to that pesky default DACL. This means normally NtGetNextProcess always fails. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new conhost process is created however it inherits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new modified default DACL that we can access, this means we can just sit in a very small loop calling NtGetNextProcess until it succeeds. The returned handle is almost certainly conhost so we can quickly suspend cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process, and now can take as much time as we like. We need to do this in a thread as AllocConsole will block, but that’s not a problem. So for example:

HANDLE GetConhostProcess()
{       
   HANDLE hCurr = nullptr;
   
   while (!hCurr)
   {
       hCurr = nullptr;
       if (NtGetNextProcess(hCurr, MAXIMUM_ALLOWED,
                            0, 0, &hCurr) == 0)
       {
           NtSuspendProcess(hCurr);
           return hCurr;
       }
   }

   return 0;
}

So with a handle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conhost process we can modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 LdrInitializeThunk method to prevent it failing and inject some shellcode. You’ll only have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 services of NTDLL as no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r DLL will get mapped in. Still cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 goal has been met, you can now escape a restrictive Job object, even in such a locked down process. What you now do with that power is up to you.

Conclusions


So what use is this? Well not a lot really, at least from a direct escape of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox. It just weakens cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 defences a little and opens up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface for exploiting ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r issues. I can understand why Microsoft wouldn’t want to fix it, it acts in this manner for backwards compatibility reasons and changing it would be difficult. That said I believe it could be made to work within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security context of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API as few applications ever make use of such restrictive tokens as application sandboxes.

Also Chrome works to make furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r efforts to mitigate security issues. For example while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Job breakout removes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 imposed Job UI restrictions Chrome now uses win32k lockdown on all affected platforms, which as far as I can tell can’t be disabled even in child processes. Security mitigations continue to evolve, taking advantage of new features of a platform, however security regressions are inevitable. A well developed sandbox shouldn’t rely on any one platform feature to be secure, as that functionality could break at any time.