Wednesday, April 18, 2018

Windows Exploitation Tricks: Exploiting Arbitrary File Writes for Local Elevation of Privilege

Posted by James Forshaw, Project Zero

Previously I presented a technique to exploit arbitrary directory creation vulnerabilities on Windows to give you read access to any file on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 upcoming Spring Creators Update (RS4) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 abuse of mount points to link to files as I exploited in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post has been remediated. This is an example of a long term security benefit from detailing how vulnerabilities might be exploited, giving a developer an incentive to find ways of mitigating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploitation vector.

Keeping with that spirit in this blog post I’ll introduce a novel technique to exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more common case of arbitrary file writes on Windows 10. Perhaps once again Microsoft might be able to harden cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS to make it more difficult to exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se types of vulnerabilities. I’ll demonstrate exploitation by describing in detail cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recently fixed issue that Project Zero reported to Microsoft (issue 1428).

An arbitrary file write vulnerability is where a user can create or modify a file in a location cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could not normally access. This might be due to a privileged service incorrectly sanitizing information passed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user or due to a symbolic link planting attack where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user can write a link into a location which is subsequently used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 privileged service. The ideal vulnerability is one where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacking user not only controls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file being written but also cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire contents. This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of vulnerability we’ll consider in this blog post.
A common way of exploiting arbitrary file writes is to perform DLL hijacking. When a Windows executable begins executing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial loader in NTDLL will attempt to find all imported DLLs. The locations that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loader checks for imported DLLs are more complex than you’d expect but for our purposes can be summarized as follows:

  1. Check Known DLLs, which is a pre-cached list of DLLs which are known to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS. If found, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL is mapped into memory from a pre-loaded section object.
  2. Check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application’s directory, for example if importing TEST.DLL and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application is in C:\APP cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n it will check C:\APP\TEST.DLL.
  3. Check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system locations, such as C:\WINDOWS\SYSTEM32 and C:\WINDOWS.
  4. If all else fails search cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current environment PATH.

The aim of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL hijack is to find an executable which runs at a high privilege which will load a DLL from a location that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability allows us to write to. The hijack only succeeds if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL hasn’t already been found in a location checked earlier.

There are two problems which make DLL hijacking annoying:

  1. You typically need to create a new instance of a privileged process as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 majority of DLL imports are resolved when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process is first executed.
  2. Most system binaries, executables and DLLs that will run as a privileged user will be installed into SYSTEM32.

The second problem means that in steps 2 and 3 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loader will always look for DLLs in SYSTEM32. Assuming that overwriting a DLL isn’t likely to be an option (at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL is already loaded you can’t write to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file), that makes it harder to find a suitable DLL to hijack. A typical way around cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se problems is to pick an executable that is not located in SYSTEM32 and which can be easily activated, such as by loading a COM server or running a scheduled task.

Even if you find a suitable target executable to DLL hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation can be quite ugly. Sometimes you need to implement stub exports for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original DLL, 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 loading of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL will fail. In ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cases cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best place to run code is during DllMain, which introduces ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r problems such as running code inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loader lock. What would be nice is a privileged service that will just load an arbitrary DLL for us, no hijacking, no needing to spawn cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “correct” privileged process. The question is, does such a service exist?

It turns out yes one does, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service itself has been abused at least twice previously, once by Lokihardt for a sandbox escape, and once by me for user to system EoP. This service goes by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name “Microsoft (R) Diagnostics Hub Standard Collector Service,” but we’ll call it DiagHub for short.

The DiagHub service was introduced in Windows 10, although cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a service that performs a similar task called IE ETW Collector in Windows 7 and 8.1. The purpose of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service is to collect diagnostic information using Event Tracing for Windows (ETW) on behalf of sandboxed applications, specifically Edge and Internet Explorer. One of its interesting features is that it can be configured to load an arbitrary DLL from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SYSTEM32 directory, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact feature that Lokihardt and I exploited to gain elevated privileges. All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functionality for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service is exposed over a registered DCOM object, so in order to load our DLL we’ll need to work out how to call methods on that DCOM object. At this point you can skip to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end but if you want to understand how I would go about finding how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM object is implemented, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next section might be of interest.

