[SERVICES][ADVAPI32] Support the security process aka lsass.exe

- Reserve the pipe NtControlPipe0 for the security process.
- Count regular service control pipes from 1.
- Use I_ScIsSecurityProcess to identify the security process.
- Services.exe uses the SECURITY_SERVICES_STARTED event to notify the security process that NtControlPipe0 is ready for use.
This commit is contained in:
Eric Kohl 2019-08-31 17:24:47 +02:00
parent 8571c26a71
commit 0625eb3746
4 changed files with 139 additions and 55 deletions

View file

@ -40,61 +40,89 @@ static DWORD PipeTimeout = 30000; /* 30 Seconds */
/* FUNCTIONS *****************************************************************/
static
BOOL
ScmIsSecurityService(
_In_ PSERVICE_IMAGE pServiceImage)
{
return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL);
}
static DWORD
ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage)
ScmCreateNewControlPipe(
_In_ PSERVICE_IMAGE pServiceImage,
_In_ BOOL bSecurityServiceProcess)
{
WCHAR szControlPipeName[MAX_PATH + 1];
SECURITY_ATTRIBUTES SecurityAttributes;
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
DWORD ServiceCurrent = 0;
DWORD KeyDisposition;
DWORD dwServiceCurrent = 1;
DWORD dwKeyDisposition;
DWORD dwKeySize;
DWORD dwError;
/* Get the service number */
/* TODO: Create registry entry with correct write access */
dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL,
REG_OPTION_VOLATILE,
KEY_WRITE | KEY_READ,
NULL,
&hServiceCurrentKey,
&KeyDisposition);
if (dwError != ERROR_SUCCESS)
if (bSecurityServiceProcess == FALSE)
{
DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
return dwError;
}
if (KeyDisposition == REG_OPENED_EXISTING_KEY)
{
dwKeySize = sizeof(DWORD);
dwError = RegQueryValueExW(hServiceCurrentKey,
L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize);
/* TODO: Create registry entry with correct write access */
dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent",
0,
NULL,
REG_OPTION_VOLATILE,
KEY_WRITE | KEY_READ,
NULL,
&hServiceCurrentKey,
&dwKeyDisposition);
if (dwError != ERROR_SUCCESS)
{
RegCloseKey(hServiceCurrentKey);
DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
return dwError;
}
ServiceCurrent++;
if (dwKeyDisposition == REG_OPENED_EXISTING_KEY)
{
dwKeySize = sizeof(DWORD);
dwError = RegQueryValueExW(hServiceCurrentKey,
L"",
0,
NULL,
(BYTE*)&dwServiceCurrent,
&dwKeySize);
if (dwError != ERROR_SUCCESS)
{
RegCloseKey(hServiceCurrentKey);
DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
return dwError;
}
dwServiceCurrent++;
}
dwError = RegSetValueExW(hServiceCurrentKey,
L"",
0,
REG_DWORD,
(BYTE*)&dwServiceCurrent,
sizeof(dwServiceCurrent));
RegCloseKey(hServiceCurrentKey);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
return dwError;
}
}
dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent));
RegCloseKey(hServiceCurrentKey);
if (dwError != ERROR_SUCCESS)
else
{
DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
return dwError;
dwServiceCurrent = 0;
}
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName),
L"\\\\.\\pipe\\net\\NtControlPipe%lu", ServiceCurrent);
L"\\\\.\\pipe\\net\\NtControlPipe%lu", dwServiceCurrent);
DPRINT("PipeName: %S\n", szControlPipeName);
@ -437,6 +465,7 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService)
DWORD dwError = ERROR_SUCCESS;
DWORD dwRecordSize;
LPWSTR pString;
BOOL bSecurityService;
DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
@ -518,8 +547,11 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService)
goto done;
}
bSecurityService = ScmIsSecurityService(pServiceImage);
/* Create the control pipe */
dwError = ScmCreateNewControlPipe(pServiceImage);
dwError = ScmCreateNewControlPipe(pServiceImage,
bSecurityService);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError);
@ -542,6 +574,11 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService)
goto done;
}
if (bSecurityService)
{
SetSecurityServicesEvent();
}
/* FIXME: Add more initialization code here */
@ -1806,7 +1843,8 @@ ScmWaitForServiceConnect(PSERVICE Service)
}
}
if (dwProcessId != Service->lpImage->dwProcessId)
if ((ScmIsSecurityService(Service->lpImage) == FALSE)&&
(dwProcessId != Service->lpImage->dwProcessId))
{
#if 0
_ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
@ -1916,7 +1954,7 @@ ScmStartUserModeService(PSERVICE Service,
StartupInfo.lpDesktop = L"WinSta0\\Default";
}
if (wcsstr(Service->lpImage->pszImagePath, L"\\system32\\lsass.exe") == NULL)
if (!ScmIsSecurityService(Service->lpImage))
{
Result = CreateProcessW(NULL,
Service->lpImage->pszImagePath,

View file

@ -28,6 +28,7 @@ int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
BOOL ScmInitialize = FALSE;
BOOL ScmShutdown = FALSE;
static HANDLE hScmShutdownEvent = NULL;
static HANDLE hScmSecurityServicesEvent = NULL;
/* FUNCTIONS *****************************************************************/
@ -48,6 +49,38 @@ PrintString(LPCSTR fmt, ...)
}
DWORD
SetSecurityServicesEvent(VOID)
{
DWORD dwError;
if (hScmSecurityServicesEvent != NULL)
return ERROR_SUCCESS;
/* Create or open the SECURITY_SERVICES_STARTED event */
hScmSecurityServicesEvent = CreateEventW(NULL,
TRUE,
FALSE,
L"SECURITY_SERVICES_STARTED");
if (hScmSecurityServicesEvent == NULL)
{
dwError = GetLastError();
if (dwError != ERROR_ALREADY_EXISTS)
return dwError;
hScmSecurityServicesEvent = OpenEventW(EVENT_MODIFY_STATE,
FALSE,
L"SECURITY_SERVICES_STARTED");
if (hScmSecurityServicesEvent == NULL)
return GetLastError();
}
SetEvent(hScmSecurityServicesEvent);
return ERROR_SUCCESS;
}
VOID
ScmLogEvent(DWORD dwEventId,
WORD wType,
@ -258,6 +291,9 @@ done:
if (bCanDeleteNamedPipeCriticalSection != FALSE)
ScmDeleteNamedPipeCriticalSection();
if (hScmSecurityServicesEvent != NULL)
CloseHandle(hScmSecurityServicesEvent);
/* Close the shutdown event */
if (hScmShutdownEvent != NULL)
CloseHandle(hScmShutdownEvent);

View file

@ -256,6 +256,7 @@ ScmCreateDefaultServiceSD(
/* services.c */
VOID PrintString(LPCSTR fmt, ...);
DWORD SetSecurityServicesEvent(VOID);
VOID ScmLogEvent(DWORD dwEventId,
WORD wType,
WORD wStrings,

View file

@ -58,6 +58,7 @@ typedef struct _ACTIVE_SERVICE
static DWORD dwActiveServiceCount = 0;
static PACTIVE_SERVICE lpActiveServices = NULL;
static handle_t hStatusBinding = NULL;
static BOOL bSecurityServiceProcess = FALSE;
/* FUNCTIONS *****************************************************************/
@ -227,7 +228,7 @@ ScConnectControlPipe(HANDLE *hPipe)
{
DWORD dwBytesWritten;
DWORD dwState;
DWORD dwServiceCurrent = 0;
DWORD dwServiceCurrent = 1;
NTSTATUS Status;
WCHAR NtControlPipeName[MAX_PATH + 1];
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
@ -237,25 +238,32 @@ ScConnectControlPipe(HANDLE *hPipe)
hPipe);
/* Get the service number and create the named pipe */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
QueryTable[0].Name = L"";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].EntryContext = &dwServiceCurrent;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"ServiceCurrent",
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
if (bSecurityServiceProcess == FALSE)
{
ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
return RtlNtStatusToDosError(Status);
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].Name = L"";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].EntryContext = &dwServiceCurrent;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"ServiceCurrent",
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
return RtlNtStatusToDosError(Status);
}
}
else
{
dwServiceCurrent = 0;
}
swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent);
TRACE("PipeName: %S\n", NtControlPipeName);
if (!WaitNamedPipeW(NtControlPipeName, 30000))
{
@ -836,13 +844,14 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
*
* Undocumented
*
* @unimplemented
* @implemented
*/
VOID
WINAPI
I_ScIsSecurityProcess(VOID)
{
FIXME("I_ScIsSecurityProcess()\n");
TRACE("I_ScIsSecurityProcess()\n");
bSecurityServiceProcess = TRUE;
}