Ejemplo n.º 1
0
PVOID UserCreateHeap(
    HANDLE hSection,
    PVOID pvBaseAddress,
    DWORD dwSize)
{
    PVOID pUserBase;
    ULONG ulViewSize;
    LARGE_INTEGER liOffset;
    PEPROCESS Process = PsGetCurrentProcess();
    RTL_HEAP_PARAMETERS HeapParams;
    NTSTATUS Status;

    /*
     * Map the section into the current process and commit the
     * first page of the section.
     */
    ulViewSize = 0;
    liOffset.QuadPart = 0;
    pUserBase = NULL;
    Status = MmMapViewOfSection(hSection, Process,
                                &pUserBase, 0, PAGE_SIZE, &liOffset, &ulViewSize, ViewUnmap,
                                SEC_NO_CHANGE, PAGE_EXECUTE_READ);
    if (!NT_SUCCESS(Status))
        return NULL;
    MmUnmapViewOfSection(Process, pUserBase);

    /*
     * We now have a committed page to create the heap in.
     */
    RtlZeroMemory(&HeapParams, sizeof(HeapParams));
    HeapParams.Length = sizeof(HeapParams);
    HeapParams.InitialCommit = PAGE_SIZE;
    HeapParams.InitialReserve = dwSize;
    HeapParams.CommitRoutine = UserCommitMemory;

    return RtlCreateHeap(
               HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY,
               pvBaseAddress,
               dwSize,
               PAGE_SIZE,
               NULL,
               &HeapParams
           );
}
Ejemplo n.º 2
0
VOID
NTAPI
EngUnmapSectionView(
    _In_ PVOID pvBits,
    _In_ ULONG cjOffset,
    _In_ HANDLE hSecure)
{
    NTSTATUS Status;

    /* Unsecure the memory */
    EngUnsecureMem(hSecure);

    /* Calculate the real start of the section view */
    pvBits = (PUCHAR)pvBits - (cjOffset & (MM_ALLOCATION_GRANULARITY - 1));

    /* Unmap the section view */
    Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits);
    ASSERT(NT_SUCCESS(Status));
}
Ejemplo n.º 3
0
VOID
LpcpDeletePort (
    IN PVOID Object
    )

/*++

Routine Description:

    This routine is the callback used for deleting a port object.

Arguments:

    Object - Supplies a pointer to the port object being deleted

Return Value:

    None.

--*/

