PWSTR OfflinePath = L"\\Registry\\Machine\\System\\MountedDevices\\Offline";
UNICODE_STRING RemoteDatabase = RTL_CONSTANT_STRING(L"\\System Volume Information\\MountPointManagerRemoteDatabase");
-UNICODE_STRING RemoteDatabaseFile = RTL_CONSTANT_STRING(L"\\:$MountMgrRemoteDatabase");
/*
* @implemented
*/
VOID
NTAPI
-MigrateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject,
- IN PVOID Context)
+CreateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
{
- ULONG Length;
NTSTATUS Status;
- PVOID TmpBuffer;
- CHAR Disposition;
- LARGE_INTEGER ByteOffset;
+ HANDLE Database = 0;
+ UNICODE_STRING DatabaseName;
PMIGRATE_WORK_ITEM WorkItem;
IO_STATUS_BLOCK IoStatusBlock;
- HANDLE Migrate = 0, Database = 0;
+ OBJECT_ATTRIBUTES ObjectAttributes;
PDEVICE_INFORMATION DeviceInformation;
- BOOLEAN PreviousMode, Complete = FALSE;
- UNICODE_STRING DatabaseName, DatabaseFile;
- OBJECT_ATTRIBUTES ObjectAttributes, MigrateAttributes;
-#define TEMP_BUFFER_SIZE 0x200
UNREFERENCED_PARAMETER(DeviceObject);
/* Reconstruct appropriate string */
DatabaseName.Length = DeviceInformation->DeviceName.Length + RemoteDatabase.Length;
DatabaseName.MaximumLength = DatabaseName.Length + sizeof(WCHAR);
-
- DatabaseFile.Length = DeviceInformation->DeviceName.Length + RemoteDatabaseFile.Length;
- DatabaseFile.MaximumLength = DatabaseFile.Length + sizeof(WCHAR);
-
DatabaseName.Buffer = AllocatePool(DatabaseName.MaximumLength);
- DatabaseFile.Buffer = AllocatePool(DatabaseFile.MaximumLength);
- /* Allocate buffer that will be used to swap contents */
- TmpBuffer = AllocatePool(TEMP_BUFFER_SIZE);
- if (!DatabaseName.Buffer || !DatabaseFile.Buffer || !TmpBuffer)
+ if (DatabaseName.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
/* Finish initating strings */
RtlCopyMemory(DatabaseName.Buffer, DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
- RtlCopyMemory(DatabaseFile.Buffer, DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
RtlCopyMemory(DatabaseName.Buffer + (DeviceInformation->DeviceName.Length / sizeof(WCHAR)),
RemoteDatabase.Buffer, RemoteDatabase.Length);
- RtlCopyMemory(DatabaseFile.Buffer + (DeviceInformation->DeviceName.Length / sizeof(WCHAR)),
- RemoteDatabaseFile.Buffer, RemoteDatabaseFile.Length);
DatabaseName.Buffer[DatabaseName.Length / sizeof(WCHAR)] = UNICODE_NULL;
- DatabaseFile.Buffer[DatabaseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
/* Create database */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
NULL);
- Status = ZwCreateFile(&Database,
+ Status = IoCreateFile(&Database,
SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES |
FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES |
FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT,
NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- Database = 0;
- goto Cleanup;
- }
-
- InitializeObjectAttributes(&MigrateAttributes,
- &DatabaseFile,
- OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
- NULL,
- NULL);
-
- /* Disable hard errors and open the database that will be copied */
- PreviousMode = IoSetThreadHardErrorMode(FALSE);
- Status = ZwCreateFile(&Migrate,
- SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES |
- FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES |
- FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA,
- &MigrateAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
0,
- FILE_OPEN,
- FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT,
+ CreateFileTypeNone,
NULL,
- 0);
- IoSetThreadHardErrorMode(PreviousMode);
+ IO_STOP_ON_SYMLINK);
if (!NT_SUCCESS(Status))
{
- Migrate = 0;
- }
- if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- Status = STATUS_SUCCESS;
- Complete = TRUE;
- }
- if (!NT_SUCCESS(Status) || Complete)
- {
- goto Cleanup;
- }
-
- ByteOffset.QuadPart = 0LL;
- PreviousMode = IoSetThreadHardErrorMode(FALSE);
- /* Now, loop as long it's possible */
- while (Status == STATUS_SUCCESS)
- {
- /* Read data from existing database */
- Status = ZwReadFile(Migrate,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- TmpBuffer,
- TEMP_BUFFER_SIZE,
- &ByteOffset,
- NULL);
- if (!NT_SUCCESS(Status))
+ if (Status == STATUS_STOPPED_ON_SYMLINK)
{
- break;
+ DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
}
- /* And write them into new database */
- Length = (ULONG)IoStatusBlock.Information;
- Status = ZwWriteFile(Database,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- TmpBuffer,
- Length,
- &ByteOffset,
- NULL);
- ByteOffset.QuadPart += Length;
- }
- IoSetThreadHardErrorMode(PreviousMode);
-
- /* Delete old databse if it was well copied */
- if (Status == STATUS_END_OF_FILE)
- {
- Disposition = 1;
- Status = ZwSetInformationFile(Migrate,
- &IoStatusBlock,
- &Disposition,
- sizeof(Disposition),
- FileDispositionInformation);
+ Database = 0;
+ goto Cleanup;
}
- /* Migration is over */
-
Cleanup:
- if (TmpBuffer)
- {
- FreePool(TmpBuffer);
- }
-
- if (DatabaseFile.Buffer)
- {
- FreePool(DatabaseFile.Buffer);
- }
-
if (DatabaseName.Buffer)
{
FreePool(DatabaseName.Buffer);
}
- if (Migrate)
- {
- ZwClose(Migrate);
- }
-
if (NT_SUCCESS(Status))
{
DeviceInformation->Migrated = 1;
}
- else if (Database)
+ else if (Database != 0)
{
ZwClose(Database);
}
WorkItem->Database = Database;
KeSetEvent(WorkItem->Event, 0, FALSE);
-#undef TEMP_BUFFER_SIZE
}
/*
* @implemented
*/
NTSTATUS
-MigrateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation,
- IN OUT PHANDLE Database)
+CreateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation,
+ IN OUT PHANDLE Database)
{
KEVENT Event;
NTSTATUS Status;
/* And queue it */
IoQueueWorkItem(WorkItem->WorkItem,
- MigrateRemoteDatabaseWorker,
+ CreateRemoteDatabaseWorker,
DelayedWorkQueue,
WorkItem);
/* Disable hard errors */
PreviousMode = IoSetThreadHardErrorMode(FALSE);
- Status = ZwCreateFile(&Database,
+ Status = IoCreateFile(&Database,
SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES |
FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES |
FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA,
(!MigrateDatabase || DeviceInformation->Migrated == 0) ? FILE_OPEN_IF : FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT,
NULL,
- 0);
+ 0,
+ CreateFileTypeNone,
+ NULL,
+ IO_STOP_ON_SYMLINK);
+ if (Status == STATUS_STOPPED_ON_SYMLINK)
+ {
+ DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
+ }
/* If base it to be migrated and was opened successfully, go ahead */
if (MigrateDatabase && NT_SUCCESS(Status))
{
- MigrateRemoteDatabase(DeviceInformation, &Database);
+ CreateRemoteDatabase(DeviceInformation, &Database);
}
IoSetThreadHardErrorMode(PreviousMode);