A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #23465  by Cr4sh
 Tue Jul 29, 2014 11:19 pm
Code: Select all
typedef struct _PROCESSOR_THREAD_PARAM
{
    KAFFINITY Mask;
    PKSTART_ROUTINE Routine;
    PVOID Param;

} PROCESSOR_THREAD_PARAM,
*PPROCESSOR_THREAD_PARAM;

void ProcessorThread(PVOID Param)
{
    PPROCESSOR_THREAD_PARAM ThreadParam = (PPROCESSOR_THREAD_PARAM)Param;
    
    // bind thread to specific processor
    KeSetSystemAffinityThread(ThreadParam->Mask);
    
    // execute payload on this processor
    ThreadParam->Routine(ThreadParam->Param);
}

void ForEachProcessor(PKSTART_ROUTINE Routine, PVOID Param)
{
    if (KeGetCurrentIrql() > PASSIVE_LEVEL)
    {
        DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Invalid IRQL (Must be =PASSIVE_LEVEL)\n");
        return;
    }

    // get bitmask of active processors
    KAFFINITY ActiveProcessors = KeQueryActiveProcessors();    

    for (KAFFINITY i = 0; i < sizeof(KAFFINITY) * 8; i++)
    {
        KAFFINITY Mask = 1 << i;

        // check if this processor bit present in mask
        if (ActiveProcessors & Mask)
        {
            HANDLE hThread = NULL;
            PROCESSOR_THREAD_PARAM ThreadParam;
            
            ThreadParam.Mask    = Mask;
            ThreadParam.Param   = Param;
            ThreadParam.Routine = Routine;
            
            // create thread for this processor
            NTSTATUS ns = PsCreateSystemThread(
                &hThread, 
                THREAD_ALL_ACCESS, 
                NULL, NULL, NULL, 
                ProcessorThread, 
                &ThreadParam
            );
            if (NT_SUCCESS(ns))
            {
                PVOID Thread;                
                // get pointer to thread object
                ns = ObReferenceObjectByHandle(
                    hThread,
                    THREAD_ALL_ACCESS,
                    NULL,
                    KernelMode,
                    &Thread,
                    NULL
                );
                if (NT_SUCCESS(ns))
                {
                    // waiting for thread termination
                    KeWaitForSingleObject(Thread, Executive, KernelMode, FALSE, NULL);
                    ObDereferenceObject(Thread);
                }
                else
                {
                    DbgMsg(__FILE__, __LINE__, "ObReferenceObjectByHandle() fails; status: 0x%.8x\n", ns);
                }                

                ZwClose(hThread);
            }
            else
            {
                DbgMsg(__FILE__, __LINE__, "PsCreateSystemThread() fails; status: 0x%.8x\n", ns);
            }
        }
    }
}