Reverse Engineering a DCOM Object

Let’s go through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 steps I would take to try and find what interfaces an unknown DCOM object supports and find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation so we can reverse engineer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. There are two approaches I will typically take, go straight for RE in IDA Pro or similar, or do some on-system inspection first to narrow down cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 areas we have to investigate. Here we’ll go for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second approach as it’s more informative. I can’t say how Lokihardt found his issue; I’m going to opt for magic.

For this approach we’ll need some tools, specifically my OleViewDotNet v1.4+ (OVDN) tool from github as well as an installation of WinDBG from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SDK. The first step is to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 registration information for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM object and discover what interfaces are accessible. We know that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM object is hosted in a service so once you’ve loaded OVDN go to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 menu Registry ⇒ Local Services and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tool will load a list of registered system services which expose COM objects. If you now find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365  “Microsoft (R) Diagnostics Hub Standard Collector Service” service (applying a filter here is helpful) you should find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entry in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list. If you open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service tree node you’ll see a child, “Diagnostics Hub Standard Collector Service,” which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hosted DCOM object. If you open that tree node cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tool will create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n query for all remotely accessible COM interfaces to give you a list of interfaces cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object supports. I’ve shown this in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 screenshot below:


While we’re here it’s useful to inspect what security is required to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM object. If you right click cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class treenode you can select View Access Permissions or View Launch Permissions and you’ll get a window that shows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 permissions. In this case it shows that this DCOM object will be accessible from IE Protected Mode as well as Edge’s AppContainer sandbox, including LPAC.


Of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of interfaces shown we only really care about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 standard interfaces. Sometimes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are interesting interfaces in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 factory but in this case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re aren’t. Of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se standard interfaces cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two we care about, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IStandardCollectorAuthorizationService and IStandardCollectorService. Just to cheat slightly I already know that it’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IStandardCollectorService service we’re interested in, but as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following process is going to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same for each of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interfaces it doesn’t matter which one we pick first. If you right click cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface treenode and select Properties you can see a bit of information about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 registered interface.


There’s not much more information that will help us here, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than we can see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are 8 methods on this interface. As with a lot of COM registration information, this value might be missing or erroneous, but in this case we’ll assume it’s correct. To understand what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 methods are we’ll need to track down cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of IStandardCollectorService inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server. This knowledge will allow us to target our RE efforts to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct binary and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct methods. Doing this for an in-process COM object is relatively easy as we can query for an object’s VTable pointer directly by dereferencing a few pointers. However, for out-of-process it’s more involved. This is because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual in-process object you’d call is really a proxy for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote object, as shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following diagram:


All is not lost, however; we can still find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VTable of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OOP object by extracting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information stored about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server process. Start by right clicking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “Diagnostics Hub Standard Collector Service” object tree node and select Create Instance. This will create a new instance of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM object as shown below:


The instance gives you basic information such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CLSID for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object which we’ll need later (in this case {42CBFAA7-A4A7-47BB-B422-BD10E9D02700}) as well as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of supported interfaces. Now we need to ensure we have a connection to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface we’re interested in. For that select cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IStandardCollectorService interface in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lower list, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Operations menu at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bottom select Marshal ⇒ View Properties. If successful you’ll now see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following new view:


There’s a lot of information in this view but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two pieces of most interest are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Process ID of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hosting service and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Interface Pointer Identifier (IPID). In this case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Process ID should be obvious as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service is running in its own process, but this isn’t always cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case—sometimes when you create a COM object you’ve no idea which process is actually hosting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server so this information is invaluable. The IPID is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unique identifier in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hosting process for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DCOM object; we can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Process ID and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IPID in combination to find this server and from that find out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual VTable implementing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM methods. It’s worth noting that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maximum Process ID size from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IPID is 16 bits; however, modern versions of Windows can have much larger PIDs so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a chance that you’ll have to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process manually or restart cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service multiple times until you get a suitable PID.

