Tuesday, October 16, 2018

Injecting Code into Windows Protected Processes using COM - Part 1

Posted by James Forshaw, Google Project Zero

At Recon Montreal 2018 I presented “Unknown Known DLLs and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r Code Integrity Trust Violations” with Alex Ionescu. We described cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of Microsoft Windows’ Code Integrity mechanisms and how Microsoft implemented Protected Processes (PP). As part of that I demonstrated various ways of bypassing Protected Process Light (PPL), some requiring administrator privileges, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs not.

In this blog I’m going to describe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process I went through to discover a way of injecting code into a PPL on Windows 10 1803. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only issue Microsoft considered to be violating a defended security boundary has now been fixed I can discuss cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit in more detail.

Background on Windows Protected Processes

The origins of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows Protected Process (PP) model stretch back to Vista where it was introduced to protect DRM processes. The protected process model was heavily restricted, limiting loaded DLLs to a subset of code installed with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operating system. Also for an executable to be considered eligible to be started protected it must be signed with a specific Microsoft certificate which is embedded in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary. One protection that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel enforced is that a non-protected process couldn’t open a handle to a protected process with enough rights to inject arbitrary code or read memory.

In Windows 8.1 a new mechanism was introduced, Protected Process Light (PPL), which made cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protection more generalized. PPL loosened some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 restrictions on what DLLs were considered valid for loading into a protected process and introduced different signing requirements for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main executable. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r big change was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 introduction of a set of signing levels to separate out different types of protected processes. A PPL in one level can open for full access any process at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same signing level or below, with a restricted set of access granted to levels above. These signing levels were extended to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old PP model, a PP at one level can open all PP and PPL at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same signing level or below, however cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reverse was not true, a PPL can never open a PP at any signing level for full access. Some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 levels and this relationship are shown below:

Signing levels allow Microsoft to open up protected processes to third-parties, although at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current time cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only type of protected process that a third party can create is an Anti-Malware PPL. The Anti-Malware level is special as it allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 third party to add additional permitted signing keys by registering an Early Launch Anti-Malware (ELAM) certificate. There is also Microsoft’s TruePlay, which is an Anti-Cheat technology for games which uses components of PPL but it isn’t really important for this discussion.

I could spend a lot of this blog post describing how PP and PPL work under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hood, but I recommend reading cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 blog post series by Alex Ionescu instead (Parts 1, 2 and 3) which will do a better job. While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 blog posts are primarily based on Windows 8.1, most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 concepts haven’t changed substantially in Windows 10.

I’ve written about Protected Processes before [link], in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 form of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 custom implementation by Oracle in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir VirtualBox virtualization platform on Windows. The blog showed how I bypassed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process protection using multiple different techniques. What I didn’t mention at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first technique I described, injecting JScript code into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process, also worked against Microsoft's PPL implementation. I reported that I could inject arbitrary code into a PPL to Microsoft (see Issue 1336) from an abundance of caution in case Microsoft wanted to fix it. In this case Microsoft decided it wouldn’t be fixed as a security bulletin. However Microsoft did fix cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next major release on Windows (version 1803) by adding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code to CI.DLL, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Kernel’s Code Integrity library:

UNICODE_STRING g_BlockedDllsForPPL[] = {
 DECLARE_USTR("scrobj.dll"),
 DECLARE_USTR("scrrun.dll"),
 DECLARE_USTR("jscript.dll"),
 DECLARE_USTR("jscript9.dll"),
 DECLARE_USTR("vbscript.dll")
};

NTSTATUS CipMitigatePPLBypassThroughInterpreters(PEPROCESS Process,
                                                LPBYTE Image,
                                                SIZE_T ImageSize) {
 if (!PsIsProtectedProcess(Process))
   return STATUS_SUCCESS;

 UNICODE_STRING OriginalImageName;
 // Get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original filename from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image resources.
 SIPolicyGetOriginalFilenameAndVersionFromImageBase(
     Image, ImageSize, &OriginalImageName);
 for(int i = 0; i < _countof(g_BlockedDllsForPPL); ++i) {
   if (RtlEqualUnicodeString(g_BlockedDllsForPPL[i],
                             &OriginalImageName, TRUE)) {
     return STATUS_DYNAMIC_CODE_BLOCKED;
   }
 }
 return STATUS_SUCCESS;
}

