コード例 #1
0
PPH_UPDATER_CONTEXT CreateUpdateContext(
    _In_ BOOLEAN StartupCheck
    )
{
    PPH_UPDATER_CONTEXT context;

    context = (PPH_UPDATER_CONTEXT)PhCreateAlloc(sizeof(PH_UPDATER_CONTEXT));
    memset(context, 0, sizeof(PH_UPDATER_CONTEXT));

    context->CurrentVersionString = PhGetPhVersion();
    context->StartupCheck = StartupCheck;

    return context;
}
コード例 #2
0
ファイル: appsup.c プロジェクト: john-peterson/processhacker
VOID PhWritePhTextHeader(
    __inout PPH_FILE_STREAM FileStream
    )
{
    PPH_STRING version;
    LARGE_INTEGER time;
    SYSTEMTIME systemTime;
    PPH_STRING dateString;
    PPH_STRING timeString;

    PhWriteStringAsAnsiFileStream2(FileStream, L"Process Hacker ");

    if (version = PhGetPhVersion())
    {
        PhWriteStringAsAnsiFileStream(FileStream, &version->sr);
        PhDereferenceObject(version);
    }

    PhWriteStringFormatFileStream(FileStream, L"\r\nWindows NT %u.%u", PhOsVersion.dwMajorVersion, PhOsVersion.dwMinorVersion);

    if (PhOsVersion.szCSDVersion[0] != 0)
        PhWriteStringFormatFileStream(FileStream, L" %s", PhOsVersion.szCSDVersion);

#ifdef _M_IX86
    PhWriteStringAsAnsiFileStream2(FileStream, L" (32-bit)");
#else
    PhWriteStringAsAnsiFileStream2(FileStream, L" (64-bit)");
#endif

    PhQuerySystemTime(&time);
    PhLargeIntegerToLocalSystemTime(&systemTime, &time);

    dateString = PhFormatDate(&systemTime, NULL);
    timeString = PhFormatTime(&systemTime, NULL);
    PhWriteStringFormatFileStream(FileStream, L"\r\n%s %s\r\n\r\n", dateString->Buffer, timeString->Buffer);
    PhDereferenceObject(dateString);
    PhDereferenceObject(timeString);
}
コード例 #3
0
PVIRUSTOTAL_API_RESPONSE VirusTotalRequestIpAddressReport(
    _In_ PPH_STRING IpAddress
    )
{
    PVIRUSTOTAL_API_RESPONSE result = NULL;
    PPH_BYTES jsonString = NULL;
    PPH_HTTP_CONTEXT httpContext = NULL;
    PPH_STRING versionString = NULL;
    PPH_STRING userAgentString = NULL;
    PPH_STRING urlPathString = NULL;
    PVOID jsonRootObject = NULL;

    versionString = PhGetPhVersion();
    userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer);

    if (!PhHttpSocketCreate(
        &httpContext, 
        PhGetString(userAgentString)
        ))
    {
        goto CleanupExit;
    }

    if (!PhHttpSocketConnect(
        httpContext,
        L"www.virustotal.com",
        PH_HTTP_DEFAULT_HTTPS_PORT
        ))
    {
        goto CleanupExit;
    }

    {
        PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

        urlPathString = PhFormatString(
            L"%s%s%s%s%s%S%s%s",
            L"/vtapi",
            L"/v2",
            L"/ip-address",
            L"/report",
            L"?\x0061\x0070\x0069\x006B\x0065\x0079=",
            resourceString->Buffer,
            L"&ip=",
            IpAddress->Buffer
            );

        PhClearReference(&resourceString);
    }

    if (!PhHttpSocketBeginRequest(
        httpContext,
        L"POST",
        PhGetString(urlPathString),
        PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE
        ))
    {
        goto CleanupExit;
    }

    if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0))
        goto CleanupExit;

    if (!PhHttpSocketSendRequest(httpContext, NULL, 0))
        goto CleanupExit;

    if (!PhHttpSocketEndRequest(httpContext))
        goto CleanupExit;
    
    if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE)))
        goto CleanupExit;

    if (!(jsonRootObject = PhCreateJsonParser(jsonString->Buffer)))
        goto CleanupExit;

    result = PhAllocate(sizeof(VIRUSTOTAL_API_RESPONSE));
    memset(result, 0, sizeof(VIRUSTOTAL_API_RESPONSE));

    //result->ResponseCode = PhGetJsonValueAsLong64(jsonRootObject, "response_code");
    //result->StatusMessage = PhGetJsonValueAsString(jsonRootObject, "verbose_msg");
    //result->PermaLink = PhGetJsonValueAsString(jsonRootObject, "permalink");
    //result->ScanId = PhGetJsonValueAsString(jsonRootObject, "scan_id");

