background servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/labs... · web viewin this lab...

21
Hands-On Lab Background Services - .NET Lab version: 1.0.0 Last updated: 10/8/2009

Upload: others

Post on 09-Mar-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Hands-On LabBackground Services - .NET

Lab version: 1.0.0

Last updated: 10/8/2009

Page 2: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

CONTENTS

OVERVIEW................................................................................................................................................. 3

EXERCISE 1: TRIGGER-START SERVICE...............................................................................................7Task 1 – Implement Service Configuration Changes............................................................................7

Task 2 – Add Code to Register the Service as Trigger-Start...............................................................10

Task 3 – Enable the UsbCopyService to Trigger-Start........................................................................12

SUMMARY................................................................................................................................................ 18

2

Page 3: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

Overview

Windows 7 and Windows Vista have introduced many improvements in background processing. The modern challenges of implementing efficient background processes are:

Performance – boot latency, logon latency, shutdown latency; background work interfering with foreground processing

Power consumption

Security – increased attack surface

Windows 7 background services and scheduled tasks offer a variety of mechanisms for minimizing power consumption, reducing the system’s attack surface and improving application and system performance. Among these mechanisms are:

Service requested security privileges

Service SIDs

Delayed auto-start services

Trigger-start services

Scheduled tasks conditions and settings

With the abundance of services in any modern installation of Windows, background processing must be designed to meet security, performance and power consumption requirements.

Objectives

In this Hands-On Lab, you will learn how to:

Design and implement a trigger-start service

Minimize the amount of privileges requested by a service

System Requirements

You must have the following items to complete this lab:

Microsoft Visual Studio 2008

Windows 7

Windows 7 SDK

3

Page 4: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

Windows Sysinternals Process Explorer

Setup

This lab requires that the Windows 7 SDK is correctly integrated with Visual Studio 2008. To do this you can follow these steps:

1. From the Start Menu, go to All Programs | Microsoft Windows SDK v7.0 | Visual Studio Registration and click Windows SDK Configuration Tool. On the Windows SDK Configuration Tool dialog, verify that the v7.0 version is selected and then click Make Current.

Figure 1Windows SDK Configuration tool

2. You also need update Visual C++ directories to point to the Windows 7 SDK headers, libraries and tools. These paths should match your local Windows 7 SDK installation. To do this, from the Microsoft Visual Studio 2008 menu, select Tools | Options to open the Options dialog. Expand the Projects and Solutions node from the left panel, select VC++ Directories and follow these steps:

a. From the right panel, select Executable files from the combo located at the upper-right

corner. Then select the button, browse to the %Windows7SDKInstallDir%\v7.0\Bin folder and click Select Folder.

4

Page 5: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

Figure 2Configuring the VC++ directories

Note: Windows 7 SDK is installed by default under the C:\Program Files\Microsoft SDKs\Windows folder.

b. Repeat the previous step adding the %Windows7SDKInstallDir%\v7.0\Include folder for the Include files option, and the %Windows7SDKInstallDir%\v7.0\Lib folder for the Library Files option.

c. Finally, click OK to save the settings.

Additionally, this lab requires specific “hard coded” folders to work with that you need to create:

1. On the local C drive you need to create a C:\FromUSB folder to which all the images from the USB key will be copied.

2. On the generic USB key you need to create a ToCopy folder from which all the images will be copied from.

Note: The service demonstrated in this exercise is not well-designed with regard to the design goals for background processes on Windows. It is a just sample application showing how to use the Trigger Start Services in Windows 7. For more information on designing efficient background processes, consult the Microsoft whitepaper “Designing Efficient Background Processes”.

5

Page 6: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

6

Page 7: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

Exercise 1: Trigger-Start Service

In this exercise, you will modify an existing service to be a better citizen of the operating system. You will change the service’s requested security privileges to run with least privileges; and you will change the service configuration so that it automatically starts when necessary instead of running and polling the system in the background.

The sample service used for this purpose is a USB file copy service, which copies files from a specific directory on any USB storage device inserted to the system. The techniques used in this exercise are applicable to any service that can trigger-start when certain criteria are met.