The fix checks cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original file name in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resource section of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image being loaded against a blacklist of 5 DLLs. The blacklist includes DLLs such as JSCRIPT.DLL, which implements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original JScript scripting engine, and SCROBJ.DLL, which implements scriptlet objects. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel detects a PP or PPL loading one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se DLLs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image load is rejected with STATUS_DYNAMIC_CODE_BLOCKED. This kills my exploit, if you modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resource section of one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 listed DLLs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signature of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image will be invalidated resulting in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image load failing due to a cryptographic hash mismatch. It’s actually cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same fix that Oracle used to block cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack in VirtualBox, although that was implemented in user-mode.

Finding New Targets

The previous injection technique using script code was a generic technique that worked on any PPL which loaded a COM object. With cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 technique fixed I decided to go back and look at what executables will load as a PPL to see if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y have any obvious vulnerabilities I could exploit to get arbitrary code execution. I could have chosen to go after a full PP, but PPL seemed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 easier of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two and I’ve got to start somewhere. There’s so many ways to inject into a PPL if we could just get administrator privileges, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least of which is just loading a kernel driver. For that reason any vulnerability I discover must work from a normal user account. Also I wanted to get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest signing level I can get, which means PPL at Windows TCB signing level.

The first step was to identify executables which run as a protected process, this gives us cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maximum attack surface to analyze for vulnerabilities. Based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 blog posts from Alex it seemed that in order to be loaded as PP or PPL cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signing certificate needs a special Object Identifier (OID) in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 certificate’s Enhanced Key Usage (EKU) extension. There are separate OID for PP and PPL; we can see this below with a comparison between WERFAULTSECURE.EXE, which can run as PP/PPL, and CSRSS.EXE, which can only run as PPL.


I decided to look for executables which have an embedded signature with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se EKU OIDs and that’ll give me a list of all executables to look for exploitable behavior. I wrote cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Get-EmbeddedAucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticodeSignature cmdlet for my NtObjectManager PowerShell module to extract this information.

At this point I realized cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was a problem with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 approach of relying on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signing certificate, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a lot of binaries I expected to be allowed to run as PP or PPL which were missing from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list I generated. As PP was originally designed for DRM cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was no obvious executable to handle cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Protected Media Path such as AUDIODG.EXE. Also, based on my previous research into Device Guard and Windows 10S, I knew cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re must be an executable in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 .NET framework which could run as PPL to add cached signing level information to NGEN generated binaries (NGEN is an Ahead-of-Time JIT to convert a .NET assembly into native code). The criteria for PP/PPL were more fluid than I expected. Instead of doing static analysis I decided to perform dynamic analysis, just start protected every executable I could enumerate and query cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protection level granted. I wrote cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following script to test a single executable:

Import-Module NtObjectManager

