Stopping the Event Logger via Service Control Handler

Introduction

In this post, I’d like to briefly demonstrate a way to stop the event logger service without terminating any threads or processes. It’s quite an old technique, dating back to 2008 so it may not interest everyone.

An existing tool called Phant0m can already stop the event logger, but does so through termination of threads. The method I describe here doesn’t terminate anything.

About 10 years ago while taking part in a security challenge, one the goals in addition to compromising a windows box via buffer overflow was to stop the event logger without terminating any process. The last step was the most interesting aspect of the challenge, since sending SERVICE_CONTROL_STOP to the eventlog service simply didn’t work, and terminating the host process, which at the time was “services.exe” wasn’t an option. So, this led me to investigating the eventlog internals to try determine how the service was stopped by the operating system before shutting down.

The ControlHandler

When installing a service, the StartServiceCtrlDispatcher API is called with a pointer to one or more SERVICE_TABLE_ENTRY structures pre-initialized with a service name and pointer to a ServiceMain procedure. The following structure is defined in the Windows SDK.

typedef struct _SERVICE_TABLE_ENTRY {
  LPTSTR                  lpServiceName;
  LPSERVICE_MAIN_FUNCTION lpServiceProc;
} SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;

When the service starts, it calls ServiceMain, which then calls RegisterServiceCtrlHandler or RegisterServiceCtrlHandlerEx to register a service control handler.

SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandler(
  _In_ LPCTSTR            lpServiceName,
  _In_ LPHANDLER_FUNCTION lpHandlerProc
);

Each service has a control handler invoked by the control dispatcher when the service process receives a control request.

VOID WINAPI Handler(_In_ DWORD fdwControl);

After disassembling the Handler procedure for event logger, it was discovered the service will accept SERVICE_CONTROL_STOP, but only if the control dispatcher allows it. So, one needs to bypass the dispatcher completely to stop the event logger.

Locating the Control Handler

If we examine an existing service, and set a breakpoint on the ControlHandler address, we can see from the stack, calls are made from the address space of sechost.dll, which is used by the service control dispatcher to interact with service control handlers. We can also see the same module contains a Dispatch Table, which contains an array of INTERNAL_DISPATCH_ENTRY structures.

typedef struct _INTERNAL_DISPATCH_ENTRY {
  LPWSTR                  ServiceName;
  LPWSTR                  ServiceRealName;
  LPSERVICE_MAIN_FUNCTION ServiceStartRoutine;
  LPHANDLER_FUNCTION_EX   ControlHandler;
  HANDLE                  StatusHandle;
  DWORD                   ServiceFlags;
  DWORD                   Tag;
  HANDLE                  MainThreadHandle;
  DWORD                   dwReserved;
} INTERNAL_DISPATCH_ENTRY;

On Windows 10, this structure has been revised. It contains additional entries.

typedef struct _INTERNAL_DISPATCH_ENTRY {
    LPWSTR                  ServiceName;
    LPWSTR                  ServiceRealName;
    LPWSTR                  ServiceName2;       // Windows 10
    LPSERVICE_MAIN_FUNCTION ServiceStartRoutine;
    LPHANDLER_FUNCTION_EX   ControlHandler;
    HANDLE                  StatusHandle;
    DWORD64                 ServiceFlags;        // 64-bit on windows 10
    DWORD64                 Tag;
    HANDLE                  MainThreadHandle;
    DWORD64                 dwReserved;
    DWORD64                 dwReserved2;
} INTERNAL_DISPATCH_ENTRY, *PINTERNAL_DISPATCH_ENTRY;

Stopping the event logger

The following steps are almost exactly what I used in July 2008 to stop the event logger, and should still work today.

  1. Open the process hosting the event logger service.
  2. Locate the INTERNAL_DISPATCH_ENTRY by scanning memory.
  3. Once found, pass the ControlHandler address to RtlCreateUserThread with SERVICE_CONTROL_STOP as the parameter.
  4. Wait for thread to terminate.

Here’s a demonstration with event logger

Source code for a PoC tool can be found here.

This entry was posted in malware, programming, security, shellcode, windows and tagged , , . Bookmark the permalink.

1 Response to Stopping the Event Logger via Service Control Handler

  1. Pingback: Windows Process Injection: Service Control Handler | modexp

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s