Tag Archives: syslog

Monitoring command line executions

A new feature coming to WLS is the ability to monitor commands executed at the command prompt. Using methods similar to Volatility’s cmdhistory.py and Extracting Windows Cmd Line Details from Physical Memory (pdf), commands and their associated cmd.exe PID can now be logged in near real-time.

Update: Here’s a video showing the results:

On WIndows XP, each cmd.exe process has it’s history stored in csrss.exe, which you can see using Process Explorer or Process Hacker:


On Windows Vista+, each cmd.exe process has it’s own conhost.exe:


The only correlation (that I could find) between the cmd.exe process and the process that holds it’s command history, is that csrss.exe / conhost.exe has an open handle to the associated cmd.exe process.

Finding the handle

NtQuerySystemInformation is used to obtain a list of handle entries which contain: OwnerPID, ObjectType, HandleFlags, ObjectPointer, and AccessMask. Each entry is checked for an ObjectType of Process, an OwnerPID belonging to csrss.exe / conhost.exe and a HandleValue that references a cmd.exe process. The HandleValue will be used to correlate this entry with a command history structure.

Finding the history structure

Scanning for the command history structure in memory involves searching for a known value, typically the maximum command history, then checking if the data surrounding it matches the structure definition. Invariably there will be false positives which can mostly be weeded out by value checking the first four values in the structure, and that the pointer in the structure points to it’s start address. This structure also contains the process handle value found in the handle entry above.

Address Description
x86 x64
0x00 0x00 Command Count (0 – Max)
0x02 0x02 Last Added (0 – Max)
0x04 0x04 Last Displayed (0 – Max)
0x06 0x06 First Command (0 – Max)
0x08 0x08 Max History
0x0C 0x10 Virtual Address / Handle
0x10 0x18 Pointer to this structure @ 0x00
0x14 0x20 Pointer to this structure @ 0x00

Now there is a 1:1 relationship between a cmd.exe instance and the command history in memory. Aside from the obvious benefit of knowing the ProcessId, scanning memory for new structures is no longer needed once each relationship is known, eliminating the most resource intensive part of the monitoring process.


cmd.exe opened with a ProcessId of 8884 (0x22B4), conhost.exe 14868 (0x3A14) has it’s command history.



A handle entry scan returns an entry with an OwnerPID matching that of conhost.exe and an ObjectType of 0x07, which is a Process on Vista+. The cmd.exe PID is obtained by duplicating the handle in HandleValue and calling GetProcessId. Since OwnerPID equals 0x3A14 and the value returned from GetProcessId is 0x22B4, we have a match.

AccessMask: 0x1FFFFF
HandleFlags: 0x00
HandleValue: 0x94
ObjectType: 0x07
OwnerPID: 0x3A14

A memory scan for the max history value (typically 0x32) finds the following structure, indicating 1 executed command, a virtual address of 0x94 which matches the HandleValue above, and two pointers that correctly identify the location in memory of the structure.

Address Value Description
0x00 0x01 CommandCount
0x01 0x00 CommandCount
0x02 0x00 LastAdded
0x03 0x00 LastAdded
0x04 0x00 LastDisplayed
0x05 0x00 LastDisplayed
0x06 0x00 FirstCommand
0x07 0x00 FirstCommand
0x08 0x32 MaxHistory
0x09 0x00 MaxHistory
0x0A 0xEF
0x0B 0xFF
0x0C 0xFC
0x0D 0xFC
0x0E 0xFC
0x0F 0xFF
0x10 0x94 VirtualAddress
0x11 0x00 VirtualAddress
0x12 0x00 VirtualAddress
0x13 0x00 VirtualAddress
0x14 0x00 VirtualAddress
0x15 0x00 VirtualAddress
0x16 0x00 VirtualAddress
0x17 0x00 VirtualAddress
0x18 0x78 StructurePointer1
0x19 0xE8 StructurePointer1
0x1A 0x16 StructurePointer1
0x1B 0x00 StructurePointer1
0x1C 0x00 StructurePointer1
0x1D 0x00 StructurePointer1
0x1E 0x00 StructurePointer1
0x1F 0x00 StructurePointer1
0x20 0x78 StructurePointer2
0x21 0xE8 StructurePointer2
0x22 0x16 StructurePointer2
0x23 0x00 StructurePointer2
0x24 0x00 StructurePointer2
0x25 0x00 StructurePointer2
0x26 0x00 StructurePointer2
0x27 0x00 StructurePointer2

The next section of the command history structure contains a list of pointers to simple structures containing the length of the command and the command itself in unicode.

0x28 &H70 Command1
0x29 &HDA Command1
0x2A &H16 Command1
0x2B &H0 Command1
0x2C &H0 Command1
0x2D &H0 Command1
0x2E &H0 Command1
0x2F &H0 Command1

The structure found by following the pointer above correctly indicates a length of 14 and the unicode encoded command “echo hi”, which was the command executed.

Address Value
0x00 0x0E 14
0x01 0X00
0x02 &H65 e
0x03 &H00
0x04 &H63 c
0x05 &H00
0x06 &H68 h
0x07 &H00
0x08 &H6F o
0x09 &H00
0x0A &H20
0x0B &H00
0x0C &H68 h
0x0D &H00
0x0E &H69 i
0x0F &H00