Task 1 – Implement Service Configuration Changes

To modify service configuration programmatically, the Win32 API function ChangeServiceConfig2 must be called with the appropriate parameters.

1. Open the starting solution Begin.sln located under the %TrainingKitInstallDir%\BackgroundServices\Ex1-TriggerStartService\Begin folder, choosing the language of your preference (C# or VB).

Note: Visual Studio 2008 must be run in elevated mode. To do this, right-click the Visual Studio 2008 icon and select Run as Administrator.

2. In the ServiceControlInterop project, locate the ServiceControlInterop.cpp file, under the Source Files folder, and add code in the RemoveAllPrivilegesFromService method to specify that the service requires no privileges:

a. Allocate a SERVICE_REQUIRED_PRIVILEGES_INFO structure and set its pmszRequiredPrivileges member to SE_CHANGE_NOTIFY_NAME L"\0".

b. Call the ChangeServiceConfig2 method with the SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO information level and pass the address of the structure allocated in the previous step.

Use the following code as a complete example (shown in bold):

C++

void ServiceControl::RemoveAllPrivilegesFromService(System::String^ serviceName){ .... if (hService == NULL)

7

Page 8: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

{ DWORD dwLastError = GetLastError(); CloseServiceHandle(hSCManager); throw Marshal::GetExceptionForHR(dwLastError); }

//This effectively strips out all other privileges. SERVICE_REQUIRED_PRIVILEGES_INFO requiredPrivileges = {0}; requiredPrivileges.pmszRequiredPrivileges = SE_CHANGE_NOTIFY_NAME L"\0";

if (ChangeServiceConfig2(hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, &requiredPrivileges) == FALSE) { DWORD dwLastError = GetLastError(); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); throw Marshal::GetExceptionForHR(dwLastError); }

CloseServiceHandle(hService); CloseServiceHandle(hSCManager);}

3. In the SetServiceTriggerStartOnUSBArrival method, add code to set the service to trigger-start when a generic USB disk becomes available:

a. Allocate a SERVICE_TRIGGER_SPECIFIC_DATA_ITEM structure. To do this:

i. Set its dwDataType member to SERVICE_TRIGGER_DATA_TYPE_STRING.

ii. Set its cbData member to the length of the string L"USBSTOR\\GenDisk" in bytes.

iii. Set its pData member to that string.

b. Allocate a SERVICE_TRIGGER structure. To do this:

i. Set its dwTriggerType member to SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL.

ii. Set its dwAction member to SERVICE_TRIGGER_ACTION_SERVICE_START.

iii. Set its pTriggerSubtype member to the address of the GUID_USBDevice GUID.

iv. Set its cDataItems member to 1 and its pDataItems member to the address of the structure allocated in the previous step.

c. Allocate a SERVICE_TRIGGER_INFO structure. To do this:

8

Page 9: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

i. Set set its cTriggers member to 1 and its pTriggers member to the address of the structure allocated in the previous step.

d. Call the ChangeServiceConfig2 function with the SERVICE_CONFIG_TRIGGER_INFO information level and pass to it the address of the structure allocated in the previous step.

Use the following code as a complete example (shown in bold):

C++

void ServiceControl::SetServiceTriggerStartOnUSBArrival(System::String^ serviceName){ ... if (hService == NULL) { DWORD dwLastError = GetLastError(); CloseServiceHandle(hSCManager); throw Marshal::GetExceptionForHR(dwLastError); }

LPCWSTR lpszDeviceString = L"USBSTOR\\GenDisk";

SERVICE_TRIGGER_SPECIFIC_DATA_ITEM deviceData = {0}; deviceData.dwDataType = SERVICE_TRIGGER_DATA_TYPE_STRING; deviceData.cbData = (wcslen(lpszDeviceString)+1) * sizeof(WCHAR); deviceData.pData = (PBYTE)lpszDeviceString;

SERVICE_TRIGGER serviceTrigger = {0}; serviceTrigger.dwTriggerType = SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL; serviceTrigger.dwAction = SERVICE_TRIGGER_ACTION_SERVICE_START; serviceTrigger.pTriggerSubtype = (GUID*)&GUID_USBDevice; serviceTrigger.cDataItems = 1; serviceTrigger.pDataItems = &deviceData;

SERVICE_TRIGGER_INFO serviceTriggerInfo = {0}; serviceTriggerInfo.cTriggers = 1; serviceTriggerInfo.pTriggers = &serviceTrigger;

if (ChangeServiceConfig2(hService, SERVICE_CONFIG_TRIGGER_INFO, &serviceTriggerInfo) == FALSE) { DWORD dwLastError = GetLastError(); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); throw Marshal::GetExceptionForHR(dwLastError);

9

Page 10: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

}