{
    PETHREAD CurrentThread;
    PLPCP_PORT_OBJECT Port = Object;
    PLPCP_PORT_OBJECT ConnectionPort;
    LPC_CLIENT_DIED_MSG ClientPortClosedDatagram;
    PLPCP_MESSAGE Msg;
    PLIST_ENTRY Head, Next;
    HANDLE CurrentProcessId;
    NTSTATUS Status;
    LARGE_INTEGER RetryInterval = {(ULONG)(-10 * 1000 * 100), -1}; // 100 milliseconds

    PAGED_CODE();

    CurrentThread = PsGetCurrentThread ();

    //
    //  If the port is a server communication port then make sure that if
    //  there is a dangling client thread that we get rid of it.  This
    //  handles the case of someone calling NtAcceptConnectPort and not
    //  calling NtCompleteConnectPort
    //

    if ((Port->Flags & PORT_TYPE) == SERVER_COMMUNICATION_PORT) {

        PETHREAD ClientThread;

        LpcpAcquireLpcpLockByThread(CurrentThread);

        if ((ClientThread = Port->ClientThread) != NULL) {

            Port->ClientThread = NULL;

            LpcpReleaseLpcpLock();

            ObDereferenceObject( ClientThread );

        } else {

            LpcpReleaseLpcpLock();
        }
    }

    //
    //  Send an LPC_PORT_CLOSED datagram to whoever is connected
    //  to this port so they know they are no longer connected.
    //

    if ((Port->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {

        ClientPortClosedDatagram.PortMsg.u1.s1.TotalLength = sizeof( ClientPortClosedDatagram );
        ClientPortClosedDatagram.PortMsg.u1.s1.DataLength = sizeof( ClientPortClosedDatagram.CreateTime );

        ClientPortClosedDatagram.PortMsg.u2.s2.Type = LPC_PORT_CLOSED;
        ClientPortClosedDatagram.PortMsg.u2.s2.DataInfoOffset = 0;

        ClientPortClosedDatagram.CreateTime = PsGetCurrentProcess()->CreateTime;

        Status = LpcRequestPort( Port, (PPORT_MESSAGE)&ClientPortClosedDatagram );

        while (Status == STATUS_NO_MEMORY) {

            KeDelayExecutionThread(KernelMode, FALSE, &RetryInterval);

            Status = LpcRequestPort( Port, (PPORT_MESSAGE)&ClientPortClosedDatagram );
        }
    }

    //
    //  If connected, disconnect the port, and then scan the message queue
    //  for this port and dereference any messages in the queue.
    //

    LpcpDestroyPortQueue( Port, TRUE );

    //
    //  If we had mapped sections into the server or client communication ports,
    //  we need to unmap them in the context of that process.
    //

    if ( (Port->ClientSectionBase != NULL) ||
         (Port->ServerSectionBase != NULL) ) {

        //
        //  If the client has a port memory view, then unmap it
        //

        if (Port->ClientSectionBase != NULL) {

            MmUnmapViewOfSection( Port->MappingProcess,
                                  Port->ClientSectionBase );

        }

        //
        //  If the server has a port memory view, then unmap it
        //

        if (Port->ServerSectionBase != NULL) {

            MmUnmapViewOfSection( Port->MappingProcess,
                                  Port->ServerSectionBase  );

        }

        //
        //  Removing the reference added while mapping the section
        //

        ObDereferenceObject( Port->MappingProcess );

        Port->MappingProcess = NULL;
    }

    //
    //  Dereference the pointer to the connection port if it is not
    //  this port.
    //

    LpcpAcquireLpcpLockByThread(CurrentThread);

    ConnectionPort = Port->ConnectionPort;

    if (ConnectionPort) {

        CurrentProcessId = CurrentThread->Cid.UniqueProcess;

        Head = &ConnectionPort->LpcDataInfoChainHead;
        Next = Head->Flink;

        while (Next != Head) {

            Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry );
            Next = Next->Flink;
            
            if (Port == ConnectionPort) {

                //
                //  If the Connection port is going away free all queued messages
                //

                RemoveEntryList( &Msg->Entry );
                InitializeListHead( &Msg->Entry );

                LpcpFreeToPortZone( Msg, LPCP_MUTEX_OWNED );

                //
                //  In LpcpFreeToPortZone the LPC lock is released and reacquired.
                //  Another thread might free the LPC message captured above
                //  in Next. We need to restart the search at the list head.
                //

                Next = Head->Flink;

            } else if ((Msg->Request.ClientId.UniqueProcess == CurrentProcessId)
                    &&
                ((Msg->SenderPort == Port) 
                        || 
                 (Msg->SenderPort == Port->ConnectedPort) 
                        || 
                 (Msg->SenderPort == ConnectionPort))) {

                //
                //  Test whether the message come from the same port and process
                //

                LpcpTrace(( "%s Freeing DataInfo Message %lx (%u.%u)  Port: %lx\n",
                            PsGetCurrentProcess()->ImageFileName,
                            Msg,
                            Msg->Request.MessageId,
                            Msg->Request.CallbackId,
                            ConnectionPort ));

                RemoveEntryList( &Msg->Entry );
                InitializeListHead( &Msg->Entry );

                LpcpFreeToPortZone( Msg, LPCP_MUTEX_OWNED );

                //
                //  In LpcpFreeToPortZone the LPC lock is released and reacquired.
                //  Another thread might free the LPC message captured above
                //  in Next. We need to restart the search at the list head.
                //

                Next = Head->Flink;
            }
        }

        LpcpReleaseLpcpLock();

        if (ConnectionPort != Port) {

            ObDereferenceObject( ConnectionPort );
        }

    } else {

        LpcpReleaseLpcpLock();
    }

    if (((Port->Flags & PORT_TYPE) == SERVER_CONNECTION_PORT) &&
        (ConnectionPort->ServerProcess != NULL)) {

        ObDereferenceObject( ConnectionPort->ServerProcess );

        ConnectionPort->ServerProcess = NULL;
    }

    //
    //  Free any static client security context
    //

    LpcpFreePortClientSecurity( Port );

    //
    //  And return to our caller
    //

    return;
}
Ejemplo n.º 4
0
VOID
NTAPI
LpcpDeletePort(IN PVOID ObjectBody)
{
    LARGE_INTEGER Timeout;
    PETHREAD Thread;
    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody;
    PLPCP_PORT_OBJECT ConnectionPort;
    PLPCP_MESSAGE Message;
    PLIST_ENTRY ListHead, NextEntry;
    HANDLE Pid;
    CLIENT_DIED_MSG ClientDiedMsg;

    PAGED_CODE();
    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);

    Timeout.QuadPart = -1000000;

    /* Check if this is a communication port */
    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT)
    {
        /* Acquire the lock */
        KeAcquireGuardedMutex(&LpcpLock);

        /* Get the thread */
        Thread = Port->ClientThread;
        if (Thread)
        {
            /* Clear it */
            Port->ClientThread = NULL;

            /* Release the lock and dereference */
            KeReleaseGuardedMutex(&LpcpLock);
            ObDereferenceObject(Thread);
        }
        else
        {
            /* Release the lock */
            KeReleaseGuardedMutex(&LpcpLock);
        }
    }

    /* Check if this is a client-side port */
    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
    {
        /* Setup the client died message */
        ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg);
        ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime);
        ClientDiedMsg.h.u2.ZeroInit = 0;
        ClientDiedMsg.h.u2.s2.Type = LPC_PORT_CLOSED;
        ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime;

        /* Send it */
        for (;;)
        {
            /* Send the message */
            if (LpcRequestPort(Port, &ClientDiedMsg.h) != STATUS_NO_MEMORY)
                break;

            /* Wait until trying again */
            KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
        }
    }

    /* Destroy the port queue */
    LpcpDestroyPortQueue(Port, TRUE);

    /* Check if we had views */
    if ((Port->ClientSectionBase) || (Port->ServerSectionBase))
    {
        /* Check if we had a client view */
        if (Port->ClientSectionBase)
        {
            /* Unmap it */
            MmUnmapViewOfSection(Port->MappingProcess,
                                 Port->ClientSectionBase);
        }

        /* Check for a server view */
        if (Port->ServerSectionBase)
        {
            /* Unmap it */
            MmUnmapViewOfSection(Port->MappingProcess,
                                 Port->ServerSectionBase);
        }

        /* Dereference the mapping process */
        ObDereferenceObject(Port->MappingProcess);
        Port->MappingProcess = NULL;
    }

    /* Acquire the lock */
    KeAcquireGuardedMutex(&LpcpLock);

    /* Get the connection port */
    ConnectionPort = Port->ConnectionPort;
    if (ConnectionPort)
    {
        /* Get the PID */
        Pid = PsGetCurrentProcessId();

        /* Loop the data lists */
        ListHead = &ConnectionPort->LpcDataInfoChainHead;
        NextEntry = ListHead->Flink;
        while (NextEntry != ListHead)
        {
            /* Get the message */
            Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
            NextEntry = NextEntry->Flink;

            /* Check if this is the connection port */
            if (Port == ConnectionPort)
            {
                /* Free queued messages */
                RemoveEntryList(&Message->Entry);
                InitializeListHead(&Message->Entry);
                LpcpFreeToPortZone(Message, LPCP_LOCK_HELD);

                /* Restart at the head */
                NextEntry = ListHead->Flink;
            }
            else if ((Message->Request.ClientId.UniqueProcess == Pid) &&
                     ((Message->SenderPort == Port) ||
                      (Message->SenderPort == Port->ConnectedPort) ||
                      (Message->SenderPort == ConnectionPort)))
            {
                /* Remove it */
                RemoveEntryList(&Message->Entry);
                InitializeListHead(&Message->Entry);
                LpcpFreeToPortZone(Message, LPCP_LOCK_HELD);

                /* Restart at the head */
                NextEntry = ListHead->Flink;
            }
        }

        /* Release the lock */
        KeReleaseGuardedMutex(&LpcpLock);

        /* Dereference the object unless it's the same port */
        if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort);

        /* Check if this is a connection port with a server process */
        if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) &&
            (ConnectionPort->ServerProcess))
        {
            /* Dereference the server process */
            ObDereferenceObject(ConnectionPort->ServerProcess);
            ConnectionPort->ServerProcess = NULL;
        }
    }
    else
    {
        /* Release the lock */
        KeReleaseGuardedMutex(&LpcpLock);
    }

    /* Free client security */
    LpcpFreePortClientSecurity(Port);
    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port);
}
Ejemplo n.º 5
0
NTSTATUS
MuInitializeUserModeHelper (
    PMU_GLOBAL_DATA GlobalData
)
{
    NTSTATUS status;
    HANDLE file, proc, dllsec;
    SIZE_T imgsize = 0;
    PVOID secobj, dllbase = NULL;
    LARGE_INTEGER secofs;
    UNICODE_STRING fp;
    IO_STATUS_BLOCK iosb;
    OBJECT_ATTRIBUTES oa;
    WCHAR path[MAX_PATH];
    
    wcscpy(path, MU_ROOTDIR_SYSTEM32);
    wcscat(path, MU_FILENAME_HELPER_DLL);
    
    RtlInitUnicodeString(&fp, path);
    
    InitializeObjectAttributes(&oa,
                               &fp,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               NULL,
                               NULL);
    
    status = ZwOpenFile(&file,
                        GENERIC_READ,
                        &oa,
                        &iosb,
                        FILE_SHARE_READ,
                        FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    
    if (NT_SUCCESS(status))
    {
        status = ZwCreateSection(&dllsec,
                                 SECTION_ALL_ACCESS,
                                 NULL,
                                 NULL,
                                 PAGE_EXECUTE_READWRITE,
                                 SEC_IMAGE,
                                 file);
        
        ZwClose(file);
        
        if (!NT_SUCCESS(status))
            return status;
            
        status = ObReferenceObjectByHandle(dllsec,
                                           SECTION_ALL_ACCESS,
                                           *MmSectionObjectType,
                                           KernelMode,
                                           &secobj,
                                           NULL);
        
        ZwClose(dllsec);
        
        if (NT_SUCCESS(status))
        {
            secofs.QuadPart = 0;
            
            status = MmMapViewOfSection(secobj,
                                        PsGetCurrentProcess(),
                                        &dllbase,
                                        0,
                                        0,
                                        &secofs,
                                        &imgsize,
                                        ViewShare,
                                        0,
                                        PAGE_EXECUTE_READWRITE);
            
            if (NT_SUCCESS(status))
            {
                status = MuLinkDll(GlobalData, dllbase);
                
                MmUnmapViewOfSection(PsGetCurrentProcess(), dllbase);
            }
            
            if (!NT_SUCCESS(status))
            {
                ObDereferenceObject(secobj);
                
                secobj = NULL;
            }
            
            GlobalData->DllSection   = secobj;
            GlobalData->DllImageSize = imgsize;
            GlobalData->DllImageBase = dllbase;
        }
    }
    
    return status;
}
Ejemplo n.º 6
0
BOOL
APIENTRY
EngMapSection(
    IN PVOID pvSection,
    IN BOOL bMap,
    IN HANDLE hProcess,
    OUT PVOID* pvBaseAddress)
{
    NTSTATUS Status;
    PENGSECTION pSection = pvSection;
    PEPROCESS pepProcess;

    /* Get a pointer to the process */
    Status = ObReferenceObjectByHandle(hProcess,
                                       PROCESS_VM_OPERATION,
                                       NULL,
                                       KernelMode,
                                       (PVOID*)&pepProcess,
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("Could not access process %p, Status=0x%lx\n", hProcess, Status);
        return FALSE;
    }

    if (bMap)
    {
        /* Make sure the section isn't already mapped */
        ASSERT(pSection->pvMappedBase == NULL);

        /* Map the section into the process address space */
        Status = MmMapViewOfSection(pSection->pvSectionObject,
                                    pepProcess,
                                    &pSection->pvMappedBase,
                                    0,
                                    pSection->cjViewSize,
                                    NULL,
                                    &pSection->cjViewSize,
                                    0,
                                    0,
                                    PAGE_READWRITE);
        if (!NT_SUCCESS(Status))
        {
            DPRINT1("Failed to map a section Status=0x%x\n", Status);
        }
    }
    else
    {
        /* Make sure the section is mapped */
        ASSERT(pSection->pvMappedBase);

        /* Unmap the section from the process address space */
        Status = MmUnmapViewOfSection(pepProcess, pSection->pvMappedBase);
        if (NT_SUCCESS(Status))
        {
            pSection->pvMappedBase = NULL;
        }
        else
        {
            DPRINT1("Failed to unmap a section @ %p Status=0x%x\n",
                    pSection->pvMappedBase, Status);
        }
    }

    /* Dereference the process */
    ObDereferenceObject(pepProcess);

    /* Set the new mapping base and return bool status */
    *pvBaseAddress = pSection->pvMappedBase;
    return NT_SUCCESS(Status);
}
Ejemplo n.º 7
0
VOID
LpcpDeletePort (
    IN PVOID Object
    )

/*++

Routine Description:

    This routine is the callback used for deleting a port object.

Arguments:

    Object - Supplies a pointer to the port object being deleted

Return Value:

    None.

--*/

{
    PLPCP_PORT_OBJECT Port = Object;
    PLPCP_PORT_OBJECT ConnectionPort;
    LPC_CLIENT_DIED_MSG ClientPortClosedDatagram;
    PLPCP_MESSAGE Msg;
    PLIST_ENTRY Head, Next;
    HANDLE CurrentProcessId;

    PAGED_CODE();

    //
    //  If the port is a server communication port then make sure that if
    //  there is a dangling client thread that we get rid of it.  This
    //  handles the case of someone calling NtAcceptConnectPort and not
    //  calling NtCompleteConnectPort
    //

    LpcpPortExtraDataDestroy( Port );

    if ((Port->Flags & PORT_TYPE) == SERVER_COMMUNICATION_PORT) {

        PETHREAD ClientThread;

        LpcpAcquireLpcpLock();

        if ((ClientThread = Port->ClientThread) != NULL) {

            Port->ClientThread = NULL;

            LpcpReleaseLpcpLock();

            ObDereferenceObject( ClientThread );

        } else {

            LpcpReleaseLpcpLock();
        }
    }

    //
    //  Send an LPC_PORT_CLOSED datagram to whoever is connected
    //  to this port so they know they are no longer connected.
    //

    if ((Port->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {

        ClientPortClosedDatagram.PortMsg.u1.s1.TotalLength = sizeof( ClientPortClosedDatagram );
        ClientPortClosedDatagram.PortMsg.u1.s1.DataLength = sizeof( ClientPortClosedDatagram.CreateTime );

        ClientPortClosedDatagram.PortMsg.u2.s2.Type = LPC_PORT_CLOSED;
        ClientPortClosedDatagram.PortMsg.u2.s2.DataInfoOffset = 0;

        ClientPortClosedDatagram.CreateTime = PsGetCurrentProcess()->CreateTime;

        LpcRequestPort( Port, (PPORT_MESSAGE)&ClientPortClosedDatagram );
    }

    //
    //  If connected, disconnect the port, and then scan the message queue
    //  for this port and dereference any messages in the queue.
    //

    LpcpDestroyPortQueue( Port, TRUE );

    //
    //  If the client has a port memory view, then unmap it
    //

    if (Port->ClientSectionBase != NULL) {

        MmUnmapViewOfSection( PsGetCurrentProcess(),
                              Port->ClientSectionBase );

    }

    //
    //  If the server has a port memory view, then unmap it
    //

    if (Port->ServerSectionBase != NULL) {

        MmUnmapViewOfSection( PsGetCurrentProcess(),
                              Port->ServerSectionBase  );

    }

    //
    //  Dereference the pointer to the connection port if it is not
    //  this port.
    //

    if (ConnectionPort = Port->ConnectionPort) {

        CurrentProcessId = PsGetCurrentThread()->Cid.UniqueProcess;

        LpcpAcquireLpcpLock();

        Head = &ConnectionPort->LpcDataInfoChainHead;
        Next = Head->Flink;

        while (Next != Head) {

            Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry );
            Next = Next->Flink;

            if (Msg->Request.ClientId.UniqueProcess == CurrentProcessId) {

                LpcpTrace(( "%s Freeing DataInfo Message %lx (%u.%u)  Port: %lx\n",
                            PsGetCurrentProcess()->ImageFileName,
                            Msg,
                            Msg->Request.MessageId,
                            Msg->Request.CallbackId,
                            ConnectionPort ));

                RemoveEntryList( &Msg->Entry );

                LpcpFreeToPortZone( Msg, TRUE );
            }
        }

        LpcpReleaseLpcpLock();

        if (ConnectionPort != Port) {

            ObDereferenceObject( ConnectionPort );
        }
    }

    if (((Port->Flags & PORT_TYPE) == SERVER_CONNECTION_PORT) &&
        (ConnectionPort->ServerProcess != NULL)) {

        ObDereferenceObject( ConnectionPort->ServerProcess );

        ConnectionPort->ServerProcess = NULL;
    }

    //
    //  Free any static client security context
    //

    LpcpFreePortClientSecurity( Port );

    //
    //  And return to our caller
    //

    return;
}