Lockdown is not just about lockdown
Posted By J.T. Kimbell
Program Manager
This is the last entry in this week’s series about the lockdown features found in Windows Embedded Standard 8. In this post Brendan Rempel goes into more depth about how to manage your lockdown features. Brendan is a Software Development Engineer who works on a variety of Windows Embedded device lockdown features. Outside of Embedded, Brendan spends all remaining time with his family, fueling two boys’ obsessions with loud toys, especially the Washington State’s steam trains and model rockets.
But before Brendan gets into the meat of this article, he’s got a story to share.
A while back I had nifty a car alarm. It had all the typical features for preventing theft and even had an engine starter. But the best part was the remote. It had a little picture of a car and realistic LCD indicators to represent its state. I could press a button to see if the doors were locked and lock them if they weren’t. It could tell me if the engine was started correctly. It would also beep loudly if someone tried to break in. Best of all, it had a ¼ mile range and worked even when in deep underground parking. While it didn’t stop break-in attempts, I was able to respond fast when someone did and never worried about the car being secure.
Windows Embedded Standard 8 introduces many new and improved features related to securing devices and maintaining their primary purpose. We’ve also added consistent user interface through the MMC and a consistent set of WMI providers for easy scripting. This was all meant to help administrators manage devices, regardless of how that’s done.
Using history as our teacher, we learned that many Lockdown related problems in devices go undetected. It’s easy to remember being at an airport, freeway, or game and see a digital sign showing a Windows error message or logon screen. This is as embarrassing to us as it is for the person who made the device, but often only the public knows when this happens. This is why we’ve done our best to stop these problems, but we’ve added several new features to help administrators detect when problems sneak through and record when we succeed.
All our features use the Event Tracing for Windows (ETW) to report problems in their typical scenarios. This includes:
- Dialog Filter reports dialogs that appear, are closed by it, or are allowed to show. It also logs the contents of the window and contains enough information to block the window. Even if a dialog is never visible because it was closed automatically, it could represent a problem that has to be fixed, such as an application error. A window can also be blocked by using the information logged.
- Keyboard Filter reports logging in/out, locking/unlocking the console. Logging out is necessary for servicing, but if a device logs out and doesn’t come back after 10 minutes, what’s wrong?
- Shell Launcher reports when it starts the shell. This must occur one time after logon, but if it’s occurring frequently, is the application crashing?
- Unified Write Filter reports when memory is running low. This is caused by lots of file changes, but a good kiosk shouldn’t store that much information locally. Is someone making a lot of changes they shouldn’t?
Administrators can use the Event Viewer to see these events. You can do this locally if MMC and Event Viewer Snap-In is installed, or remote if the firewall ports are opened. It can also be obtained locally in code by using .NET or Power Shell. For my examples, I’ve used class libraries built into .NET 2.0 and later versions.
Determining Health
An administrator may want to know what dialogs are currentlybeing closed by the Dialog Filter. In a perfect world, it would be none because there should be no errors, no popup dialogs, no way to get unintended applications from appearing. So, it should be reasonable to prove if this is true. Using .NET, a program run locally can figure this out:
1: static void Main(string[] args)
2: {
3: string eventChannel = "Microsoft-Windows-DialogFilter/Operational";
4:
5: EventLogQuery eventsQuery = new EventLogQuery(eventChannel, PathType.LogName, "Event/System/EventID=20012");
6: EventLogReader logReader = new EventLogReader(eventsQuery);
7:
8: for (EventRecord record = logReader.ReadEvent(); record != null; record = logReader.ReadEvent())
9: {
10: Console.WriteLine("ID={0} Level={1} Time={2} ", record.Id, record.LevelDisplayName, record.TimeCreated.ToString());
11:
12: if (record.Properties.Count == 5)
13: {
14: Console.WriteLine("Process={0}”, record.Properties[0].Value.ToString());
15: Console.WriteLine("Title={0}”, record.Properties[1].Value.ToString());
16: Console.WriteLine("Action={0}”, record.Properties[2].Value.ToString());
17: Console.WriteLine("Content={0}”, record.Properties[3].Value.ToString());
18: Console.WriteLine("Actions={0}”, record.Properties[4].Value.ToString());
19: }
20: }
21: }
What this gives us is a list of all dialogs that were closed by the default action. The eventChannel and EventID are obtained from an event in the Event Viewer and can be changed to any valid log.
We can then expand this to other events as well, such as logging on and off, low memory conditions, or anything that could disrupt our devices. With this information, you can look for common problems, new problems, or even break in attempts to learn and improve the security and stability of your devices without having to see or watch them.
Notification
The last thing we want is a dialog visible for a long period of time, or be stuck on a logon screen. Instead, we want problems exposed and fixed as fast as possible. The ETW can help, but it takes some tricks to get working. For information about how to integrate ETW events to Power Shell, see this excellent blog entry from Otto Helweg.
You’ll need to follow the steps defined in this blog and added additional steps specific to using .NET and Lockdown features. For this, you’ll need a Windows Embedded 8 test device with Dialog Filter, Event Viewer, and Task Scheduler installed and running. The steps required are:
- Create a trigger event. Using the Event Viewer, browse to Applications and Services, Microsoft, Windows, DialogFilter, Operational. Operational log is disabled by default so you’ll have to enable it. Find an event, such as the 20012 (closed by default action) or 20010 (closed by performing an action).
- Attach a task to this event as the notification application you’ll write. The TechNet blog uses PowerShell, my example is a .NET application. Set the arguments to –eventRecordID $(eventRecordID) –eventChannel $(eventChannel)
- Modify the task to pass details about the trigger event. The Event Viewer UI doesn’t do everything, you’ll need to export the new trigger to XML, hand edit, and reimport. Follow the TechNet blog’s instructions. Reimporting is done with command line and doesn’t require MMC, so you can import this new trigger on all machines even if they don’t have administrative tools like MMC installed.
- Implement the trigger program.
How this trigger program works is up to you, but it’s going to receive two command line parameters it must parse: -eventRecordID and –eventChannel. Event Record ID is the log entry that just happened and Event Channel is the log itself. You already know the Event Channel, but keeping it data-driven means that you can recycle this application for other events, not only other Lockdown features, but any log on Windows. Event Record ID will get you the log entry which you can use to obtain the Window’s content.
1: eventChannel = <value of –eventChannel parameter>
2: eventRecordID = <value of –eventRecordID parameter>
3:
4: EventLogQuery eventsQuery = new EventLogQuery(eventChannel, PathType.LogName, "Event/System/EventRecordID=" + eventRecordID.ToString());
5: EventLogReader logReader = new EventLogReader(eventsQuery);
6:
7: for (EventRecord record = logReader.ReadEvent(); record != null; record = logReader.ReadEvent())
8: {
9: if (record.Properties.Count == 5)
10: {
11: Console.WriteLine("Process={0}”, record.Properties[0].Value.ToString());
12: Console.WriteLine("Title={0}”, record.Properties[1].Value.ToString());
13: Console.WriteLine("Action={0}”, record.Properties[2].Value.ToString());
14: Console.WriteLine("Content={0}”, record.Properties[3].Value.ToString());
15: Console.WriteLine("Actions={0}”, record.Properties[4].Value.ToString());
16: }
17: }
This will execute every time a window appears. From my experiments, it might be useful to:
- Make this executable a windowed program with no window. A console program may become visible and may get blocked causing annoying recursion. Think of this as a WinForms program but all the forms are deleted from the project. It’s better to be invisible.
- Not rely on the content of Properties and find a generic way of transmitting them. The EventRecord only knows what each property value is, not what it represents. Code elsewhere needs to align events with their properties.
Where to go from here
We really wanted our new Lockdown tools to not just add some settings to help make devices more secure but also enable you to make sure they are secure and available to your customers. How you capture and present this information is up to you, but there are lots of options.
- Upload messages to a web service or cloud service as issues occur and send alerts to your smartphone
- Build reports that show trends and respond to them before they become widespread
- Monitor state. A web service can be notified that a system has logged off and transmit notification to IT if it doesn’t log back on and start the appropriate shell within a couple minutes