The resulting log from WLS looks like this:

2013-10-27T12:28:43-05:00 [pc] WLS_CommandMonitor: LogType=”WLS”, Command=”echo hi”, ProcessId=”0x22b4″, Type=”Executed”

WLS tracks the LastAdded and LastDisplayed values, and logs them when a change occurs, noting the Type in the log entry. Here I entered some more commands, arrowed up through history, then appended a character to a previous entry and executed it.

2013-10-27T13:28:30-05:00 [pc] WLS_CommandMonitor: LogType=”WLS”, Command=”echo hi2″, ProcessId=”0x22b4″, Type=”Executed”

2013-10-27T13:28:32-05:00 [pc] WLS_CommandMonitor: LogType=”WLS”, Command=”echo hi3″, ProcessId=”0x22b4″, Type=”Executed”

2013-10-27T13:28:33-05:00 [pc] WLS_CommandMonitor: LogType=”WLS”, Command=”echo hi2″, ProcessId=”0x22b4″, Type=”Displayed”

2013-10-27T13:28:37-05:00 [pc] WLS_CommandMonitor: LogType=”WLS”, Command=”echo hi24″, ProcessId=”0x22b4″, Type=”Executed”

For more information on WLS, click “WLS Information” at the top, or here: WLS Information

If you’d like additional information about WLS, send me a note via the contact form. WLS is currently available to US entities, but does require a signed license agreement.

Configuring WLS – Server Configuration

This is what I intend to be the first of a series of posts on configuring WLS. Configuration before installation is done via the initial.xml file, post-installation configuration changes are done via the registry; the names and basic structure remain the same.

The first and only required change to the initial.xml file is changing the “Network” section to match your environment. Also, only non-default settings need to be set; any missing settings will be set to defaults on start-up by WLS. The term Network was chosen instead of server since it defines a source network and where hosts that meet the definition should send their logs. Multiple networks can be defined, allowing for single configuration deployment across an enterprise and server redundancy in the event a server becomes unreachable for an extended period.

Global network settings

  • FailedSendTimeout: If ALL configured and qualified networks are out of range or connectivity attempts have failed, wait x seconds before retrying.
  • SendAsync: Use asynchronous sockets to send data
  • SocketTimeout: If no data has been sent for X seconds, close the socket

Per-instance network settings

  • The registry key name is how this will be referred to in the logs; name it appropriately.
  • AcceptInvalidCertificates: Allow expired, non matching domains, etc
  • ClientCertificate: Only applicable if UseSSL is enabled.
    • Blank: (default) No client certificate
    • UseLocal: Retrieve the client certificate from the local certifcate store
    • File path to use a certificate on disk
  • IPRange: The IP range that the local host’s IP address MUST fall within to use this “network”
    • Any – Any IPv4 or IPv6 address
    • – Any IPv4 address
    • ::/0 – Any IPv6 address
    • Valid CIDR
    • Min-max IP range
  • LogFormat
    • syslog (default)
    • json
  • Priority: If the hosts IP address falls into multiple ranges, this determines which order to try and use them. If multiple same priority networks qualify, alphabetical order is used.
  • Protocol
    • TCP (default)
    • UDP
  • ServerNameOrIP: The host name or ip address of the destination server
  • ServerPort: The port on the destination server
  • UseSSL: Use SSL when sending logs


Example 1

I run a local Splunk instance for testing and want my logs sent to it regardless of my IP address. I’ll set the IPRange to “Any” to allow any IPv4 or IPv6 source range and define the local server configuration. That’s it, all other values are defaults.


Example 2

I have a work laptop that when used internally, should log directly to the log server without encryption; if it’s taken off-network, it should use an externally visible log server with SSL.

Note: If the laptop obtains an IP in the range defined by “Inside” while off the work network, it will not send data unless the server is available and a connection succeeds; when that fails, it will use the next range – “Outside”.


What is WLS?

The Windows Logging Service (WLS) is a Windows service that forwards your event logs, along with user defined contextual data, to your log server.

Each process execution log is augmented with:

  • Creator process name
  • Command line parameters

and optionally:

  • Any file metadata (attributes, MAC times, version, size, etc)
  • Digital signature flag
  • Entropy
  • Environmental variables (per process)
  • Hashes (MD5, RIPEMD160, SHA1, SHA256, SHA384, SHA512)
  • Zone

WLS can also log the following information to your log server:

  • Certificates
  • Devices
  • Drives
  • File system changes – including file metadata
  • Listening and connected ports, with associated process information
  • Loaded modules – including file metadata
  • Mutexes, semaphores, and other Windows objects
  • Named pipes
  • Optical media used
  • Performance counters
  • Registry changes
  • WMI information

I’ll cover the details of each of these features and configuration examples in upcoming posts, as well as provide example Splunk searches I use for day-to-day operations.

If you’d like more information on WLS, send me a note via the contact form. WLS is currently available to US entities, but does require a signed license agreement.