CleanupExit:

    if (httpContext)
        PhHttpSocketDestroy(httpContext);

    if (jsonRootObject)
        PhFreeJsonParser(jsonRootObject);

    PhClearReference(&jsonString);
    PhClearReference(&versionString);
    PhClearReference(&userAgentString);

    return result;
}
コード例 #4
0
PVIRUSTOTAL_FILE_REPORT VirusTotalRequestFileReport(
    _In_ PPH_STRING FileHash
    )
{
    PVIRUSTOTAL_FILE_REPORT result = NULL;
    PPH_BYTES jsonString = NULL;
    PPH_HTTP_CONTEXT httpContext = NULL;
    PPH_STRING versionString = NULL;
    PPH_STRING userAgentString = NULL;
    PPH_STRING urlPathString = NULL;
    PVOID jsonRootObject = NULL;
    PVOID jsonScanObject;

    versionString = PhGetPhVersion();
    userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer);

    if (!PhHttpSocketCreate(
        &httpContext, 
        PhGetString(userAgentString)
        ))
    {
        goto CleanupExit;
    }

    if (!PhHttpSocketConnect(
        httpContext,
        L"www.virustotal.com",
        PH_HTTP_DEFAULT_HTTPS_PORT
        ))
    {
        goto CleanupExit;
    }

    {
        PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

        urlPathString = PhFormatString(
            L"%s%s%s%s%s%S%s%s",
            L"/vtapi",
            L"/v2",
            L"/file",
            L"/report",
            L"?\x0061\x0070\x0069\x006B\x0065\x0079=",
            resourceString->Buffer,
            L"&resource=",
            FileHash->Buffer
            );

        PhClearReference(&resourceString);
    }

    if (!PhHttpSocketBeginRequest(
        httpContext,
        L"POST",
        PhGetString(urlPathString),
        PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE
        ))
    {
        goto CleanupExit;
    }

    if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0))
        goto CleanupExit;

    if (!PhHttpSocketSendRequest(httpContext, NULL, 0))
        goto CleanupExit;

    if (!PhHttpSocketEndRequest(httpContext))
        goto CleanupExit;
    
    if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE)))
        goto CleanupExit;

    if (!(jsonRootObject = PhCreateJsonParser(jsonString->Buffer)))
        goto CleanupExit;

    result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT));
    memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT));

    result->ResponseCode = PhGetJsonValueAsLong64(jsonRootObject, "response_code");
    result->StatusMessage = PhGetJsonValueAsString(jsonRootObject, "verbose_msg");
    result->PermaLink = PhGetJsonValueAsString(jsonRootObject, "permalink");
    result->ScanDate = PhGetJsonValueAsString(jsonRootObject, "scan_date");
    result->ScanId = PhGetJsonValueAsString(jsonRootObject, "scan_id");
    result->Total = PhFormatUInt64(PhGetJsonValueAsLong64(jsonRootObject, "total"), FALSE);
    result->Positives = PhFormatUInt64(PhGetJsonValueAsLong64(jsonRootObject, "positives"), FALSE);
    //result->Md5 = PhGetJsonValueAsString(jsonRootObject, "md5");
    //result->Sha1 = PhGetJsonValueAsString(jsonRootObject, "sha1");
    //result->Sha256 = PhGetJsonValueAsString(jsonRootObject, "sha256");

    if (jsonScanObject = PhGetJsonObject(jsonRootObject, "scans"))
    {
        PPH_LIST jsonArrayList;

        if (jsonArrayList = PhGetJsonObjectAsArrayList(jsonScanObject))
        {
            result->ScanResults = PhCreateList(jsonArrayList->Count);

            for (ULONG i = 0; i < jsonArrayList->Count; i++)
            {
                PVIRUSTOTAL_FILE_REPORT_RESULT entry;
                PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i];

                entry = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT));
                memset(entry, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT));

                entry->Vendor = PhConvertUtf8ToUtf16(object->Key);
                entry->Detected = PhGetJsonObjectBool(object->Entry, "detected");
                entry->EngineVersion = PhGetJsonValueAsString(object->Entry, "version");
                entry->DetectionName = PhGetJsonValueAsString(object->Entry, "result");
                entry->DatabaseDate = PhGetJsonValueAsString(object->Entry, "update");
                PhAddItemList(result->ScanResults, entry);

                PhFree(object);
            }

            PhDereferenceObject(jsonArrayList);
        }
    }

CleanupExit:

    if (httpContext)
        PhHttpSocketDestroy(httpContext);

    if (jsonRootObject)
        PhFreeJsonParser(jsonRootObject);

    PhClearReference(&jsonString);
    PhClearReference(&versionString);
    PhClearReference(&userAgentString);

    return result;
}
コード例 #5
0
PPH_BYTES VirusTotalSendHttpRequest(
    _In_ PPH_BYTES JsonArray
    )
{
    PPH_BYTES subRequestBuffer = NULL;
    PPH_HTTP_CONTEXT httpContext = NULL;
    PPH_STRING versionString = NULL;
    PPH_STRING userAgentString = NULL;
    PPH_STRING urlPathString = NULL;

    versionString = PhGetPhVersion();
    userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer);

    if (!PhHttpSocketCreate(&httpContext, PhGetString(userAgentString)))
        goto CleanupExit;

    if (!PhHttpSocketConnect(httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT))
        goto CleanupExit;

    {
        PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

        urlPathString = PhFormatString(
            L"%s%s%s%s%S",
            L"/partners",
            L"/sysinternals",
            L"/file-reports",
            L"?\x0061\x0070\x0069\x006B\x0065\x0079=",
            resourceString->Buffer
            );

        PhClearReference(&resourceString);
    }

    if (!PhHttpSocketBeginRequest(
        httpContext,
        L"POST",
        urlPathString->Buffer,
        PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE
        ))
    {
        goto CleanupExit;
    }

    if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0))
        goto CleanupExit;

    if (!PhHttpSocketSendRequest(httpContext, JsonArray->Buffer, (ULONG)JsonArray->Length))
        goto CleanupExit;

    if (!PhHttpSocketEndRequest(httpContext))
        goto CleanupExit;

    if (!(subRequestBuffer = PhHttpSocketDownloadString(httpContext, FALSE)))
        goto CleanupExit;

