Exemplo n.º 1
0
NTSTATUS NTAPI VirusTotalProcessApiThread(
    _In_ PVOID Parameter
    )
{
    LONG priority;
    IO_PRIORITY_HINT ioPriority;

    // TODO: Workqueue support.
    priority = THREAD_PRIORITY_LOWEST;
    ioPriority = IoPriorityVeryLow;

    NtSetInformationThread(NtCurrentThread(), ThreadBasePriority, &priority, sizeof(LONG));
    NtSetInformationThread(NtCurrentThread(), ThreadIoPriority, &ioPriority, sizeof(IO_PRIORITY_HINT));

    Sleep(10 * 1000);

    do
    {
        ULONG i;
        INT64 resultLength;
        PPH_BYTES jsonApiResult = NULL;
        PVOID jsonArray;
        PVOID rootJsonObject = NULL;
        PVOID dataJsonObject;
        PPH_STRING jsonArrayToSendString = NULL;
        PPH_LIST resultTempList = NULL;
        PPH_LIST virusTotalResults = NULL;

        jsonArray = PhCreateJsonArray();
        resultTempList = PhCreateList(30);

        PhAcquireQueuedLockExclusive(&ProcessListLock);

        for (i = 0; i < VirusTotalList->Count; i++)
        {
            PVIRUSTOTAL_FILE_HASH_ENTRY extension = VirusTotalList->Items[i];

            if (resultTempList->Count >= 30)
                break;

            if (!extension->Stage1)
            {
                extension->Stage1 = TRUE;

                PhAddItemList(resultTempList, extension);
            }
        }

        PhReleaseQueuedLockExclusive(&ProcessListLock);

        if (resultTempList->Count == 0)
        {
            Sleep(30 * 1000); // Wait 30 seconds
            goto CleanupExit;
        }

        for (i = 0; i < resultTempList->Count; i++)
        {
            VirusTotalBuildJsonArray(resultTempList->Items[i], jsonArray);
        }

        if (!(jsonArrayToSendString = PhGetJsonArrayString(jsonArray)))
            goto CleanupExit;

        if (!(jsonApiResult = VirusTotalSendHttpRequest(PhConvertUtf16ToUtf8(jsonArrayToSendString->Buffer))))
            goto CleanupExit;

        if (!(rootJsonObject = PhCreateJsonParser(jsonApiResult->Buffer)))
            goto CleanupExit;

        if (!(dataJsonObject = PhGetJsonObject(rootJsonObject, "data")))
            goto CleanupExit;

        if (!(resultLength = PhGetJsonValueAsLong64(rootJsonObject, "result")))
            goto CleanupExit;

        if (virusTotalResults = VirusTotalJsonToResultList(dataJsonObject))
        {
            for (i = 0; i < virusTotalResults->Count; i++)
            {
                PVIRUSTOTAL_API_RESULT result = virusTotalResults->Items[i];

                if (result->Found)
                {
                    PVIRUSTOTAL_FILE_HASH_ENTRY entry = VirusTotalGetCachedResultFromHash(result->FileHash);

                    if (entry && !entry->Processed)
                    {
                        entry->Processed = TRUE;
                        entry->Found = result->Found;
                        entry->Positives = result->Positives;
                        entry->Total = result->Total;
 
                        if (!FindProcessDbObject(&entry->FileName->sr))
                        {
                            CreateProcessDbObject(
                                entry->FileName,
                                entry->Positives,
                                entry->Total,
                                result->FileHash
                                );
                        }
                    }
                }
            }
        }

CleanupExit:

        if (virusTotalResults)
        {
            for (i = 0; i < virusTotalResults->Count; i++)
            {
                PVIRUSTOTAL_API_RESULT result = virusTotalResults->Items[i];
            
            //    PhClearReference(&result->Permalink);
            //    PhClearReference(&result->FileHash);
            //    PhClearReference(&result->DetectionRatio);

                PhFree(result);
            }
            
            PhDereferenceObject(virusTotalResults);
        }
        
        if (rootJsonObject)
        {
            PhFreeJsonParser(rootJsonObject);
        }

        if (jsonArrayToSendString)
            PhDereferenceObject(jsonArrayToSendString);

        if (jsonArray)
        {
            PhFreeJsonParser(jsonArray);
        }

        if (jsonApiResult)
        {
            PhDereferenceObject(jsonApiResult);
        }

        if (resultTempList)
        {
            // Re-queue items without any results from VirusTotal.
            //for (i = 0; i < resultTempList->Count; i++)
            //{
            //    PVIRUSTOTAL_FILE_HASH_ENTRY result = resultTempList->Items[i];
            //    PPROCESS_EXTENSION extension = result->Extension;
            //
            //    if (extension->Retries > 3)
            //        continue;
            //
            //    if (PhIsNullOrEmptyString(result->FileResult))
            //    {
            //        extension->Stage1 = FALSE;
            //    }
            //
            //    extension->Retries++;
            //}

            PhDereferenceObject(resultTempList);
        }

        Sleep(5 * 1000); // Wait 5 seconds

    } while (VirusTotalHandle);

    return STATUS_SUCCESS;
}
Exemplo n.º 2
0
VOID ProcessesUpdatedCallback(
    _In_opt_ PVOID Parameter,
    _In_opt_ PVOID Context
    )
{
    static ULONG ProcessesUpdatedCount = 0;
    PLIST_ENTRY listEntry;

    if (!VirusTotalScanningEnabled)
        return;

    if (ProcessesUpdatedCount < 2)
    {
        ProcessesUpdatedCount++;
        return;
    }

    listEntry = ProcessListHead.Flink;

    while (listEntry != &ProcessListHead)
    {
        PPROCESS_EXTENSION extension;
        PPH_STRING filePath = NULL;

        extension = CONTAINING_RECORD(listEntry, PROCESS_EXTENSION, ListEntry);

        if (extension->ProcessItem)
        {
            filePath = extension->ProcessItem->FileName;
        }
        else if (extension->ModuleItem)
        {
            filePath = extension->ModuleItem->FileName;
        }
        else if (extension->ServiceItem)
        {
            if (extension->FilePath)
            {
                filePath = extension->FilePath;
            }
            else
            {
                PPH_STRING serviceFileName = NULL;
                PPH_STRING serviceBinaryPath = NULL;

                if (NT_SUCCESS(QueryServiceFileName(
                    &extension->ServiceItem->Name->sr,
                    &serviceFileName,
                    &serviceBinaryPath
                    )))
                {
                    PhMoveReference(&extension->FilePath, serviceFileName);
                    if (serviceBinaryPath) PhDereferenceObject(serviceBinaryPath);
                }

                filePath = extension->FilePath;
            }
        }

        if (!PhIsNullOrEmptyString(filePath))
        {
            if (!extension->ResultValid)
            {
                PPROCESS_DB_OBJECT object;

                if (object = FindProcessDbObject(&filePath->sr))
                {
                    extension->Stage1 = TRUE;
                    extension->ResultValid = TRUE;

                    extension->Positives = object->Positives;
                    PhSwapReference(&extension->VirusTotalResult, object->Result);
                }
            }

            if (!extension->Stage1)
            {
                if (!VirusTotalGetCachedResult(filePath))
                {
                    VirusTotalAddCacheResult(filePath, extension);
                }

                extension->Stage1 = TRUE;
            }
        }

        listEntry = listEntry->Flink;
    }
}