Thursday, October 15, 2015

Windows Drivers are True’ly Tricky

Posted by James Forshaw, Driving for Bugs


Auditing a product for security vulnerabilities can be a difficult challenge, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no guarantee you’ll catch all vulnerabilities even when you do. This post describes an issue I identified in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows Driver code for Truecrypt, which has already gone through a security audit. The issue allows an application running as a normal user or within a low-integrity sandbox to remap cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main system drive and elevate privileges to SYSTEM or even cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. I hope to show why cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug in question might have been missed. I don’t provide any guarantees that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are no more bugs left to find.

It’s worth noting that this vulnerability didn’t have a direct impact on 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 encrypted drive volumes at rest. Before I delve into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 details let’s take a look at an aspect of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows NT operating system that’ll be very important later.

The History of DosDevices

Under MS-DOS and versions of Windows that ran on top of it drive letters were generally assigned in a specific order based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device and disk partition type. In Windows NT this isn’t cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case. As I mentioned in my previous post on symbolic links, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letters you see in Windows Explorer are really symbolic links under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hood which point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter (say C:) to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mounted device object (say \Device\HarddiskVolume4). The OS is free to assign cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se drive letters in an arbitrary order.



The OS needs a known location to store cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se symbolic links so in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original Windows NT 3.1 an object directory was added to 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 object manager namespace called DosDevices. This directory stored all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive and device symbolic links for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system. There was only a single directory for all users, but for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original versions of Windows NT this didn’t matter as you could only ever have one interactive user logged on at one time. When calling a Win32 API which takes a DOS path it’s converted to an absolute drive path and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DosDevices prefix is appended before passing to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native NT system call.

Over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 subsequent versions of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of DosDevices changed. First in NT 4 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name was changed from DosDevices to ??. This was presumably for performance reasons as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel could quickly check for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prefix using two 32 bit integer comparisons for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 4 unicode characters \??\. To ensure old code still worked DosDevices now became a symbolic link pointing to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new shorter path.

The biggest change, however, happened in Windows XP (well technically with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 introduction of Terminal Services but XP was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first consumer OS with this support). XP shipped with Fast User-Switching and remote desktop support, which allowed multiple interactive users to be logged in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same machine at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time. This required that DosDevices supported per-user objects, because it would be annoying and potentially dangerous to allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sharing of user specific drive mapping. To achieve this a per-user object directory is created under \Sessions\0\DosDevices with a name which corresponds to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s logon ID.



So how does this per-user directory get referenced? By creating a fake DosDevices object directory. First cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original ?? directory was renamed to GLOBAL?? and ?? now became a virtual directory. When reading from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory, say resolving a drive letter, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory is checked. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory doesn’t contain a corresponding entry cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel falls back to checking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global directory, if no entry is found cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re 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 generates an appropriate error such as STATUS_OBJECT_NAME_NOT_FOUND. An interesting case is what happens when a process creates a new object in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual directory. Only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory is taken into account so any new object creation to \?? will result in that object being added to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory. The access control on GLOBAL?? is set so that only administrators can modify objects within it, however a normal user is free to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own per-user directory.

To add a furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r complication Windows 2000 introduced cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 concept of a per-process DosDevices directory. This can be specified by calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call NtSetInformationProcess with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ProcessDeviceMap information class passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handle to a new object directory. On Windows 2000 this just replaces cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ?? directory lookup entirely, however on XP and above cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fallback to GLOBAL?? still occurs. This is only used when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lookup is occurring within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same process, no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r process on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new DosDevices map.

Here’s a condensed history of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 major changes in how DosDevices works across NT operating systems.


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

So with that bit of history out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way let’s look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability itself. The opened issue can be found here. The Truecrypt driver exposes a number of different IOCTLs to a user-mode application to perform its various tasks such as mount and unmounting encrypted disk images and enumerating information. The vulnerability is due to bugs in  cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mounting and unmounting of Truecrypt volumes, corresponding to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IOCTLs TC_IOCTL_MOUNT_VOLUME and TC_IOCTL_DISMOUNT_VOLUME. All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable code is contained in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Driver\Ntdriver.c file in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Truecrypt source code.

When a drive is mounted in Windows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are a few ways that a drive letter can be assigned. The most common way is by registering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Mount Manager driver. This requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller to be an administrator, and all registration information will go into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Registry. The alternative is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive can be created manually using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IoCreateSymbolicLink API. Ultimately though it must go into one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DosDevices locations ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise normal user-mode application would not be able to pick up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter.

The Truecrypt driver supports both ways of mounting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive, it can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Mount Manager to mount cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive (if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bMountManager flag is set in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver), however, just in case it also manually creates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link as shown:

// We create symbolic link even if mount manager is notified of
// arriving volume as it apparently sometimes fails to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link
CreateDriveLink (mount->nDosDriveNo);

From user-mode we can only specify a number from 0 to 25 as nDosDriveNo which represents cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letters A through Z. Now let’s look at what CreateDriveLink is doing:

#define DOS_MOUNT_PREFIX L"\\DosDevices\\"

void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo) {
   WCHAR tmp[3] =
   {0, ':', 0};
   int j = nDriveNo + (WCHAR) 'A';

   tmp[0] = (short) j;
   wcscpy (dosname, (LPWSTR) DOS_MOUNT_PREFIX);
   wcscat (dosname, tmp);
}

NTSTATUS CreateDriveLink (int nDosDriveNo) {
   WCHAR dev[128], link[128];
   UNICODE_STRING deviceName, symLink;
   NTSTATUS ntStatus;

   TCGetNTNameFromNumber (dev, nDosDriveNo);
   TCGetDosNameFromNumber (link, nDosDriveNo);

   RtlInitUnicodeString (&deviceName, dev);
   RtlInitUnicodeString (&symLink, link);
   // Delete \DosDevices\X:
   ntStatus = IoCreateSymbolicLink (&symLink, &deviceName);
   return ntStatus;
}

Ignore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 horrible looking string manipulation in TCGetDosNameFromNumber as it’s not relevant to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability. What cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code is doing is building a path for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter symbolic link to \DosDevices\X: where X is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter determined simply by adding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive number to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 character ‘A’.

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ory we could redefine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C: drive, perhaps that could be used to elevate privileges? Well sadly not, if you go back to my description of DosDevices on XP and later versions of Windows you’ll notice that when writing to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DosDevices directory (which is really a symbolic link to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual ?? directory) it will create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory  which doesn’t really gain you much. You’re only overriding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current user’s view of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive. This is useful to escape a sandbox (assuming you can access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Truecrypt device) but as a normal user you can already write to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user DosDevices directory. That seems like a dead end, perhaps it’s worth taking a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unmount process instead.

When unmounting a Truecrypt volume you only need to pass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive number. Unmounting an existing device will delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original symbolic link using RemoveDriveLink.

NTSTATUS RemoveDriveLink (int nDosDriveNo) {
   WCHAR link[256];
   UNICODE_STRING symLink;
   NTSTATUS ntStatus;

   TCGetDosNameFromNumber (link, nDosDriveNo);
   RtlInitUnicodeString (&symLink, link);
   // Delete \DosDevices\X:
   ntStatus = IoDeleteSymbolicLink (&symLink);
   return ntStatus;
}

// We always remove symbolic link as mount manager might fail to do so
RemoveDriveLink (extension->nDosDriveNo);

Does this help us in anyway? Let’s see what IoDeleteSymbolicLink is doing under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hood:

NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) {
 NTSTATUS status;
 OBJECT_ATTRIBUTES ObjectAttributes;
 HANDLE Handle;

 InitializeObjectAttributes(&ObjectAttributes, SymbolicLinkName, ...);
 
 status = ZwOpenSymbolicLinkObject(&Handle, DELETE, &ObjectAttributes);
 if (NT_SUCCESS(status)) {
   status = ZwMakeTemporaryObject(Handle);
   if (NT_SUCCESS(status))
     ZwClose(Handle);
 }
 return status;
}

We can see IoDeleteSymbolicLink is opening cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link object for DELETE access. It cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calls ZwMakeTemporaryObject to drop cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reference count of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object by 1 (which was added when creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first place). As no ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r handles are open to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object it gets deleted from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object namespace which removes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name. Crucially though this is a “Read” operation, even though we’re asking for DELETE permissions it's only opening an existing object, this means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual ?? directory will first try to open in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n fallback to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global directory. The result is if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter can’t be found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory it will actually open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global symbolic link, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n delete it.

So seems like we’re getting somewhere, we’ve got a primitive to delete an existing drive letter in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global directory. However we need to have already mounted a Truecrypt volume to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding drive letter in order to delete it. If we try and do this cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mount process fails, what’s stopping us defining a new C: drive? During cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mount process cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function IsDriveLetterAvailable is called, if it returns TRUE 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 letter is available for use. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function returns FALSE 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 command refuses to mount cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 volume as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specified drive letter.