CleanupExit:

    if (httpContext)
        PhHttpSocketDestroy(httpContext);

    PhClearReference(&urlPathString);
    PhClearReference(&versionString);
    PhClearReference(&userAgentString);

    if (JsonArray)
        PhDereferenceObject(JsonArray);

    return subRequestBuffer;
}
コード例 #6
0
ファイル: updater.c プロジェクト: john-peterson/processhacker
static NTSTATUS DownloadUpdateThreadStart(
    __in PVOID Parameter
    )
{
    PPH_STRING downloadUrlPath = NULL;
    HANDLE tempFileHandle = NULL;
    HINTERNET hInitialize = NULL, hConnection = NULL, hRequest = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    HWND hwndDlg = (HWND)Parameter;

    Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), FALSE);
    SetDlgItemText(hwndDlg, IDC_STATUS, L"Initializing");

    // Reset the progress state on Vista and above.
    if (WindowsVersion > WINDOWS_XP)
        SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_NORMAL, 0L);

    if (!ConnectionAvailable())
        return status;

    __try
    {
        // Get temp dir.
        WCHAR tempPathString[MAX_PATH];
        DWORD tempPathLength = GetTempPath(MAX_PATH, tempPathString);

        if (tempPathLength == 0 || tempPathLength > MAX_PATH)
        {
            LogEvent(hwndDlg, PhFormatString(L"CreateFile failed (%d)", GetLastError()));
            __leave;
        }

        // create the download path string.
        downloadUrlPath = PhFormatString(
            L"/projects/processhacker/files/processhacker2/processhacker-%u.%u-setup.exe/download?use_mirror=autoselect", /* ?use_mirror=waix" */
            UpdateData.MajorVersion,
            UpdateData.MinorVersion
            );

        // Append the tempath to our string: %TEMP%processhacker-%u.%u-setup.exe
        // Example: C:\\Users\\dmex\\AppData\\Temp\\processhacker-2.10-setup.exe
        SetupFilePath = PhFormatString(
            L"%sprocesshacker-%u.%u-setup.exe",
            tempPathString,
            UpdateData.MajorVersion,
            UpdateData.MinorVersion
            );

        // Create output file
        status = PhCreateFileWin32(
            &tempFileHandle,
            SetupFilePath->Buffer,
            FILE_GENERIC_READ | FILE_GENERIC_WRITE,
            FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            FILE_OVERWRITE_IF,
            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
            );

        if (!NT_SUCCESS(status))
        {
            LogEvent(hwndDlg, PhFormatString(L"PhCreateFileWin32 failed (%s)", ((PPH_STRING)PHA_DEREFERENCE(PhGetNtMessage(status)))->Buffer));
            __leave;
        }

        {
            // Create a user agent string.
            PPH_STRING phVersion = PhGetPhVersion();
            PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer);

            // Initialize the wininet library.
            if (!(hInitialize = InternetOpen(
                userAgent->Buffer,
                INTERNET_OPEN_TYPE_PRECONFIG,
                NULL,
                NULL,
                0
                )))
            {
                LogEvent(hwndDlg, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError()));

                PhDereferenceObject(userAgent);
                PhDereferenceObject(phVersion);

                __leave;
            }

            PhDereferenceObject(userAgent);
            PhDereferenceObject(phVersion);
        }

        // Connect to the server.
        if (!(hConnection = InternetConnect(
            hInitialize,
            L"sourceforge.net",
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0)))
        {
            LogEvent(hwndDlg, PhFormatString(L"InternetConnect failed (%d)", GetLastError()));
            __leave;
        }

        // Open the HTTP request.
        if (!(hRequest = HttpOpenRequest(
            hConnection,
            NULL,
            downloadUrlPath->Buffer,
            NULL,
            NULL,
            NULL,
            INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RESYNCHRONIZE,
            0
            )))
        {
            LogEvent(hwndDlg, PhFormatString(L"HttpOpenRequest failed (%d)", GetLastError()));
            __leave;
        }

        SetDlgItemText(hwndDlg, IDC_STATUS, L"Connecting");

        // Send the HTTP request.
        if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
        {
            LogEvent(hwndDlg, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError()));

            // Enable the 'Retry' button.
            Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
            SetDlgItemText(hwndDlg, IDC_DOWNLOAD, L"Retry");

            // Reset the state and let user retry the download.
            PhUpdaterState = Download;
        }
        else
        {
            BYTE hashBuffer[20]; 
            DWORD contentLengthSize = sizeof(DWORD);
            PH_HASH_CONTEXT hashContext;

            // Initialize hash algorithm.
            PhInitializeHash(&hashContext, Sha1HashAlgorithm);

            if (!HttpQueryInfoW(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &contentLengthSize, 0))
            {
                // No content length...impossible to calculate % complete...
                // we can read the data, BUT in this instance Sourceforge always returns the content length
                // so instead we'll exit here instead of downloading the file.
                LogEvent(hwndDlg, PhFormatString(L"HttpQueryInfo failed (%d)", GetLastError()));
                __leave;
            }
            else
            {
                BYTE buffer[PAGE_SIZE];
                DWORD bytesRead = 0, startTick = 0;
                IO_STATUS_BLOCK isb;

                // Zero the buffer.
                ZeroMemory(buffer, PAGE_SIZE);

                // Reset the counters.
                bytesDownloaded = 0, timeTransferred = 0, LastUpdateTime = 0;
                IsUpdating = FALSE;

                // Start the clock.
                startTick = GetTickCount();
                timeTransferred = startTick;

                // Download the data.
                while (InternetReadFile(hRequest, buffer, PAGE_SIZE, &bytesRead))
                {
                    // If we get zero bytes, the file was uploaded or there was an error.
                    if (bytesRead == 0)
                        break;

                    // If window closed and thread handle was closed, just dispose and exit.
                    // (This also skips error checking/prompts and updating the disposed UI)
                    if (!DownloadThreadHandle)
                        __leave;

                    // Update the hash of bytes we downloaded.
                    PhUpdateHash(&hashContext, buffer, bytesRead);

                    // Write the downloaded bytes to disk.
                    status = NtWriteFile(
                        tempFileHandle,
                        NULL,
                        NULL,
                        NULL,
                        &isb,
                        buffer,
                        bytesRead,
                        NULL,
                        NULL
                        );

                    if (!NT_SUCCESS(status))
                    {
                        PPH_STRING message = PhGetNtMessage(status);

                        LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer));

                        PhDereferenceObject(message);
                        break;
                    }

                    // Check dwBytesRead are the same dwBytesWritten length returned by WriteFile.
                    if (bytesRead != isb.Information)
                    {
                        PPH_STRING message = PhGetNtMessage(status);

                        LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer));

                        PhDereferenceObject(message);
                        break;
                    }
                                        
                    // Update our total bytes downloaded
                    PhAcquireQueuedLockExclusive(&Lock);
                    bytesDownloaded += (DWORD)isb.Information;
                    PhReleaseQueuedLockExclusive(&Lock);

                    AsyncUpdate();
                }

                // Check if we downloaded the entire file.
                assert(bytesDownloaded == contentLength);

                // Compute our hash result.
                if (PhFinalHash(&hashContext, &hashBuffer, 20, NULL))
                {
                    // Allocate our hash string, hex the final hash result in our hashBuffer.
                    PPH_STRING hexString = PhBufferToHexString(hashBuffer, 20);

                    if (PhEqualString(hexString, UpdateData.Hash, TRUE))
                    {
                        // If PH is not elevated, set the UAC shield for the install button as the setup requires elevation.
                        if (!PhElevated)
                            SendMessage(GetDlgItem(hwndDlg, IDC_DOWNLOAD), BCM_SETSHIELD, 0, TRUE);

                        // Set the download result, don't include hash status since it succeeded.
                        //SetDlgItemText(hwndDlg, IDC_STATUS, L"Download Complete");
                        // Set button text for next action
                        Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Install");
                        // Enable the Install button
                        Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
                        // Hash succeeded, set state as ready to install.
                        PhUpdaterState = Install;
                    }
                    else
                    {
                        if (WindowsVersion > WINDOWS_XP)
                            SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L);

                        SetDlgItemText(hwndDlg, IDC_STATUS, L"Download complete, SHA1 Hash failed.");

                        // Set button text for next action
                        Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Retry");
                        // Enable the Install button
                        Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
                        // Hash failed, reset state to downloading so user can redownload the file.
                        PhUpdaterState = Download;
                    }

                    PhDereferenceObject(hexString);
                }
                else
                {
                    //SetDlgItemText(hwndDlg, IDC_STATUS, L"PhFinalHash failed");

                    // Show fancy Red progressbar if hash failed on Vista and above.
                    if (WindowsVersion > WINDOWS_XP)
                        SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L);
                }
            }
        }

        status = STATUS_SUCCESS;
    }
    __finally
    {
        if (hInitialize)
        {
            InternetCloseHandle(hInitialize);
            hInitialize = NULL;
        }

        if (hConnection)
        {
            InternetCloseHandle(hConnection);
            hConnection = NULL;
        }

        if (hRequest)
        {
            InternetCloseHandle(hRequest);
            hRequest = NULL;
        }

        if (tempFileHandle)
        {
            NtClose(tempFileHandle);
            tempFileHandle = NULL;
        }

        if (downloadUrlPath)
        {
            PhDereferenceObject(downloadUrlPath);
            downloadUrlPath = NULL;
        }
    }

    return status;
}
コード例 #7
0
ファイル: updater.c プロジェクト: john-peterson/processhacker
static BOOL QueryXmlData(
    VOID
    )
{
    PCHAR data = NULL;
    BOOL isSuccess = FALSE;
    HINTERNET netInitialize = NULL, netConnection = NULL, netRequest = NULL;
    mxml_node_t *xmlDoc = NULL, *xmlNodeVer = NULL, *xmlNodeRelDate = NULL, *xmlNodeSize = NULL, *xmlNodeHash = NULL;

    // Create a user agent string.
    PPH_STRING phVersion = PhGetPhVersion();
    PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer);

    __try
    {
        // Initialize the wininet library.
        if (!(netInitialize = InternetOpen(
            userAgent->Buffer,
            INTERNET_OPEN_TYPE_PRECONFIG,
            NULL,
            NULL,
            0
            )))
        {
            LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError()));
            __leave;
        }

        // Connect to the server.
        if (!(netConnection = InternetConnect(
            netInitialize,
            UPDATE_URL,
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0
            )))
        {
            LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) InternetConnect failed (%d)", GetLastError()));
            __leave;
        }

        // Open the HTTP request.
        if (!(netRequest = HttpOpenRequest(
            netConnection,
            L"GET",
            UPDATE_FILE,
            NULL,
            NULL,
            NULL,
            // wj32: do NOT cache --------------------------- Old - "Always cache the update xml, it can be cleared by deleting IE history, we configured the file to cache locally for two days."
            INTERNET_FLAG_RELOAD,
            0
            )))
        {
            LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) HttpOpenRequest failed (%d)", GetLastError()));
            __leave;
        }

        // Send the HTTP request.
        if (!HttpSendRequest(netRequest, NULL, 0, NULL, 0))
        {
            LogEvent(NULL, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError()));
            __leave;
        }

        // Read the resulting xml into our buffer.
        if (!ReadRequestString(netRequest, &data, NULL))
        {
            // We don't need to log this.
            __leave;
        }

        // Load our XML.
        xmlDoc = mxmlLoadString(NULL, data, QueryXmlDataCallback);
        // Check our XML.
        if (xmlDoc == NULL || xmlDoc->type != MXML_ELEMENT)
        {
            LogEvent(NULL, PhCreateString(L"Updater: (WorkerThreadStart) mxmlLoadString failed."));
            __leave;
        }

        // Find the ver node.
        xmlNodeVer = mxmlFindElement(xmlDoc, xmlDoc, "ver", NULL, NULL, MXML_DESCEND);
        // Find the reldate node.
        xmlNodeRelDate = mxmlFindElement(xmlDoc, xmlDoc, "reldate", NULL, NULL, MXML_DESCEND);
        // Find the size node.
        xmlNodeSize = mxmlFindElement(xmlDoc, xmlDoc, "size", NULL, NULL, MXML_DESCEND);
        // Find the hash node.
        xmlNodeHash = mxmlFindElement(xmlDoc, xmlDoc, "sha1", NULL, NULL, MXML_DESCEND);

        // Format strings into unicode PPH_STRING's
        UpdateData.Version = PhGetOpaqueXmlNodeText(xmlNodeVer);
        UpdateData.RelDate = PhGetOpaqueXmlNodeText(xmlNodeRelDate);
        UpdateData.Size = PhGetOpaqueXmlNodeText(xmlNodeSize);
        UpdateData.Hash = PhGetOpaqueXmlNodeText(xmlNodeHash);

        // parse and check string
        //if (!ParseVersionString(XmlData->Version->Buffer, &XmlData->MajorVersion, &XmlData->MinorVersion))
        //    __leave;
        if (!PhIsNullOrEmptyString(UpdateData.Version))
        {
            PH_STRINGREF sr, majorPart, minorPart;
            ULONG64 majorInteger = 0, minorInteger = 0;

            PhInitializeStringRef(&sr, UpdateData.Version->Buffer);

            if (PhSplitStringRefAtChar(&sr, '.', &majorPart, &minorPart))
            {
                PhStringToInteger64(&majorPart, 10, &majorInteger);
                PhStringToInteger64(&minorPart, 10, &minorInteger);

                UpdateData.MajorVersion = (ULONG)majorInteger;
                UpdateData.MinorVersion = (ULONG)minorInteger;

                isSuccess = TRUE;
            }
        }
    }
    __finally
    {
        if (xmlDoc)
        {
            mxmlDelete(xmlDoc);
            xmlDoc = NULL;
        }

        if (netInitialize)
        {
            InternetCloseHandle(netInitialize);
            netInitialize = NULL;
        }

        if (netConnection)
        {
            InternetCloseHandle(netConnection);
            netConnection = NULL;
        }

        if (netRequest)
        {
            InternetCloseHandle(netRequest);
            netRequest = NULL;
        }

        if (userAgent)
        {
            PhDereferenceObject(userAgent);
            userAgent = NULL;
        }

        if (phVersion)
        {
            PhDereferenceObject(phVersion);
            phVersion = NULL;
        }
    }

    return isSuccess;
}
コード例 #8
0
ファイル: virustotal.c プロジェクト: poizan42/processhacker2
PVIRUSTOTAL_FILE_REPORT_RESULT VirusTotalSendHttpFileReportRequest(
    _In_ PPH_STRING FileHash
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE fileHandle = INVALID_HANDLE_VALUE;
    HINTERNET httpSessionHandle = NULL;
    HINTERNET connectHandle = NULL;
    HINTERNET requestHandle = NULL;
    PSTR subRequestBuffer = NULL;
    PPH_STRING phVersion = NULL;
    PPH_STRING userAgent = NULL;
    PPH_STRING urlString = NULL;

    phVersion = PhGetPhVersion();
    userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer);

    if (!(httpSessionHandle = WinHttpOpen(
        userAgent->Buffer,
        WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS,
        0
        )))
    {
        goto CleanupExit;
    }

    if (WindowsVersion >= WINDOWS_8_1)
    {
        WinHttpSetOption(
            httpSessionHandle,
            WINHTTP_OPTION_DECOMPRESSION, 
            &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, 
            sizeof(ULONG)
            );
    }

    if (!(connectHandle = WinHttpConnect(
        httpSessionHandle,
        L"www.virustotal.com",
        INTERNET_DEFAULT_HTTPS_PORT,
        0
        )))
    {
        goto CleanupExit;
    }

    PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

    urlString = PhFormatString(
        L"%s%s%s%s%S%s%s",
        L"/vtapi",
        L"/v2",
        L"/file",
        L"/report",
        L"?apikey=",
        resourceString->Buffer,
        L"&resource=",
        PhGetString(FileHash)
        );

    PhClearReference(&resourceString);

    if (!(requestHandle = WinHttpOpenRequest(
        connectHandle,
        L"POST",
        PhGetString(urlString),
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_SECURE
        )))
    {
        goto CleanupExit;
    }

    if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0))
        goto CleanupExit;

    if (!WinHttpSendRequest(
        requestHandle,
        WINHTTP_NO_ADDITIONAL_HEADERS,
        0,
        WINHTTP_NO_REQUEST_DATA,
        0,
        WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
        0
        ))
    {
        goto CleanupExit;
    }

    if (WinHttpReceiveResponse(requestHandle, NULL))
    {
        BYTE buffer[PAGE_SIZE];
        ULONG allocatedLength;
        ULONG dataLength;
        ULONG returnLength;

        allocatedLength = sizeof(buffer);
        subRequestBuffer = PhAllocate(allocatedLength);
        dataLength = 0;

        while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength))
        {
            if (returnLength == 0)
                break;

            if (allocatedLength < dataLength + returnLength)
            {
                allocatedLength *= 2;
                subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
            }

            memcpy(subRequestBuffer + dataLength, buffer, returnLength);
            dataLength += returnLength;
        }

        if (allocatedLength < dataLength + 1)
        {
            allocatedLength++;
            subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
        }

        subRequestBuffer[dataLength] = 0;
    }