Now we’ll use a feature of OVDN which allows us to reach into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server process and find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IPID information. You can access information about all processes through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main menu Object ⇒ Processes but as we know which process we’re interested in just click cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 View button next to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Process ID in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 marshal view. You do need to be running OVDN as an administrator ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise you’ll not be able to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service process. If you’ve not done so already cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tool will ask you to configure symbol support as OVDN needs public symbols to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct locations in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM DLLs to parse. You’ll want to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 version of DBGHELP.DLL which comes with WinDBG as that supports remote symbol servers. Configure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbols similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following dialog:


If everything is correctly configured and you’re an administrator you should now see more details about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IPID, as shown below:


The two most useful pieces of information here are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Interface pointer, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap allocated object (in case you want to inspect its state), and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VTable pointer for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface. The VTable address gives us information for where exactly cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server implementation is located. As we can see here cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VTable is located in a different module (DiagnosticsHub.StandardCollector.Runtime) from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main executable (DiagnosticsHub.StandardCollector.Server). We can verify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VTable address is correct by attaching to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service process using WinDBG and dumping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbols at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VTable address. We also know from before we’re expecting 8 methods so we can take that into account by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command:

dqs DiagnosticsHub_StandardCollector_Runtime+0x36C78 L8

Note that WinDBG converts periods in a module name to underscores. If successful you’ll see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 something similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following screenshot:


Extracting out that information we now get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 methods (shown below) as well as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary. We could set breakpoints and see what gets called during normal operation, or take this information and start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RE process.

ATL::CComObject::QueryInterface
ATL::CComObjectCached::AddRef
ATL::CComObjectCached::Release
StandardCollectorService::CreateSession
StandardCollectorService::GetSession
StandardCollectorService::DestroySession
StandardCollectorService::DestroySessionAsync
StandardCollectorService::AddLifetimeMonitorProcessIdForSession

The list of methods looks correct: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y start with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 3 standard methods for a COM object, which in this case are implemented by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ATL library. Following those methods are five implemented by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 StandardCollectorService class. Being public symbols, this doesn’t tell us what parameters we expect to pass to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 COM server. Due to C++ names containing some type information, IDA Pro might be able to extract that information for you, however that won’t necessarily tell you cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 format of any structures which might be passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function. Fortunately due to how COM proxies are implemented using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Network Data Representation (NDR) interpreter to perform marshalling, it’s possible to reverse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NDR bytecode back into a format we can understand. In this case go back to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original service information, right click cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IStandardCollectorService treenode and select View Proxy Definition. This will get OVDN to parse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NDR proxy information and display a new view as shown below.


Viewing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 proxy definition will also parse out any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r interfaces which that proxy library implements. This is likely to be useful for furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r RE work. The decompiled proxy definition is shown in a C# like pseudo code but it should be easy to convert into working C# or C++ as necessary. Notice that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 proxy definition doesn’t contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 names of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 methods but we’ve already extracted those out. So applying a bit of cleanup and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method names we get a definition which looks like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

[uuid("0d8af6b7-efd5-4f6d-a834-314740ab8caa")]
struct IStandardCollectorService : IUnknown {
   HRESULT CreateSession(_In_ struct Struct_24* p0,
                         _In_ IStandardCollectorClientDelegate* p1,
                         _Out_ ICollectionSession** p2);
   HRESULT GetSession(_In_ GUID* p0, _Out_ ICollectionSession** p1);
   HRESULT DestroySession(_In_ GUID* p0);
   HRESULT DestroySessionAsync(_In_ GUID* p0);
   HRESULT AddLifetimeMonitorProcessIdForSession(_In_ GUID* p0, [In] int p1);
}

There’s one last piece missing; we don’t know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 definition of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Struct_24 structure. It’s possible to extract this from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RE process but fortunately in this case we don’t have to. The NDR bytecode must know how to marshal this structure across so OVDN just extracts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure definition out for us automatically: select cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Structures tab and find Struct_24.


As you go through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RE process you can repeat this process as necessary until you understand how everything works. Now let’s get to actually exploiting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DiagHub service and demonstrating its use with a real world exploit.

Example Exploit

