/** * Starts a program as another user. * * \param hWnd A handle to the parent window. * \param Program The command line of the program to start. * \param UserName The user to start the program as. The user * name should be specified as: domain\\name. This parameter * can be NULL if \a ProcessIdWithToken is specified. * \param Password The password for the specified user. If there * is no password, specify an empty string. This parameter * can be NULL if \a ProcessIdWithToken is specified. * \param LogonType The logon type for the specified user. This * parameter can be 0 if \a ProcessIdWithToken is specified. * \param ProcessIdWithToken The ID of a process from which * to duplicate the token. * \param SessionId The ID of the session to run the program * under. * \param DesktopName The window station and desktop to run the * program under. * \param UseLinkedToken Uses the linked token if possible. * * \retval STATUS_CANCELLED The user cancelled the operation. * * \remarks This function will cause another instance of * Process Hacker to be executed if the current security context * does not have sufficient system access. This is done * through a UAC elevation prompt. */ NTSTATUS PhExecuteRunAsCommand2( _In_ HWND hWnd, _In_ PWSTR Program, _In_opt_ PWSTR UserName, _In_opt_ PWSTR Password, _In_opt_ ULONG LogonType, _In_opt_ HANDLE ProcessIdWithToken, _In_ ULONG SessionId, _In_ PWSTR DesktopName, _In_ BOOLEAN UseLinkedToken ) { NTSTATUS status = STATUS_SUCCESS; PH_RUNAS_SERVICE_PARAMETERS parameters; WCHAR serviceName[32]; PPH_STRING portName; UNICODE_STRING portNameUs; memset(¶meters, 0, sizeof(PH_RUNAS_SERVICE_PARAMETERS)); parameters.ProcessId = HandleToUlong(ProcessIdWithToken); parameters.UserName = UserName; parameters.Password = Password; parameters.LogonType = LogonType; parameters.SessionId = SessionId; parameters.CommandLine = Program; parameters.DesktopName = DesktopName; parameters.UseLinkedToken = UseLinkedToken; // Try to use an existing instance of the service if possible. if (RunAsOldServiceName[0] != 0) { PhAcquireQueuedLockExclusive(&RunAsOldServiceLock); portName = PhConcatStrings2(L"\\BaseNamedObjects\\", RunAsOldServiceName); PhStringRefToUnicodeString(&portName->sr, &portNameUs); if (NT_SUCCESS(PhSvcConnectToServer(&portNameUs, 0))) { parameters.ServiceName = RunAsOldServiceName; status = PhSvcCallInvokeRunAsService(¶meters); PhSvcDisconnectFromServer(); PhDereferenceObject(portName); PhReleaseQueuedLockExclusive(&RunAsOldServiceLock); return status; } PhDereferenceObject(portName); PhReleaseQueuedLockExclusive(&RunAsOldServiceLock); } // An existing instance was not available. Proceed normally. memcpy(serviceName, L"ProcessHacker", 13 * sizeof(WCHAR)); PhGenerateRandomAlphaString(&serviceName[13], 16); PhAcquireQueuedLockExclusive(&RunAsOldServiceLock); memcpy(RunAsOldServiceName, serviceName, sizeof(serviceName)); PhReleaseQueuedLockExclusive(&RunAsOldServiceLock); parameters.ServiceName = serviceName; if (PhGetOwnTokenAttributes().Elevated) { status = PhExecuteRunAsCommand(¶meters); } else { if (PhUiConnectToPhSvc(hWnd, FALSE)) { status = PhSvcCallExecuteRunAsCommand(¶meters); PhUiDisconnectFromPhSvc(); } else { status = STATUS_CANCELLED; } } return status; }
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; }