CleanupExit:

    PhClearReference(&urlString);

    if (requestHandle)
        WinHttpCloseHandle(requestHandle);

    if (connectHandle)
        WinHttpCloseHandle(connectHandle);

    if (httpSessionHandle)
        WinHttpCloseHandle(httpSessionHandle);


    PVOID jsonRootObject;
    //PVOID jsonScanObject;
    PVIRUSTOTAL_FILE_REPORT_RESULT result;

    if (!(jsonRootObject = CreateJsonParser(subRequestBuffer)))
        goto CleanupExit;

    if (!GetJsonValueAsUlong(jsonRootObject, "response_code"))
        goto CleanupExit;

    result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT));
    memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT));

    result->Total = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "total"), FALSE);
    result->Positives = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "positives"), FALSE);
    result->Resource = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "resource"));
    result->ScanId = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_id"));
    result->Md5 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "md5"));
    result->Sha1 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha1"));
    result->Sha256 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha256"));
    result->ScanDate = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_date"));
    result->Permalink = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "permalink"));
    result->StatusMessage = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "verbose_msg"));

    //if (jsonScanObject = JsonGetObject(jsonRootObject, "scans"))
    //{
    //    PPH_LIST jsonArrayList;
    //
    //    if (jsonArrayList = JsonGetObjectArrayList(jsonScanObject))
    //    {
    //        result->ScanResults = PhCreateList(jsonArrayList->Count);
    //
    //        for (ULONG i = 0; i < jsonArrayList->Count; i++)
    //        {
    //            PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i];
    //            //BOOLEAN detected = GetJsonValueAsBool(object->Entry, "detected") == TRUE;
    //            //PSTR version = GetJsonValueAsString(object->Entry, "version");
    //            //PSTR result = GetJsonValueAsString(object->Entry, "result");
    //            //PSTR update = GetJsonValueAsString(object->Entry, "update");
    //
    //            PhFree(object);
    //        }
    //
    //        PhDereferenceObject(jsonArrayList);
    //    }
    //}

    return result;
}
コード例 #9
0
ファイル: virustotal.c プロジェクト: poizan42/processhacker2
PSTR VirusTotalSendHttpRequest(
    _In_ PPH_BYTES JsonArray
    )
{
    HANDLE fileHandle = INVALID_HANDLE_VALUE;
    HINTERNET httpSessionHandle = NULL;
    HINTERNET connectHandle = NULL;
    HINTERNET requestHandle = NULL;
    PSTR subRequestBuffer = NULL;
    PPH_STRING phVersion = NULL;
    PPH_STRING userAgent = NULL;
    PPH_STRING urlString = NULL;

    phVersion = PhGetPhVersion();
    userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer);

    if (!(httpSessionHandle = WinHttpOpen(
        userAgent->Buffer,
        WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS,
        0
        )))
    {
        goto CleanupExit;
    }

    if (WindowsVersion >= WINDOWS_8_1)
    {
        WinHttpSetOption(
            httpSessionHandle, 
            WINHTTP_OPTION_DECOMPRESSION, 
            &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, 
            sizeof(ULONG)
            );
    }

    if (!(connectHandle = WinHttpConnect(
        httpSessionHandle,
        L"www.virustotal.com",
        INTERNET_DEFAULT_HTTPS_PORT,
        0
        )))
    {
        goto CleanupExit;
    }

    PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

    urlString = PhFormatString(
        L"%s%s%s%s%S",
        L"/partners", 
        L"/sysinternals",
        L"/file-reports",
        L"?apikey=",
        resourceString->Buffer
        );

    PhClearReference(&resourceString);

    if (!(requestHandle = WinHttpOpenRequest(
        connectHandle,
        L"POST",
        PhGetString(urlString),
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_SECURE
        )))
    {
        PhClearReference(&urlString);
        goto CleanupExit;
    }

    PhClearReference(&urlString);

    if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0))
    {
        goto CleanupExit;
    }

    if (!WinHttpSendRequest(
        requestHandle, 
        WINHTTP_NO_ADDITIONAL_HEADERS, 
        0, 
        JsonArray->Buffer, 
        (ULONG)JsonArray->Length, 
        (ULONG)JsonArray->Length,
        0
        ))
    {
        goto CleanupExit;
    }

    if (WinHttpReceiveResponse(requestHandle, NULL))
    {
        BYTE buffer[PAGE_SIZE];
        ULONG allocatedLength;
        ULONG dataLength;
        ULONG returnLength;

        allocatedLength = sizeof(buffer);
        subRequestBuffer = PhAllocate(allocatedLength);
        dataLength = 0;

        while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength))
        {
            if (returnLength == 0)
                break;

            if (allocatedLength < dataLength + returnLength)
            {
                allocatedLength *= 2;
                subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
            }

            memcpy(subRequestBuffer + dataLength, buffer, returnLength);
            dataLength += returnLength;
        }

        if (allocatedLength < dataLength + 1)
        {
            allocatedLength++;
            subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
        }

        // Ensure that the buffer is null-terminated.
        subRequestBuffer[dataLength] = 0;
    }