BOOL IsDriveLetterAvailable (int nDosDriveNo) {
   OBJECT_ATTRIBUTES objectAttributes;
   UNICODE_STRING objectName;
   WCHAR link[128];
   HANDLE handle;

   TCGetDosNameFromNumber (link, nDosDriveNo);
   RtlInitUnicodeString (&objectName, link);
   InitializeObjectAttributes (&objectAttributes, &objectName,
         OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
   // Test opening \DosDevices\X:
   if (NT_SUCCESS (ZwOpenSymbolicLinkObject (&handle, GENERIC_READ,
                                             &objectAttributes))) {
       ZwClose (handle);
       return FALSE;
   }

   return TRUE;
}

All IsDriveLetterAvailable does is call ZwOpenSymbolicLinkObject to try and open any existing symbolic link with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter name. As we saw with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IoDeleteSymbolicLink case this is a read operation so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual directory fallback will occur. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global drive letter entry exists we can’t mount cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unmount to delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter. Seems like we’re at an impasse unless we can bypass this check.

Notice that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result of ZwOpenSymbolicLinkObject is just checked to return a successful status using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NT_SUCCESS macro. This causes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logic of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function to be incorrect. The intent of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function is to say “Does no symbolic link object with this name exist?” However because of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sinking of error cases what it actually results in is asking “Does opening a symbolic link object with this name fail?” Those are subtly different questions and obviously we can get it to return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 answer we like.

When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link doesn’t exist cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API returns STATUS_OBJECT_NAME_NOT_FOUND; that was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intent of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check. However, to bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check we can just find any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r way of getting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API to fail, IsDriveLetterAvailable will return TRUE, and we can mount an arbitrary drive letter even if it already exists. A common trick in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se cases is to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access control on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function would return STATUS_ACCESS_DENIED, however as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code is using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Zw variant of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call all access checks are bypassed. Instead all we need to do is create a different object type with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same name in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual DosDevices directory. As ZwOpenSymbolicLinkObject  will verify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object type this will result in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API returning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 error status STATUS_OBJECT_TYPE_MISMATCH instead. We do have a race condition here between when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive letter check occurs and when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link is created which we need to win by deleting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 invalid object, however that’s a pretty easy this to do through brute force or abusing file OPLOCKs.

So we can combine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se small bugs into remounting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C: drive to an arbitrary Truecrypt volume, well almost. We have just one problem left, how to actually get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mount process to write to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GLOBAL?? directory. Turns out this is probably cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 easiest part of all. IoCreateSymbolicLink doesn’t perform any security checks when creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link so we can get it to write to an object directory we wouldn’t normally be able to control. However when setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-process using NtSetInformationProcess we only need a handle with DIRECTORY_TRAVERSE permissions. As this is a read permission we can open GLOBAL?? from a low-privileged user, set it as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-process DosDevices directory cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Truecrypt driver to write to it.

So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final exploit chain is as follows:
  1. Create a new kernel object in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user DosDevices directory with 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 drive letter to override.
  2. Mount a Truecrypt volume as that drive number cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n win cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 race between IsDriveLetterAvailable and CreateDriveLink.
  3. Manually delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory (it’s our directory so we can do this) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n unmount cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive. This will cause IoDeleteSymbolicLink to delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global drive letter.
  4. Assign GLOBAL?? as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-process DosDevices directory, remount cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 volume as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 letter to override.
  5. Exploit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remapped drive letter to elevate privileges such as starting a scheduled task or service.

I’ve summarised cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operations in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 diagram below.



Performing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence of operations results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global C: drive mapped to our arbitrary Truecrypt volume, and from that you can trivially elevate privileges as any system service, or even cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will think

Conclusions

So why might this issue have been missed? Well obviously cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root cause was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lack of knowledge of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack vector but you could be forgiven for this because of typical idiomatic Windows driver code which isn’t usually exploitable. Take a look at pretty much any DriverEntry method for a Windows driver. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver starts it needs to create a new device object, typically with IoCreateDevice. Then cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code will also create a symbolic link in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DosDevices directory using IoCreateSymbolicLink to make it easier for user-mode applications to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device.

The Truecrypt implementation for this is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function TCCreateRootDeviceObject, which creates a symbolic link called \DosDevices\TrueCrypt. Why isn’t this vulnerable to a similar issue? Whenever a driver starts, even if it was loaded by a user, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial thread running DriverEntry runs within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 System process, which is a special process on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NT operating system where system kernel threads execute. By running in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system process context it’s not possible, at least without Administrator privileges, to influence cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DosDevices location eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-user directory or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-process directory.

This might lead a developer, and even an auditor to think that IoCreateSymbolicLink does something special to guard against this attack. As we’ve seen it doesn’t. The issue wouldn’t have been exploitable if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link creation occurred in a system thread but that’s up to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 developer. It also wouldn’t have been vulnerable prior to Windows 2000, but that’s hardly a consolation. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behaviour of something so fundamental to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NT operating system like how DOS style devices letters is handled isn’t well documented or things like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-process device map trips up Microsoft it’s hard to blame cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 developers and auditors when bugs sneak through.