function Test-ProtectedProcess {
   [CmdletBinding()]
   param(
       [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
       [string]$FullName,
       [NtApiDotNet.PsProtectedType]$ProtectedType = 0,
       [NtApiDotNet.PsProtectedSigner]$ProtectedSigner = 0
       )
   BEGIN {
       $config = New-NtProcessConfig abc -ProcessFlags ProtectedProcess `
           -ThreadFlags Suspended -TerminateOnDispose `
           -ProtectedType $ProtectedType `
           -ProtectedSigner $ProtectedSigner
   }

   PROCESS {
       $path = Get-NtFilePath $FullName
       Write-Host $path
       try {
           Use-NtObject($p = New-NtProcess $path -Config $config) {
               $prot = $p.Process.Protection
               $props = @{
                   Path=$path;
                   Type=$prot.Type;
                   Signer=$prot.Signer;
                   Level=$prot.Level.ToString("X");
               }
               $obj = New-Object –TypeName PSObject –Prop $props
               Write-Output $obj
           }
       } catch {
       }
   }
}

When this script is executed a function is defined, Test-ProtectedProcess. The function takes a path to an executable, starts that executable with a specified protection level and checks whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r it was successful. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ProtectedType and ProtectedSigner parameters are 0 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel decides cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “best” process level. This leads to some annoying quirks, for example SVCHOST.EXE is explicitly marked as PPL and will run at PPL-Windows level, however as it’s also a signed OS component cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will determine its maximum level is PP-Aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticode. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r interesting quirk is using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native process creation APIs it’s possible to start a DLL as main executable image. As a significant number of system DLLs have embedded Microsoft signatures cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y can also be started as PP-Aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticode, even though this isn’t necessarily that useful. The list of binaries that will run at PPL is shown below along with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir maximum signing level.

Path
Signing Level
C:\windows\Microsoft.Net\Framework\v4.0.30319\mscorsvw.exe
CodeGen
C:\windows\Microsoft.Net\Framework64\v4.0.30319\mscorsvw.exe
CodeGen
C:\windows\system32\SecurityHealthService.exe
Windows
C:\windows\system32\svchost.exe
Windows
C:\windows\system32\xbgmsvc.exe
Windows
C:\windows\system32\csrss.exe
Windows TCB
C:\windows\system32\services.exe
Windows TCB
C:\windows\system32\smss.exe
Windows TCB
C:\windows\system32\werfaultsecure.exe
Windows TCB
C:\windows\system32\wininit.exe
Windows TCB

Injecting Arbitrary Code Into NGEN

After carefully reviewing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of executables which run as PPL I settled on
trying to attack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previously mentioned .NET NGEN binary, MSCORSVW.EXE. My rationale for choosing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NGEN binary was:
  • Most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r binaries are service binaries which might need administrator privileges to start correctly.
  • The binary is likely to be loading complex functionality such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 .NET framework as well as having multiple COM interactions (my go-to technology for weird behavior).
  • In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 worst case it might still yield a Device Guard bypass as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reason it runs as PPL is to give it access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel APIs to apply a cached signing level. Any bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operation of this binary might be exploitable even if we can’t get arbitrary code running in a PPL.

But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is an issue with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NGEN binary, specifically it doesn’t meet my own criteria that I get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top signing level, Windows TCB. However, I knew that when Microsoft fixed Issue 1332 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y left in a back door where a writable handle could be maintained during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signing process if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling process is PPL as shown below:

NTSTATUS CiSetFileCache(HANDLE Handle, ...) {

 PFILE_OBJECT FileObject;
 ObReferenceObjectByHandle(Handle, &FileObject);

 if (FileObject->SharedWrite ||
    (FileObject->WriteAccess &&
     PsGetProcessProtection().Type != PROTECTED_LIGHT)) {
   return STATUS_SHARING_VIOLATION;
 }

 // Continue setting file cache.
}

If I could get code execution inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NGEN binary I could reuse this backdoor to cache sign an arbitrary file which will load into any PPL. I could cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n DLL hijack a full PPL-WindowsTCB process to reach my goal.

To begin cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 investigation we need to determine how to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSCORSVW executable. Using MSCORSVW is not documented anywhere by Microsoft, so we’ll have to do a bit of digging. First off, this binary is not supposed to be run directly, instead it’s invoked by NGEN when creating an NGEN’ed binary. Therefore, we can run cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NGEN binary and use a tool such as Process Monitor to capture what command line is being used for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSCORSVW process. Executing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command:

C:\> NGEN install c:\some\binary.dll

Results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following command line being executed:

MSCORSVW -StartupEvent A -InterruptEvent B -NGENProcess C -Pipe D

A, B, C and D are handles which NGEN ensures are inherited into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process before it starts. As we don’t see any of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original NGEN command line parameters it seems likely cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’re being passed over an IPC mechanism. The “Pipe” parameter gives an indication that  named pipes are used for IPC. Digging into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code in MSCORSVW, we find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method NGenWorkerEmbedding, which looks like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

void NGenWorkerEmbedding(HANDLE hPipe) {
 CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
 CorSvcBindToWorkerClassFactory factory;

 // Marshal class factory.
 IStream* pStm;
 CreateStreamOnHGlobal(nullptr, TRUE, &pStm);
 CoMarshalInterface(pStm, &IID_IClassFactory, &factory,
                    MSHCTX_LOCAL, nullptr, MSHLFLAGS_NORMAL);

 // Read marshaled object and write to pipe.
 DWORD length;
 char* buffer = ReadEntireIStream(pStm, &length);
 WriteFile(hPipe, &length, sizeof(length));
 WriteFile(hPipe, buffer, length);
 CloseHandle(hPipe);

 // Set event to synchronize with parent.
 SetEvent(hStartupEvent);

 // Pump message loop to handle COM calls.
 MessageLoop();

 // ...
}

This code is not quite what I expected. Racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 named pipe for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire communication channel it’s only used to transfer a marshaled COM object back to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling process. The COM object is a class factory instance, normally you’d register cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 factory using CoRegisterClassObject but that would make it accessible to all processes at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same security level so instead by using marshaling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection can be left private only to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NGEN binary which spawned MSCORSVW. A .NET related process using COM gets me interested as I’ve previously described in anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r blog post how you can exploit COM objects implemented in .NET. If we’re lucky this COM object is implemented in .NET, we can determine if it is implemented in .NET by querying for its interfaces, for example we use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Get-ComInterface command in my OleViewDotNet PowerShell module as shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following screenshot.


We’re out of luck, this object is not implemented in .NET, as you’d at least expect to see an instance of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 _Object interface. There’s only one interface implemented, ICorSvcBindToWorker so let’s dig into that interface to see if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s anything we can exploit.

Something caught my eye, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 screenshot cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a HasTypeLib column, for ICorSvcBindToWorker we see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 column is set to True. What HasTypeLib indicates is racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface’s proxy code being implemented using an predefined NDR byte stream it’s generated on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fly from a type library. I’ve abused this auto-generating proxy mechanism before to elevate to SYSTEM, reported as issue 1112. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue I used some interesting behavior of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system’s Running Object Table (ROT) to force a type confusion in a system COM service. While Microsoft has fixed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue for User to SYSTEM cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s nothing stopping us using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type confusion trick to exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSCORSVW process running as PPL at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same privilege level and get arbitrary code execution. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r advantage of using a type library is a normal proxy would be loaded as a DLL which means that it must meet cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPL signing level requirements; however a type library is just data so can be loaded into a PPL without any signing level violations.

How does cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type confusion work? Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ICorSvcBindToWorker interface from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library:

interface ICorSvcBindToWorker : IUnknown {
   HRESULT BindToRuntimeWorker(
             [in] BSTR pRuntimeVersion,
             [in] unsigned long ParentProcessID,
             [in] BSTR pInterruptEventName,
             [in] ICorSvcLogger* pCorSvcLogger,
             [out] ICorSvcWorker** pCorSvcWorker);
};

The single BindToRuntimeWorker takes 5 parameters, 4 are inbound and 1 is outbound. When trying to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method over DCOM from our untrusted process cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system will automatically generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 proxy and stub for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. This will include marshaling COM interface parameters into a buffer, sending cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote process and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n unmarshaling to a pointer before calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real function. For example imagine a simpler function, DoSomething which takes a single IUnknown pointer. The marshaling process looks like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

The operation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method call is as follow:
  1. The untrusted process calls DoSomething on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface which is actually a pointer to DoSomethingProxy which was auto-generated from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library passing an IUnknown pointer parameter.
  2. DoSomethingProxy marshals cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IUnknown pointer parameter into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer and calls over RPC to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Stub in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protected process.
  3. The COM runtime calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DoSomethingStub method to handle cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. This method will unmarshal cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface pointer from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer. Note that this pointer is not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original pointer from step 1, it’s likely to be a new proxy which calls back to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 untrusted process.
  4. The stub invokes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real implemented method inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server, passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unmarshaled interface pointer.
  5. DoSomething uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface pointer, for example by calling AddRef on it via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object’s VTable.

How would we exploit this? All we need to do is modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library so that instead of passing an interface pointer we pass almost anything else. While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library file is in a system location which we can’t modify we can just replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 registration for it in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current user’s registry hive, or use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same ROT trick from before issue 1112. For example if we modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library to pass an integer instead of an interface pointer we get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

The operation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 marshal now changes as follows:
  1. The untrusted process calls DoSomething on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface which is actually a pointer to DoSomethingProxy which was auto-generated from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library passing an arbitrary integer parameter.
  2. DoSomethingProxy marshals cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer parameter into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer and calls over RPC to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Stub in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protected process.
  3. The COM runtime calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DoSomethingStub method to handle cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. This method will unmarshal cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer.
  4. The stub invokes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real implement method inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server, passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameter. However DoSomething hasn’t changed, it’s still cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same method which accepts an interface pointer. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM runtime has no more type information at this point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer is type confused with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface pointer.
  5. DoSomething uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface pointer, for example by calling AddRef on it via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object’s VTable. As this pointer is completely under control of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 untrusted process this likely results in arbitrary code execution.

By changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of parameter from an interface pointer to an integer we induce a type confusion which allows us to get an arbitrary pointer dereferenced, resulting in arbitrary code execution. We could even simplify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack by adding to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following structure:

struct FakeObject {
   BSTR FakeVTable;
};

If we pass a pointer to a FakeObject instead of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface pointer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 auto-generated proxy will marshal cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure and its BSTR, recreating it on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r side in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stub. As a BSTR is a counted string it can contain NULLs so this will create a pointer to an object, which contains a pointer to an arbitrary byte array which can act as a VTable. Place known function pointers in that BSTR and you can easily redirect execution without having to guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of a suitable VTable buffer.

To fully exploit this we’d need to call a suitable method, probably running a ROP chain and we might also have to bypass CFG. That all sounds too much like hard work, so instead I’ll take a different approach to get arbitrary code running in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPL binary, by abusing KnownDlls.

KnownDlls and Protected Processes.

In my previous blog post I described a technique to elevate privileges from an arbitrary object directory creation vulnerability to SYSTEM by adding an entry into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KnownDlls directory and getting an arbitrary DLL loaded into a privileged process. I noted that this was also an administrator to PPL code injection as PPL will also load DLLs from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system’s KnownDlls location. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code signing check is performed during section creation not section mapping as long as you can place an entry into KnownDlls you can load anything into a PPL even unsigned code.

This doesn’t immediately seem that useful, we can’t write to KnownDlls without being an administrator, and even cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n without some clever tricks. However it’s worth looking at how a Known DLL is loaded to get an understanding on how it can be abused. Inside NTDLL’s loader (LDR) code is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following function to determine if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a preexisting Known DLL.

NTSTATUS LdrpFindKnownDll(PUNICODE_STRING DllName, HANDLE *SectionHandle) {
 // If KnownDll directory handle not open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n return error.
 if (!LdrpKnownDllDirectoryHandle)
   return STATUS_DLL_NOT_FOUND;

 OBJECT_ATTRIBUTES ObjectAttributes;
 InitializeObjectAttributes(&ObjectAttributes,
   &DllName,
   OBJ_CASE_INSENSITIVE,
   LdrpKnownDllDirectoryHandle,
   nullptr);

 return NtOpenSection(SectionHandle,
                      SECTION_ALL_ACCESS,
                      &ObjectAttributes);
}

The LdrpFindKnownDll function calls NtOpenSection to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 named section object for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Known DLL. It doesn’t open an absolute path, instead it uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 feature of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native system calls to specify a root directory for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object name lookup in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OBJECT_ATTRIBUTES structure. This root directory comes from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global variable LdrpKnownDllDirectoryHandle. Implementing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call this way allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loader to only specify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename (e.g. EXAMPLE.DLL) and not have to reconstruct cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 absolute path as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lookup with be relative to an existing directory. Chasing references to LdrpKnownDllDirectoryHandle we can find it’s initialized in LdrpInitializeProcess as follows:

NTSTATUS LdrpInitializeProcess() {
 // ...
 PPEB peb = // ...
 // If a full protected process don't use KnownDlls.
 if (peb->IsProtectedProcess && !peb->IsProtectedProcessLight) {
   LdrpKnownDllDirectoryHandle = nullptr;
 } else {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING DirName;
   RtlInitUnicodeString(&DirName, L"\\KnownDlls");
   InitializeObjectAttributes(&ObjectAttributes,
                              &DirName,
                              OBJ_CASE_INSENSITIVE,
                              nullptr, nullptr);
   // Open KnownDlls directory.
   NtOpenDirectoryObject(&LdrpKnownDllDirectoryHandle,
                         DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
                         &ObjectAttributes);
}

This code shouldn’t be that unexpected, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation calls NtOpenDirectoryObject, passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 absolute path to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KnownDlls directory as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object name. The opened handle is stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 LdrpKnownDllDirectoryHandle global variable for later use. It’s worth noting that this code checks cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PEB to determine if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process is a full protected process. Support for loading Known DLLs is disabled in full protected process mode, which is why even with administrator privileges and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 clever trick I outlined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last blog post we could only compromise PPL, not PP.

How does this knowledge help us? We can use our COM type confusion trick to write values into arbitrary memory locations instead of trying to hijack code execution resulting in a data only attack. As we can inherit any handles we like into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new PPL process we can setup an object directory with a named section, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type confusion to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of LdrpKnownDllDirectoryHandle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 inherited handle. If we induce a DLL load from System32 with a known name cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 LDR will check our fake directory for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 named section and map our unsigned code into memory, even calling DllMain for us. No need for injecting threads, ROP or bypassing CFG.

All we need is a suitable primitive to write an arbitrary value, unfortunately while I could find methods which would cause an arbitrary write I couldn’t sufficiently control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value being written. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end I used cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following interface and method which was implemented on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object returned by ICorSvcBindToWorker::BindToRuntimeWorker.

interface ICorSvcPooledWorker : IUnknown {
   HRESULT CanReuseProcess(
           [in] OptimizationScenario scenario,
           [in] ICorSvcLogger* pCorSvcLogger,
           [out] long* pCanContinue);
};
In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of CanReuseProcess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target value of pCanContinue is always initialized to 0. Therefore by replacing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 [out] long* in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type library definition with [in] long we can get 0 written to any memory location we specify. By prefilling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lower 16 bits of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new process’ handle table with handles to a fake KnownDlls directory we can be sure of an alias between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real KnownDlls which will be opened once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process starts and our fake ones by just modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top 16 bits of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handle to 0. This is shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following diagram:


Once we’ve overwritten cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top 16 bits with 0 (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write is 32 bits but handles are 64 bits in 64 bit mode, so we won’t overwrite anything important) LdrpKnownDllDirectoryHandle now points to one of our fake KnownDlls handles. We can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n easily induce a DLL load by sending a custom marshaled object to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same method and we’ll get arbitrary code execution inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPL.

Elevating to PPL-Windows TCB

We can’t stop here, attacking MSCORSVW only gets us PPL at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CodeGen signing level, not Windows TCB. Knowing that generating a fake cached signed DLL should run in a PPL as well as Microsoft leaving a backdoor for PPL processes at any signing level I converted my C# code from Issue 1332 to C++ to generate a fake cached signed DLL. By abusing a DLL hijack in WERFAULTSECURE.EXE which will run as PPL Windows TCB we should get code execution at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desired signing level. This worked on Windows 10 1709 and earlier, however it didn’t work on 1803. Clearly Microsoft had changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behavior of cached signing level in some way, perhaps cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’d removed its trust in PPL entirely. That seemed unlikely as it would have a negative performance impact.

After discussing this a bit with Alex Ionescu I decided to put togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a quick parser with information from Alex for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cached signing data on a file. This is exposed in NtObjectManager as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Get-NtCachedSigningLevel command. I ran this command against a fake signed binary and a system binary which was also cached signed and immediately noticed a difference:


For cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fake signed file cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flags are set to TrustedSignature (0x02), however for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system binary PowerShell couldn’t decode cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 enumeration and so just outputs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer value of 66 which is 0x42 in hex. The value 0x40 was an extra flag on top of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original trusted signature flag. It seemed likely that without this flag set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL wouldn’t be loaded into a PPL process. Something must be setting this flag so I decided to check what happened if I loaded a valid cached signed DLL without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 extra flag into a PPL process. Monitoring it in Process Monitor I got my answer:


The Process Monitor trace shows that first cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel queries for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Extended Attributes (EA) from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL. The cached signing level data is stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file’s EA so this is almost certainly an indication of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cached signing level being read. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full trace artifacts of checking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full signature are shown such as enumerating catalog files, I’ve removed those artifacts from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 screenshot for brevity. Finally cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 EA is set, if I check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cached signing level of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file it now includes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 extra flag. So setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cached signing level is done automatically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question is how? By pulling up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack trace we can see how it happens:


Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack trace we can see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to CipSetFileCache originates from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to NtCreateSection. The kernel is automatically caching cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signature when it makes sense to do so, e.g. in a PPL so that subsequent image mapping don’t need to recheck cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signature. It’s possible to map an image section from a file with write access so we can reuse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same attack from Issue 1332 and replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to NtSetCachedSigningLevel with NtCreateSection and we can fake sign any DLL. It turned out that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file cache happened after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write check introducted to fix Issue 1332 and so it was possible to use this to bypass Device Guard again. For that reason I reported cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bypass as Issue 1597 which was fixed in September 2018 as CVE-2018-8449. However, as with Issue 1332 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 back door for PPL is still in place so even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix eliminated cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Device Guard bypass it can still be used to get us from PPL-CodeGen to PPL-WindowsTCB.

Conclusions

This blog showed how I was able to inject arbitrary code into a PPL without requiring administrator privileges. What could you do with this new found power? Actually not a great deal as a normal user but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are some parts of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS, such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows Store which rely on PPL to secure files and resources which you can’t modify as a normal user. If you elevate to administrator and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n inject into a PPL you’ll get many more things to attack such as CSRSS (through which you can certainly get kernel code execution) or attack Windows Defender which runs as PPL Anti-Malware. Over time I’m sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use cases for PPL will be replaced with Virtual Secure Mode (VSM) and Isolated User Mode (IUM) applications which have greater security guarantees and are also considered security boundaries that Microsoft will defend and fix.

Did I report cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues to Microsoft? Microsoft has made it clear that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will not fix issues only affecting PP and PPL in a security bulletin. Without a security bulletin cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 researcher receives no acknowledgement for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 find, such as a CVE. The issue will not be fixed in current versions of Windows although it might be fixed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next major version. Previously confirming Microsoft’s policy on fixing a particular security issue was based on precedent, however cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’ve recently published a list of Windows technologies that will or will not be fixed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows Security Service Criteria which, as shown below for Protected Process Light, Microsoft will not fix or pay a bounty for issues relating to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 feature. Therefore, from now on I will not be engaging Microsoft if I discover issues which I believe to only affect PP or PPL.


The one bug I reported to Microsoft was only fixed because it could be used to bypass Device Guard. When you think about it, only fixing for Device Guard is somewhat odd. I can still bypass Device Guard by injecting into a PPL and setting a cached signing level, and yet Microsoft won’t fix PPL issues but will fix Device Guard issues. Much as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows Security Service Criteria document really helps to clarify what Microsoft will and won’t fix it’s still somewhat arbitrary. A secure feature is rarely secure in isolation, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 feature is almost certainly secure because ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r features enable it to be so.

In part 2 of this blog we’ll go into how I was also able to break into Full PP-WindowsTCB processes using anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r interesting feature of COM.