So after our efforts of reverse engineering, we’ll discover that in order to to load a DLL from SYSTEM32 we need to do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following steps:

  1. Create a new Diagnostics Session using IStandardCollectorService::CreateSession.
  2. Call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ICollectionSession::AddAgent method on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new session, passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL to load (without any path information).

The simplified loading code for ICollectionSession::AddAgent is as follows:

void EtwCollectionSession::AddAgent(LPWCSTR dll_path,
                                   REFGUID guid) {
 WCHAR valid_path[MAX_PATH];
 if ( !GetValidAgentPath(dll_path, valid_path)) {
   return E_INVALID_AGENT_PATH;
 HMODULE mod = LoadLibraryExW(valid_path,
       nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
 dll_get_class_obj = GetProcAddress(hModule, "DllGetClassObject");
 return dll_get_class_obj(guid);
}

We can see that it checks that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 agent path is valid and returns a full path (this is where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous EoP bugs existed, insufficient checks). This path is loading using LoadLibraryEx, 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 DLL is queried for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exported method DllGetClassObject which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n called. Therefore to easily get code execution all we need is to implement that method and drop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file into SYSTEM32. The implemented DllGetClassObject will be called outside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loader lock so we can do anything we want. The following code (error handling removed) will be sufficient to load a DLL called dummy.dll.

IStandardCollectorService* service;
CoCreateInstance(CLSID_CollectorService, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&service));

SessionConfiguration config = {};
config.version = 1;
config.monitor_pid = ::GetCurrentProcessId();
CoCreateGuid(&config.guid);
config.path = ::SysAllocString(L"C:\Dummy");
ICollectionSession* session;
service->CreateSession(&config, nullptr, &session);

GUID agent_guid;
CoCreateGuid(&agent_guid);
session->AddAgent(L"dummy.dll", agent_guid);

All we need now is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 arbitrary file write so that we can drop a DLL into SYSTEM32, load it and elevate our privileges. For this I’ll demonstrate using a vulnerability I found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SvcMoveFileInheritSecurity RPC method in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system Storage Service. This function caught my attention due to its use in an exploit for a vulnerability in ALPC discovered and presented by Clément Rouault & Thomas Imbert at PACSEC 2017. While this method was just a useful exploit primitive for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability I realized it has not one, but two actual vulnerabilities lurking in it (at least from a normal user privilege). The code prior to any fixes for SvcMoveFileInheritSecurity looked like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

void SvcMoveFileInheritSecurity(LPCWSTR lpExistingFileName,
                               LPCWSTR lpNewFileName,
                               DWORD dwFlags) {
 PACL pAcl;
 if (!RpcImpersonateClient()) {
   // Move file while impersonating.
   if (MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags)) {
     RpcRevertToSelf();
     // Copy inherited DACL while not.
     InitializeAcl(&pAcl, 8, ACL_REVISION);
     DWORD status = SetNamedSecurityInfo(lpNewFileName, SE_FILE_OBJECT,
         UNPROTECTED_DACL_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
         nullptr, nullptr, &pAcl, nullptr);
       if (status != ERROR_SUCCESS)
         MoveFileEx(lpNewFileName, lpExistingFileName, dwFlags);
   }
   else {
     // Copy file instead...
     RpcRevertToSelf();
   }
 }
}

The purpose of this method seems to be to move a file cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n apply any inherited ACE’s to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DACL from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new directory location. This would be necessary as when a file is moved on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same volume, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old filename is unlinked and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file is linked to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new location. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new file will maintain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security assigned from its original location. Inherited ACEs are only applied when a new file is created in a directory, or as in this case, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ACEs are explicitly applied by calling a function such as SetNamedSecurityInfo.

To ensure this method doesn’t allow anyone to move an arbitrary file while running as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service’s user, which in this case is Local System, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RPC caller is impersonated. The trouble starts immediately after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first call to MoveFileEx, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation is reverted and SetNamedSecurityInfo is called. If that call fails 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 code calls MoveFileEx again to try and revert cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original move operation. This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first vulnerability; it’s possible that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original filename location now points somewhere else, such as through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 abuse of symbolic links. It’s pretty easy to cause SetNamedSecurityInfo to fail, just add a Deny ACL for Local System to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file’s ACE for WRITE_DAC and it’ll return an error which causes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 revert and you get an arbitrary file creation. This was reported as issue 1427.