CleanupExit:

    if (requestHandle)
        WinHttpCloseHandle(requestHandle);

    if (connectHandle)
        WinHttpCloseHandle(connectHandle);

    if (httpSessionHandle)
        WinHttpCloseHandle(httpSessionHandle);

    if (JsonArray)
        PhDereferenceObject(JsonArray);

    return subRequestBuffer;
}
コード例 #10
0
ファイル: ping.c プロジェクト: glenrgordon/processhacker2
NTSTATUS NetworkPingThreadStart(
    _In_ PVOID Parameter
    )
{
    HANDLE icmpHandle = INVALID_HANDLE_VALUE;
    ULONG icmpCurrentPingMs = 0;
    ULONG icmpReplyCount = 0;
    ULONG icmpReplyLength = 0;
    PVOID icmpReplyBuffer = NULL;
    PPH_BYTES icmpEchoBuffer = NULL;
    IP_OPTION_INFORMATION pingOptions =
    {
        255,         // Time To Live
        0,           // Type Of Service
        IP_FLAG_DF,  // IP header flags
        0            // Size of options data
    };

    PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;

    __try
    {
        // Create ICMP echo buffer.
        if (context->PingSize > 0 && context->PingSize != 32)
        {
            PPH_STRING randString;

            randString = PhCreateStringEx(NULL, context->PingSize * 2 + 2);

            // Create a random string to fill the buffer.
            PhGenerateRandomAlphaString(randString->Buffer, (ULONG)randString->Length / sizeof(WCHAR));

            icmpEchoBuffer = PhConvertUtf16ToMultiByte(randString->Buffer);
            PhDereferenceObject(randString);
        }
        else
        {
            PPH_STRING version;

            // We're using a default length, query the PH version and use the previous buffer format.
            version = PhGetPhVersion();

            if (version)
            {
                icmpEchoBuffer = FormatAnsiString("processhacker_%S_0x0D06F00D_x1", version->Buffer);
                PhDereferenceObject(version);
            }
        }

        if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE)
        {
            SOCKADDR_IN6 icmp6LocalAddr = { 0 };
            SOCKADDR_IN6 icmp6RemoteAddr = { 0 };
            PICMPV6_ECHO_REPLY2 icmp6ReplyStruct = NULL;

            // Create ICMPv6 handle.
            if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE)
                __leave;

            // Set Local IPv6-ANY address.
            icmp6LocalAddr.sin6_addr = in6addr_any;
            icmp6LocalAddr.sin6_family = AF_INET6;

            // Set Remote IPv6 address.
            icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr;
            icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port);

            // Allocate ICMPv6 message.
            icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer);
            icmpReplyBuffer = PhAllocate(icmpReplyLength);
            memset(icmpReplyBuffer, 0, icmpReplyLength);

            InterlockedIncrement(&context->PingSentCount);

            // Send ICMPv6 ping...
            icmpReplyCount = Icmp6SendEcho2(
                icmpHandle,
                NULL,
                NULL,
                NULL,
                &icmp6LocalAddr,
                &icmp6RemoteAddr,
                icmpEchoBuffer->Buffer,
                (USHORT)icmpEchoBuffer->Length,
                &pingOptions,
                icmpReplyBuffer,
                icmpReplyLength,
                context->MaxPingTimeout
                );

            icmp6ReplyStruct = (PICMPV6_ECHO_REPLY2)icmpReplyBuffer;
            if (icmpReplyCount > 0 && icmp6ReplyStruct)
            {
                BOOLEAN icmpPacketSignature = FALSE;

                if (icmp6ReplyStruct->Status != IP_SUCCESS)
                {
                    InterlockedIncrement(&context->PingLossCount);
                }

                if (_memicmp(
                    icmp6ReplyStruct->Address.sin6_addr,
                    context->IpAddress.In6Addr.u.Word,
                    sizeof(icmp6ReplyStruct->Address.sin6_addr)
                    ) != 0)
                {
                    InterlockedIncrement(&context->UnknownAddrCount);
                }

                icmpPacketSignature = _memicmp(
                    icmpEchoBuffer->Buffer,
                    icmp6ReplyStruct->Data,
                    icmpEchoBuffer->Length
                    ) == 0;

                if (!icmpPacketSignature)
                {
                    InterlockedIncrement(&context->HashFailCount);
                }

                icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime;
            }
            else
            {
                InterlockedIncrement(&context->PingLossCount);
            }
        }
        else
        {
            IPAddr icmpLocalAddr = 0;
            IPAddr icmpRemoteAddr = 0;
            PICMP_ECHO_REPLY icmpReplyStruct = NULL;

            // Create ICMPv4 handle.
            if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
                __leave;

            // Set Local IPv4-ANY address.
            icmpLocalAddr = in4addr_any.s_addr;

            // Set Remote IPv4 address.
            icmpRemoteAddr = context->IpAddress.InAddr.s_addr;

            // Allocate ICMPv4 message.
            icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer);
            icmpReplyBuffer = PhAllocate(icmpReplyLength);
            memset(icmpReplyBuffer, 0, icmpReplyLength);

            InterlockedIncrement(&context->PingSentCount);

            // Send ICMPv4 ping...
            icmpReplyCount = IcmpSendEcho2Ex(
                icmpHandle,
                NULL,
                NULL,
                NULL,
                icmpLocalAddr,
                icmpRemoteAddr,
                icmpEchoBuffer->Buffer,
                (USHORT)icmpEchoBuffer->Length,
                &pingOptions,
                icmpReplyBuffer,
                icmpReplyLength,
                context->MaxPingTimeout
                );

            icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer;

            if (icmpReplyStruct && icmpReplyCount > 0)
            {
                BOOLEAN icmpPacketSignature = FALSE;

                if (icmpReplyStruct->Status != IP_SUCCESS)
                {
                    InterlockedIncrement(&context->PingLossCount);
                }

                if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr)
                {
                    InterlockedIncrement(&context->UnknownAddrCount);
                }

                if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length)
                {
                    icmpPacketSignature = _memicmp(
                        icmpEchoBuffer->Buffer,
                        icmpReplyStruct->Data,
                        icmpReplyStruct->DataSize
                        ) == 0;
                }

                icmpCurrentPingMs = icmpReplyStruct->RoundTripTime;

                if (!icmpPacketSignature)
                {
                    InterlockedIncrement(&context->HashFailCount);
                }
            }
            else
            {
                InterlockedIncrement(&context->PingLossCount);
            }
        }

        InterlockedIncrement(&context->PingRecvCount);

        if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs)
            context->PingMinMs = icmpCurrentPingMs;
        if (icmpCurrentPingMs > context->PingMaxMs)
            context->PingMaxMs = icmpCurrentPingMs;

        context->CurrentPingMs = icmpCurrentPingMs;

        PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs);
    }
    __finally
    {
        if (icmpEchoBuffer)
        {
            PhDereferenceObject(icmpEchoBuffer);
        }

        if (icmpHandle != INVALID_HANDLE_VALUE)
        {
            IcmpCloseHandle(icmpHandle);
        }

        if (icmpReplyBuffer)
        {
            PhFree(icmpReplyBuffer);
        }
    }

    PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0);

    return STATUS_SUCCESS;
}
コード例 #11
-1
ファイル: ping.c プロジェクト: lei720/processhacker2
static NTSTATUS PhNetworkPingThreadStart(
    _In_ PVOID Parameter
    )
{
    HANDLE icmpHandle = INVALID_HANDLE_VALUE;
    ULONG icmpCurrentPingMs = 0;
    ULONG icmpCurrentPingTtl = 0;
    ULONG icmpReplyCount = 0;
    ULONG icmpReplyLength = 0;
    PVOID icmpReplyBuffer = NULL;
    PPH_STRING phVersion = NULL;
    PPH_BYTES icmpEchoBuffer = NULL;
    IP_OPTION_INFORMATION pingOptions =
    {
        255,         // Time To Live
        0,           // Type Of Service
        IP_FLAG_DF,  // IP header flags
        0            // Size of options data
    };

    PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;

    __try
    {
        // Query PH version.
        if ((phVersion = PhGetPhVersion()) == NULL)
            __leave;

        // Create ICMP echo buffer.
        if ((icmpEchoBuffer = PhFormatAnsiString("processhacker_%S_0x0D06F00D_x1", phVersion->Buffer)) == NULL)
            __leave;

        if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE)
        {
            SOCKADDR_IN6 icmp6LocalAddr = { 0 };
            SOCKADDR_IN6 icmp6RemoteAddr = { 0 };
            PICMPV6_ECHO_REPLY icmp6ReplyStruct = NULL;

            // Create ICMPv6 handle.
            if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE)
                __leave;

            // Set Local IPv6-ANY address.
            icmp6LocalAddr.sin6_addr = in6addr_any;
            icmp6LocalAddr.sin6_family = AF_INET6;

            // Set Remote IPv6 address.
            icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr;
            icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port);

            // Allocate ICMPv6 message.
            icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer);
            icmpReplyBuffer = PhAllocate(icmpReplyLength);
            memset(icmpReplyBuffer, 0, icmpReplyLength);

            InterlockedIncrement(&context->PingSentCount);

            // Send ICMPv6 ping...
            icmpReplyCount = Icmp6SendEcho2(
                icmpHandle,
                NULL,
                NULL,
                NULL,
                &icmp6LocalAddr,
                &icmp6RemoteAddr,
                icmpEchoBuffer->Buffer,
                (USHORT)icmpEchoBuffer->Length,
                &pingOptions,
                icmpReplyBuffer,
                icmpReplyLength,
                context->MaxPingTimeout
                );

            icmp6ReplyStruct = (PICMPV6_ECHO_REPLY)icmpReplyBuffer;
            if (icmpReplyCount > 0 && icmp6ReplyStruct)
            {
                BOOLEAN icmpPacketSignature = FALSE;

                if (icmp6ReplyStruct->Status != IP_SUCCESS)
                {
                    InterlockedIncrement(&context->PingLossCount);
                }

                if (_memicmp(
                    icmp6ReplyStruct->Address.sin6_addr,
                    context->IpAddress.In6Addr.u.Word,
                    sizeof(icmp6ReplyStruct->Address.sin6_addr)
                    ) != 0)
                {
                    InterlockedIncrement(&context->UnknownAddrCount);
                }

                //if (icmp6ReplyStruct->DataSize == icmpEchoBuffer->MaximumLength)
                //{
                //    icmpPacketSignature = (_memicmp(
                //        icmpEchoBuffer->Buffer,
                //        icmp6ReplyStruct->Data,
                //        icmp6ReplyStruct->DataSize
                //        ) == 0);
                //}

                //if (icmpPacketSignature != TRUE)
                //{
                //    InterlockedIncrement(&context->HashFailCount);
                //}

                icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime;
                //icmpCurrentPingTtl = icmp6ReplyStruct->Options.Ttl;
            }
            else
            {
                InterlockedIncrement(&context->PingLossCount);
            }
        }
        else
        {
            IPAddr icmpLocalAddr = 0;
            IPAddr icmpRemoteAddr = 0;
            PICMP_ECHO_REPLY icmpReplyStruct = NULL;

            // Create ICMPv4 handle.
            if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
                __leave;

            // Set Local IPv4-ANY address.
            icmpLocalAddr = in4addr_any.s_addr;

            // Set Remote IPv4 address.
            icmpRemoteAddr = context->IpAddress.InAddr.s_addr;

            // Allocate ICMPv4 message.
            icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer);
            icmpReplyBuffer = PhAllocate(icmpReplyLength);
            memset(icmpReplyBuffer, 0, icmpReplyLength);

            InterlockedIncrement(&context->PingSentCount);

            // Send ICMPv4 ping...
            //if (WindowsVersion > WINDOWS_VISTA)
            //{
            //    // Vista SP1 and up we can specify the source address:
            //    icmpReplyCount = IcmpSendEcho2Ex(
            //        icmpHandle,
            //        NULL,
            //        NULL,
            //        NULL,
            //        icmpLocalAddr,
            //        icmpRemoteAddr,
            //        icmpEchoBuffer->Buffer,
            //        icmpEchoBuffer->MaximumLength,
            //        &pingOptions,
            //        icmpReplyBuffer,
            //        icmpReplyLength,
            //        context->MaxPingTimeout
            //        );
            //}

            icmpReplyCount = IcmpSendEcho2(
                icmpHandle,
                NULL,
                NULL,
                NULL,
                icmpRemoteAddr,
                icmpEchoBuffer->Buffer,
                (USHORT)icmpEchoBuffer->Length,
                &pingOptions,
                icmpReplyBuffer,
                icmpReplyLength,
                context->MaxPingTimeout
                );

            icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer;

            if (icmpReplyStruct && icmpReplyCount > 0)
            {
                BOOLEAN icmpPacketSignature = FALSE;

                if (icmpReplyStruct->Status != IP_SUCCESS)
                {
                    InterlockedIncrement(&context->PingLossCount);
                }

                if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr)
                {
                    InterlockedIncrement(&context->UnknownAddrCount);
                }

                if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length)
                {
                    icmpPacketSignature = (_memicmp(
                        icmpEchoBuffer->Buffer,
                        icmpReplyStruct->Data,
                        icmpReplyStruct->DataSize
                        ) == 0);
                }

                icmpCurrentPingMs = icmpReplyStruct->RoundTripTime;
                icmpCurrentPingTtl = icmpReplyStruct->Options.Ttl;

                if (!icmpPacketSignature)
                {
                    InterlockedIncrement(&context->HashFailCount);
                }
            }
            else
            {
                InterlockedIncrement(&context->PingLossCount);
            }
        }

        InterlockedIncrement(&context->PingRecvCount);

        if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs)
            context->PingMinMs = icmpCurrentPingMs;
        if (icmpCurrentPingMs > context->PingMaxMs)
            context->PingMaxMs = icmpCurrentPingMs;

        context->CurrentPingMs = icmpCurrentPingMs;

        PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs);
    }
    __finally
    {
        if (phVersion)
        {
            PhDereferenceObject(phVersion);
        }

        if (icmpEchoBuffer)
        {
            PhDereferenceObject(icmpEchoBuffer);
        }

        if (icmpHandle != INVALID_HANDLE_VALUE)
        {
            IcmpCloseHandle(icmpHandle);
        }

        if (icmpReplyBuffer)
        {
            PhFree(icmpReplyBuffer);
        }
    }

    PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0);

    return STATUS_SUCCESS;
}