diff --git a/2.x/trunk/ProcessHacker/actions.c b/2.x/trunk/ProcessHacker/actions.c index 923b17600..dee89c9a7 100644 --- a/2.x/trunk/ProcessHacker/actions.c +++ b/2.x/trunk/ProcessHacker/actions.c @@ -286,7 +286,7 @@ BOOLEAN PhpShowErrorAndConnectToPhSvc( * attempt failed. */ BOOLEAN PhUiConnectToPhSvc( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_ BOOLEAN ConnectOnly ) { diff --git a/2.x/trunk/ProcessHacker/appsup.c b/2.x/trunk/ProcessHacker/appsup.c index 99a51c085..24f82cc35 100644 --- a/2.x/trunk/ProcessHacker/appsup.c +++ b/2.x/trunk/ProcessHacker/appsup.c @@ -1205,7 +1205,7 @@ VOID PhWritePhTextHeader( } BOOLEAN PhShellProcessHacker( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_opt_ PWSTR Parameters, _In_ ULONG ShowWindowType, _In_ ULONG Flags, diff --git a/2.x/trunk/ProcessHacker/include/phapp.h b/2.x/trunk/ProcessHacker/include/phapp.h index 365c1aa6a..9562c4d69 100644 --- a/2.x/trunk/ProcessHacker/include/phapp.h +++ b/2.x/trunk/ProcessHacker/include/phapp.h @@ -351,7 +351,7 @@ VOID PhWritePhTextHeader( PHAPPAPI BOOLEAN PhShellProcessHacker( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_opt_ PWSTR Parameters, _In_ ULONG ShowWindowType, _In_ ULONG Flags, @@ -1113,11 +1113,13 @@ typedef enum _PH_ACTION_ELEVATION_LEVEL AlwaysElevateAction = 2 } PH_ACTION_ELEVATION_LEVEL; +PHAPPAPI BOOLEAN PhUiConnectToPhSvc( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_ BOOLEAN ConnectOnly ); +PHAPPAPI VOID PhUiDisconnectFromPhSvc( VOID ); diff --git a/2.x/trunk/ProcessHacker/include/phsvc.h b/2.x/trunk/ProcessHacker/include/phsvc.h index 4267031bc..ef1094fbf 100644 --- a/2.x/trunk/ProcessHacker/include/phsvc.h +++ b/2.x/trunk/ProcessHacker/include/phsvc.h @@ -116,6 +116,13 @@ NTSTATUS PhSvcCaptureSid( _Out_ PSID *CapturedSid ); +NTSTATUS PhSvcCaptureSecurityDescriptor( + _In_ PPH_RELATIVE_STRINGREF String, + _In_ BOOLEAN AllowNull, + _In_ SECURITY_INFORMATION RequiredInformation, + _Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor + ); + NTSTATUS PhSvcApiDefault( _In_ PPHSVC_CLIENT Client, _Inout_ PPHSVC_API_MSG Message @@ -196,4 +203,9 @@ NTSTATUS PhSvcApiCreateProcessIgnoreIfeoDebugger( _Inout_ PPHSVC_API_MSG Message ); +NTSTATUS PhSvcApiSetServiceSecurity( + _In_ PPHSVC_CLIENT Client, + _Inout_ PPHSVC_API_MSG Message + ); + #endif diff --git a/2.x/trunk/ProcessHacker/include/phsvcapi.h b/2.x/trunk/ProcessHacker/include/phsvcapi.h index 85f96bfb2..e1729875d 100644 --- a/2.x/trunk/ProcessHacker/include/phsvcapi.h +++ b/2.x/trunk/ProcessHacker/include/phsvcapi.h @@ -21,6 +21,7 @@ typedef enum _PHSVC_API_NUMBER PhSvcPostMessageApiNumber = 14, PhSvcSendMessageApiNumber = 15, PhSvcCreateProcessIgnoreIfeoDebuggerApiNumber = 16, + PhSvcSetServiceSecurityApiNumber = 17, PhSvcMaximumApiNumber } PHSVC_API_NUMBER, *PPHSVC_API_NUMBER; @@ -214,6 +215,16 @@ typedef union _PHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER } i; } PHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER, *PPHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER; +typedef union _PHSVC_API_SETSERVICESECURITY +{ + struct + { + PH_RELATIVE_STRINGREF ServiceName; + SECURITY_INFORMATION SecurityInformation; + PH_RELATIVE_STRINGREF SecurityDescriptor; + } i; +} PHSVC_API_SETSERVICESECURITY, *PPHSVC_API_SETSERVICESECURITY; + typedef struct _PHSVC_API_MSG { PORT_MESSAGE h; @@ -240,6 +251,7 @@ typedef struct _PHSVC_API_MSG PHSVC_API_ISSUEMEMORYLISTCOMMAND IssueMemoryListCommand; PHSVC_API_POSTMESSAGE PostMessage; PHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER CreateProcessIgnoreIfeoDebugger; + PHSVC_API_SETSERVICESECURITY SetServiceSecurity; } u; }; }; diff --git a/2.x/trunk/ProcessHacker/include/phsvccl.h b/2.x/trunk/ProcessHacker/include/phsvccl.h index 0e65d5cfd..b781808f8 100644 --- a/2.x/trunk/ProcessHacker/include/phsvccl.h +++ b/2.x/trunk/ProcessHacker/include/phsvccl.h @@ -46,6 +46,7 @@ NTSTATUS PhSvcCallCreateService( _In_opt_ PWSTR Password ); +PHLIBAPI NTSTATUS PhSvcCallChangeServiceConfig( _In_ PWSTR ServiceName, _In_ ULONG ServiceType, @@ -60,6 +61,7 @@ NTSTATUS PhSvcCallChangeServiceConfig( _In_opt_ PWSTR DisplayName ); +PHLIBAPI NTSTATUS PhSvcCallChangeServiceConfig2( _In_ PWSTR ServiceName, _In_ ULONG InfoLevel, @@ -89,6 +91,7 @@ NTSTATUS PhSvcCallIssueMemoryListCommand( _In_ SYSTEM_MEMORY_LIST_COMMAND Command ); +PHLIBAPI NTSTATUS PhSvcCallPostMessage( _In_opt_ HWND hWnd, _In_ UINT Msg, @@ -96,6 +99,7 @@ NTSTATUS PhSvcCallPostMessage( _In_ LPARAM lParam ); +PHLIBAPI NTSTATUS PhSvcCallSendMessage( _In_opt_ HWND hWnd, _In_ UINT Msg, @@ -107,4 +111,10 @@ NTSTATUS PhSvcCallCreateProcessIgnoreIfeoDebugger( _In_ PWSTR FileName ); +NTSTATUS PhSvcCallSetServiceSecurity( + _In_ PWSTR ServiceName, + _In_ SECURITY_INFORMATION SecurityInformation, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor + ); + #endif diff --git a/2.x/trunk/ProcessHacker/phsvc/clapi.c b/2.x/trunk/ProcessHacker/phsvc/clapi.c index 50a6c9c89..02c313538 100644 --- a/2.x/trunk/ProcessHacker/phsvc/clapi.c +++ b/2.x/trunk/ProcessHacker/phsvc/clapi.c @@ -806,3 +806,74 @@ NTSTATUS PhSvcCallCreateProcessIgnoreIfeoDebugger( return status; } + +PSECURITY_DESCRIPTOR PhpAbsoluteToSelfRelativeSD( + _In_ PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + _Out_ PULONG BufferSize + ) +{ + NTSTATUS status; + ULONG bufferSize = 0; + PSECURITY_DESCRIPTOR selfRelativeSecurityDescriptor; + + status = RtlAbsoluteToSelfRelativeSD(AbsoluteSecurityDescriptor, NULL, &bufferSize); + + if (status != STATUS_BUFFER_TOO_SMALL) + return NULL; + + selfRelativeSecurityDescriptor = PhAllocate(bufferSize); + status = RtlAbsoluteToSelfRelativeSD(AbsoluteSecurityDescriptor, selfRelativeSecurityDescriptor, &bufferSize); + + if (!NT_SUCCESS(status)) + { + PhFree(selfRelativeSecurityDescriptor); + return NULL; + } + + *BufferSize = bufferSize; + + return selfRelativeSecurityDescriptor; +} + +NTSTATUS PhSvcCallSetServiceSecurity( + _In_ PWSTR ServiceName, + _In_ SECURITY_INFORMATION SecurityInformation, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor + ) +{ + NTSTATUS status; + PHSVC_API_MSG m; + PSECURITY_DESCRIPTOR selfRelativeSecurityDescriptor = NULL; + ULONG bufferSize; + PVOID serviceName = NULL; + PVOID copiedSelfRelativeSecurityDescriptor = NULL; + + if (!PhSvcClPortHandle) + return STATUS_PORT_DISCONNECTED; + + selfRelativeSecurityDescriptor = PhpAbsoluteToSelfRelativeSD(SecurityDescriptor, &bufferSize); + + if (!selfRelativeSecurityDescriptor) + { + status = STATUS_BAD_DESCRIPTOR_FORMAT; + goto CleanupExit; + } + + m.ApiNumber = PhSvcSetServiceSecurityApiNumber; + m.u.SetServiceSecurity.i.SecurityInformation = SecurityInformation; + status = STATUS_NO_MEMORY; + + if (!(serviceName = PhSvcpCreateString(ServiceName, -1, &m.u.SetServiceSecurity.i.ServiceName))) + goto CleanupExit; + if (!(copiedSelfRelativeSecurityDescriptor = PhSvcpCreateString(selfRelativeSecurityDescriptor, bufferSize, &m.u.SetServiceSecurity.i.SecurityDescriptor))) + goto CleanupExit; + + status = PhSvcpCallServer(&m); + +CleanupExit: + if (selfRelativeSecurityDescriptor) PhFree(selfRelativeSecurityDescriptor); + if (serviceName) PhSvcpFreeHeap(serviceName); + if (copiedSelfRelativeSecurityDescriptor) PhSvcpFreeHeap(copiedSelfRelativeSecurityDescriptor); + + return status; +} diff --git a/2.x/trunk/ProcessHacker/phsvc/svcapi.c b/2.x/trunk/ProcessHacker/phsvc/svcapi.c index 773b2446b..16c157380 100644 --- a/2.x/trunk/ProcessHacker/phsvc/svcapi.c +++ b/2.x/trunk/ProcessHacker/phsvc/svcapi.c @@ -22,6 +22,7 @@ #include #include +#include typedef struct _PHSVCP_CAPTURED_RUNAS_SERVICE_PARAMETERS { @@ -51,7 +52,8 @@ PPHSVC_API_PROCEDURE PhSvcApiCallTable[] = PhSvcApiIssueMemoryListCommand, PhSvcApiPostMessage, PhSvcApiSendMessage, - PhSvcApiCreateProcessIgnoreIfeoDebugger + PhSvcApiCreateProcessIgnoreIfeoDebugger, + PhSvcApiSetServiceSecurity }; C_ASSERT(sizeof(PhSvcApiCallTable) / sizeof(PPHSVC_API_PROCEDURE) == PhSvcMaximumApiNumber - 1); @@ -214,6 +216,59 @@ NTSTATUS PhSvcCaptureSid( return STATUS_SUCCESS; } +NTSTATUS PhSvcCaptureSecurityDescriptor( + _In_ PPH_RELATIVE_STRINGREF String, + _In_ BOOLEAN AllowNull, + _In_ SECURITY_INFORMATION RequiredInformation, + _Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor + ) +{ + NTSTATUS status; + PSECURITY_DESCRIPTOR securityDescriptor; + ULONG bufferSize; + + if (!NT_SUCCESS(status = PhSvcCaptureBuffer(String, AllowNull, &securityDescriptor))) + return status; + + if (securityDescriptor) + { + if (!RtlValidRelativeSecurityDescriptor(securityDescriptor, String->Length, RequiredInformation)) + { + PhFree(securityDescriptor); + return STATUS_INVALID_SECURITY_DESCR; + } + + bufferSize = String->Length; + status = RtlSelfRelativeToAbsoluteSD2(securityDescriptor, &bufferSize); + + if (status == STATUS_BUFFER_TOO_SMALL) + { + PVOID newBuffer; + + newBuffer = PhAllocate(bufferSize); + memcpy(newBuffer, securityDescriptor, String->Length); + PhFree(securityDescriptor); + securityDescriptor = newBuffer; + + status = RtlSelfRelativeToAbsoluteSD2(securityDescriptor, &bufferSize); + } + + if (!NT_SUCCESS(status)) + { + PhFree(securityDescriptor); + return status; + } + + *CapturedSecurityDescriptor = securityDescriptor; + } + else + { + *CapturedSecurityDescriptor = NULL; + } + + return STATUS_SUCCESS; +} + NTSTATUS PhSvcApiDefault( _In_ PPHSVC_CLIENT Client, _Inout_ PPHSVC_API_MSG Message @@ -946,3 +1001,64 @@ NTSTATUS PhSvcApiCreateProcessIgnoreIfeoDebugger( return status; } + +NTSTATUS PhSvcApiSetServiceSecurity( + _In_ PPHSVC_CLIENT Client, + _Inout_ PPHSVC_API_MSG Message + ) +{ + NTSTATUS status; + PPH_STRING serviceName; + PSECURITY_DESCRIPTOR securityDescriptor; + ACCESS_MASK desiredAccess; + SC_HANDLE serviceHandle; + + if (NT_SUCCESS(status = PhSvcCaptureString(&Message->u.SetServiceSecurity.i.ServiceName, FALSE, &serviceName))) + { + if (NT_SUCCESS(status = PhSvcCaptureSecurityDescriptor(&Message->u.SetServiceSecurity.i.SecurityDescriptor, FALSE, 0, &securityDescriptor))) + { + desiredAccess = 0; + + if ((Message->u.SetServiceSecurity.i.SecurityInformation & OWNER_SECURITY_INFORMATION) || + (Message->u.SetServiceSecurity.i.SecurityInformation & GROUP_SECURITY_INFORMATION)) + { + desiredAccess |= WRITE_OWNER; + } + + if (Message->u.SetServiceSecurity.i.SecurityInformation & DACL_SECURITY_INFORMATION) + { + desiredAccess |= WRITE_DAC; + } + + if (Message->u.SetServiceSecurity.i.SecurityInformation & SACL_SECURITY_INFORMATION) + { + desiredAccess |= ACCESS_SYSTEM_SECURITY; + } + + if (serviceHandle = PhOpenService(serviceName->Buffer, desiredAccess)) + { + if (!PhSetSeObjectSecurity( + serviceHandle, + SE_SERVICE, + Message->u.SetServiceSecurity.i.SecurityInformation, + securityDescriptor + )) + { + status = PhGetLastWin32ErrorAsNtStatus(); + } + + CloseServiceHandle(serviceHandle); + } + else + { + status = PhGetLastWin32ErrorAsNtStatus(); + } + + PhFree(securityDescriptor); + } + + PhDereferenceObject(serviceName); + } + + return status; +} diff --git a/2.x/trunk/ProcessHacker/sdk/phapppub.h b/2.x/trunk/ProcessHacker/sdk/phapppub.h index 270565b09..4cac5b805 100644 --- a/2.x/trunk/ProcessHacker/sdk/phapppub.h +++ b/2.x/trunk/ProcessHacker/sdk/phapppub.h @@ -503,7 +503,7 @@ PhWritePhTextHeader( PHAPPAPI BOOLEAN PhShellProcessHacker( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_opt_ PWSTR Parameters, _In_ ULONG ShowWindowType, _In_ ULONG Flags, @@ -997,6 +997,21 @@ PhFormatLogEntry( // actions +PHAPPAPI +BOOLEAN +NTAPI +PhUiConnectToPhSvc( + _In_opt_ HWND hWnd, + _In_ BOOLEAN ConnectOnly + ); + +PHAPPAPI +VOID +NTAPI +PhUiDisconnectFromPhSvc( + VOID + ); + PHAPPAPI BOOLEAN NTAPI diff --git a/2.x/trunk/ProcessHacker/srvprp.c b/2.x/trunk/ProcessHacker/srvprp.c index 11adb4c33..1bb13b9e2 100644 --- a/2.x/trunk/ProcessHacker/srvprp.c +++ b/2.x/trunk/ProcessHacker/srvprp.c @@ -60,6 +60,36 @@ static NTSTATUS PhpOpenService( return STATUS_SUCCESS; } +static _Callback_ NTSTATUS PhpSetServiceSecurity( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ SECURITY_INFORMATION SecurityInformation, + _In_opt_ PVOID Context + ) +{ + NTSTATUS status; + PPH_STD_OBJECT_SECURITY stdObjectSecurity; + + stdObjectSecurity = (PPH_STD_OBJECT_SECURITY)Context; + + status = PhStdSetObjectSecurity(SecurityDescriptor, SecurityInformation, Context); + + if ((status == STATUS_ACCESS_DENIED || status == NTSTATUS_FROM_WIN32(ERROR_ACCESS_DENIED)) && !PhElevated) + { + // Elevate using phsvc. + if (PhUiConnectToPhSvc(NULL, FALSE)) + { + status = PhSvcCallSetServiceSecurity( + ((PPH_SERVICE_ITEM)stdObjectSecurity->Context)->Name->Buffer, + SecurityInformation, + SecurityDescriptor + ); + PhUiDisconnectFromPhSvc(); + } + } + + return status; +} + VOID PhShowServiceProperties( _In_ HWND ParentWindowHandle, _In_ PPH_SERVICE_ITEM ServiceItem @@ -108,7 +138,7 @@ VOID PhShowServiceProperties( pages[propSheetHeader.nPages++] = PhCreateSecurityPage( ServiceItem->Name->Buffer, PhStdGetObjectSecurity, - PhStdSetObjectSecurity, + PhpSetServiceSecurity, &stdObjectSecurity, accessEntries, numberOfAccessEntries diff --git a/2.x/trunk/phlib/include/ph.h b/2.x/trunk/phlib/include/ph.h index ed495d336..6b69b54dd 100644 --- a/2.x/trunk/phlib/include/ph.h +++ b/2.x/trunk/phlib/include/ph.h @@ -2579,7 +2579,7 @@ VOID PhShellExecute( PHLIBAPI BOOLEAN PhShellExecuteEx( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_ PWSTR FileName, _In_opt_ PWSTR Parameters, _In_ ULONG ShowWindowType, diff --git a/2.x/trunk/phlib/support.c b/2.x/trunk/phlib/support.c index a4c65e627..88ece3bfb 100644 --- a/2.x/trunk/phlib/support.c +++ b/2.x/trunk/phlib/support.c @@ -3232,7 +3232,7 @@ VOID PhShellExecute( * \param ProcessHandle A variable which receives a handle to the new process. */ BOOLEAN PhShellExecuteEx( - _In_ HWND hWnd, + _In_opt_ HWND hWnd, _In_ PWSTR FileName, _In_opt_ PWSTR Parameters, _In_ ULONG ShowWindowType,