This is not in fact cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability we’ll be exploiting, as that would be too easy. Instead we’ll exploit a second vulnerability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same code: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that we can get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service to call SetNamedSecurityInfo on any file we like while running as Local System. This can be achieved eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r by abusing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonated device map to redirect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 local drive letter (such as C:) when doing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial MoveFileEx, which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n results in lpNewFileName pointing to an arbitrary location, or more interestingly abusing hard links. This was reported as issue 1428. We can exploit this using hard links as follows:


  1. Create a hard link to a target file in SYSTEM32 that we want to overwrite. We can do this as you don’t need to have write privileges to a file to create a hard link to it, at least outside of a sandbox.
  2. Create a new directory location that has an inheritable ACE for a group such as Everyone or Aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated Users to allow for modification of any new file. You don’t even typically need to do this explicitly; for example, any new directory created in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C: drive has an inherited ACE for Aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated Users. Then a request can be made to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RPC service to move cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardlinked file to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new directory location. The move succeeds under impersonation as long as we have FILE_DELETE_CHILD access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original location and FILE_ADD_FILE in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new location, which we can arrange.
  3. The service will now call SetNamedSecurityInfo on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 moved hardlink file. SetNamedSecurityInfo will pick up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 inherited ACEs from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new directory location and apply cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardlinked file. The reason cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ACEs are applied to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardlinked file is from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 perspective of SetNamedSecurityInfo cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardlinked file is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new location, even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original target file we linked to was in SYSTEM32.

By exploiting this we can modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security of any file that Local System can access for WRITE_DAC access. Therefore we can modify a file in SYSTEM32, 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 DiagHub service to load it. There is a slight problem, however. The majority of files in SYSTEM32 are actually owned by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustedInstaller group and so cannot be modified, even by Local System. We need to find a file we can write to which isn’t owned by TrustedInstaller. Also we’d want to pick a file that won’t cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS install to become corrupt. We don’t care about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file’s extension as AddAgent only checks that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file exists and loads it with LoadLibraryEx. There are a number of ways we can find a suitable file, such as using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SysInternals AccessChk utility, but to be 100% certain that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Storage Service’s token can modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file we’ll use my NtObjectManager PowerShell module (specifically its Get-AccessibleFile cmdlet, which accepts a process to do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access check from). While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module was designed for checking accessible files from a sandbox, it also works to check for files accessible by privileged services. If you run cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following script as an administrator with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module installed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 $files variable will contain a list of files that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Storage Service has WRITE_DAC access to.

Import-Module NtObjectManager

Start-Service -Name "StorSvc"
Set-NtTokenPrivilege SeDebugPrivilege | Out-Null
$files = Use-NtObject($p = Get-NtProcess -ServiceName "StorSvc") {
   Get-AccessibleFile -Win32Path C:\Windows\system32 -Recurse `
    -MaxDepth 1 -FormatWin32Path -AccessRights WriteDac -CheckMode FilesOnly
}

Looking through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of files I decided to pick on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file license.rtf, which contains a short license statement for Windows. The advantage of this file is it’s very likely to be not be critical to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system and so overwriting it shouldn’t cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 installation to become corrupted.

So putting it all togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r:

  1. Use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Storage Service vulnerability to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 license.rtf file inside SYSTEM32.
  2. Copy a DLL, which implements DllGetClassObject over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 license.rtf file.
  3. Use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DiagHub service to load our modified license file as a DLL, get code execution as Local System and do whatever we want.

If you’re interested in seeing a fully working example, I’ve uploaded a full exploit to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original issue on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tracker.

Wrapping Up

In this blog post I’ve described a useful exploit primitive for Windows 10, which you can even use from some sandboxed environments such as Edge LPAC. Finding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se sorts of primitives makes exploitation much simpler and less error-prone. Also I’ve given you a taste of how you can go about finding your own bugs in similar DCOM implementations.

No comments:

Post a Comment