CloseServiceHandle(hService); CloseServiceHandle(hSCManager);}

This completes the C++/CLI wrapper necessary for .NET interaction with the service trigger-start APIs.

Task 2 – Add Code to Register the Service as Trigger-Start

Services can be registered as trigger-start from the sc.exe command line utility (using the sc triggerinfo command from an elevated Command Shell), or using the ChangeServiceConfig2 API programmatically, which we wrapped as part of the previous task.

1. In the RegisterService project, locate the RegisterServiceForm.cs (C#) or RegisterServiceForm.vb (Visual Basic) code file and within it add code to the btnRegisterTriggerStart_Click method to change the service configuration to trigger-start using the C++/CLI wrapper, as follows (shown in bold):

C#

private void btnRegisterTriggerStart_Click(object sender, EventArgs e){ AddService();

ServiceControl.SetServiceTriggerStartOnUSBArrival(ServiceName);

StopLogReaderTimer(); StartLogReaderTimer();}

Visual Basic

Private Sub btnRegisterTriggerStart_Click() Handles btnRegisterTriggerStart.Click AddService()

ServiceControl.SetServiceTriggerStartOnUSBArrival(ServiceName)

StopLogReaderTimer() StartLogReaderTimer()End Sub

2. In the btnRemovePrivileges_Click method, add code to change the service configuration to request the minimum possible privileges using the C++/CLI wrapper, as follows:

10

Page 11: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

C#

private void btnRemovePrivileges_Click(object sender, EventArgs e){ ServiceControl.RemoveAllPrivilegesFromService(ServiceName);}

Visual Basic

Private Sub btnRemovePrivileges_Click() Handles btnRemovePrivileges.Click ServiceControl.RemoveAllPrivilegesFromService(ServiceName)End Sub

You have now completed the changes to the service registration UI application so that the service can be registered as a trigger-start service with the minimum amount of necessary privileges.

11

Page 12: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

Task 3 – Enable the UsbCopyService to Trigger-Start

Unlike auto-start services which typically poll for interesting events using periodic timers, trigger-start services act when a trigger starts them and then deactivate (stop) themselves when there is no more work to perform.

1. In the UsbCopyService project, locate and open the USBService.cs (C#) or USBService.vb (Visual Basic) code file.

2. (For Visual Basic users only) Add the ProcessTriggerStart method, which will be called when the service is configured to trigger-start.

Visual Basic

Private Sub ProcessTriggerStart() DoWork()End Sub

3. Modify the OnStart method to check whether the service is configured to trigger-start using the ServiceControl.IsServiceTriggerStart method (pass the ServiceName property inherited from the ServiceBase class as the parameter). To do this, replace the method implementation with the following code:

C#

protected override void OnStart(string[] args){ if (ServiceControl.IsServiceTriggerStart(ServiceName)) { } else { _timer = new Timer(delegate { DoWork(); }); _timer.Change(0, 5000); }}

Visual Basic

Protected Overrides Sub OnStart(ByVal args() As String) If ServiceControl.IsServiceTriggerStart(ServiceName) Then

Else _timer = New Timer(AddressOf ProcessTimerEvent) _timer.Change(0, 5000) End If

12

Page 13: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

End Sub

4. Now if the service is configured to trigger-start, instead of creating the periodic timer the method will enqueue the work to be performed only once. To do this, add the following code (shown in bold):

C#

protected override void OnStart(string[] args){ if (ServiceControl.IsServiceTriggerStart(ServiceName)) { ThreadPool.QueueUserWorkItem(delegate { DoWork(); }); } else { _timer = new Timer(delegate { DoWork(); }); _timer.Change(0, 5000); }}

Visual Basic

Protected Overrides Sub OnStart(ByVal args() As String) If ServiceControl.IsServiceTriggerStart(ServiceName) Then ThreadPool.QueueUserWorkItem(AddressOf ProcessTriggerStart) Else _timer = New Timer(AddressOf ProcessTimerEvent) _timer.Change(0, 5000) End IfEnd Sub

5. After completing the work, the service should stop using the Stop method inherited from the ServiceBase class. To do this, add the following code (shown in bold) to the OnStart method (C#) or to the ProcessTriggerStart method (Visual Basic):

C#

protected override void OnStart(string[] args){ if (ServiceControl.IsServiceTriggerStart(ServiceName))

13

Page 14: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

{ ThreadPool.QueueUserWorkItem(delegate { DoWork(); Stop(); }); } else { ... }}

Visual Basic

Private Sub ProcessTriggerStart() DoWork() Me.Stop()End Sub

6. You are now ready to test the service. Run the RegisterService project.

Note: The project should be run as administrator. You can do this either from the elevated Visual Studio instance or by running the executable elevated from the shell or command prompt.

7. Register the service as demand-start by clicking the Register Demand-Start button and start it by clicking the Start button. It will continuously poll for a USB device every 5 seconds. When a USB device with the ToCopy directory is detected, it will copy that directory’s contents to the C:\FromUSB directory.

Figure 3

14

Page 15: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

Registering the service as demand-start

8. Inspect the service’s access token by launching Sysinternals Process Explorer. Right-click on the UsbCopyService.exe process in the process tree, select Properties and switch to the Security tab. Under the service’s privilege list, many privileges are either enabled or just present (disabled).

Figure 4Inspecting service privileges

Note: Find the download link for Sysinternals Process Explorer (procexp.exe) in the Prerequisites section of this hands-on lab.

15

Page 16: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

9. Stop the service using the Stop button.

10. Remove privileges from the service by clicking the Remove Privileges button.

11. Start the service by clicking the Start button and inspect its access token again using Sysinternals Process Explorer. The service’s privilege list should now contain only the SeChangeNotifyPrivilege (which is always retained for application compatibility purposes).

Figure 5Service privileges (after removing privileges)

12. Stop the service using the Stop button and delete it using the Delete button.

13. Remove the USB Device from the computer.

14. Register the service as trigger-start by clicking the Register Trigger-Start button. Do not start the service manually.

16

Page 17: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

15. Inspect the service’s trigger-start configuration by running the following command from an elevated command prompt.

Command

sc qtriggerinfo UsbCopyService

Figure 6Inspecting service's trigger-start configuration

16. Insert a USB device with a ToCopy directory. The service should automatically start, copy the files and then shut itself down.

17. You can verify that the service is down by running the following command from an elevated command prompt.

Command

sc queryex UsbCopyService

Figure 7Verifying service is down

17

Page 18: Background Servicesaz12722.vo.msecnd.net/windows7trainingcourse1-0/Labs... · Web viewIn this lab you have improved the performance and security of a Windows service to become a better

Background Services

18. When done, delete the service by clicking the Delete button.

19. You can ensure that the service has been deleted by running the same previous command from an elevated command prompt.

Command

sc queryex UsbCopyService

Figure 8Verifying service has been deleted

In this exercise, you have modified an existing service to trigger-start when a USB device is detected in the system. You have also modified the service’s requested privilege list to the minimum necessary amount of privileges, thus reducing the system’s attack surface. The full exercise solution can be found in the %TrainingKitInstallDir%\BackgroundServices\Ex1-TriggerStartService\End directory, depending on the language of your preference.

Summary

In this lab you have improved the performance and security of a Windows service to become a better citizen of the operating system. You used the trigger-start service mechanism to launch the service only when there is actual work for it to perform, and you have minimized the service’s attack surface by removing unnecessary privileges from its process’ token.

You can find a full demo of the USB copy service and the Weather Updater service as part of this Windows 7 course’s code samples.

18