|
In the whitepaper Launch your application from session 0 to session 1 using a service helper application” an application was launched by the service which had the privileges of the local system account. The advantage of such an approach was the ability to use an UI to perform high privilege tasks across any user account. It also facilitated writing to the HKLM section of the registry which could be read across all user accounts. This can also be done by designing an application which can communicate with a service through RPC to achieve the desired result.
|
|
Title: Using a task schedular to run administrative tasks on demand.
|
|
OS: Microsoft Vista
|
Language: VC++
|
|
Introduction
|
|
In the whitepaper Launch your application from session 0 to session 1 using a
service helper application” an application was launched by the service which had
the privileges of the local system account. The advantage of such an approach was
the ability to use an UI to perform high privilege tasks across any user account. It
also facilitated writing to the HKLM section of the registry which could be read
across all user accounts. This can also be done by designing an application which
can communicate with a service through RPC to achieve the desired result.
This article focuses on the Administrator account of Vista for administrative
applications. It shows how to launch an application into session 1 under the
Administrator role with full privileges effectively bypassing the UAC prompt.
Windows tasks scheduler is used for this purpose. The approach may be useful for
some automated tasks which need to run under the administrator account.
The article will be expanded further to show how RPC can be implemented
effectively to run administrative applications.
|
|
Background
|
|
The concept used is very straightforward. A normal user mode application is
developed which communicates with a service through custom messages. On
receiving the custom message, the service will register a task in the task scheduler.
Depending on the attributes assigned, the task is run on demand with the highest
privileges of that account. At the end the task is deleted from the task scheduler.
|
|
Using the code
|
|
First let us review the file CustomMessageSender.cpp. This is the user-mode
application which communicates with the service. This application can be any
normal application without any special privileges.
|
#define SERVICE_NAME _T ("CustomSvc" )
#defineSERVICE_CONTROL_CUSTOM_MESSAGE 0x0085
int _tmain(int argc, _TCHAR* argv[])
{
SC_HANDLE hMyService,hSCM;
|
BOOL bSuccess;
SERVICE_STATUS status;
hSCM = OpenSCManager(0,0,SC_MANAGER_CONNECT);
if(!hSCM)
{
printf("Open SCM failed with error %u",GetLastError());
}
hMyService =
OpenService(hSCM,SERVICE_NAME,SERVICE_USER_DEFINED_CONTROL);
if(!hMyService)
{
printf("Open SCM failed with error %u",GetLastError());
}
bSuccess =
ControlService(hMyService,SERVICE_CONTROL_CUSTOM_MESSAGE,&status);
if(!bSuccess)
{
printf("Control Service failed with error %u",GetLastError());
}
CloseServiceHandle(hMyService);
CloseServiceHandle(hSCM);
return 0;
}
|
|
The code above is very simple and straightforward.
SERVICE_USER_DEFINED_CONTROL and SC_MANAGER_CONNECT access
permission is used because any user mode applications can connect to the service
to send custom messages to it. No admin privileges are required. So this application
sends the SERVICE_CONTROL_CUSTOM_MESSAGE to the service. Once the
message is sent to the service it will register a task under the current user account
which can be run at normal or highest privileges under that account.
|
|
Most of the code for registering the task in the task scheduler is taking from the
Windows Whitepaper on UAC. I have added a section on the IPrincipal interface to
set the highest privileges attribute.
The code snippet shows that first COM and its security attributes are initialized.
Then we create an instance of the Task Service.
|
{
// ------------------------------------------------------
// Initialize COM.
LPCWSTR wszTaskName = L"Dizyatec Task";
wstring wstrExecutablePath = L"C:\\SessionLauncher\\debug\\a.exe";
// Create an instance of the Task Service.
ITaskService *pService = NULL;
hr = CoCreateInstance( CLSID_TaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
(void**)&pService );
if (FAILED(hr))
{
printf("Failed to CoCreate an instance of the TaskService class:%x"
, hr);
CoUninitialize();
return 1;
}
|
Once the task service is initialized, we connect to the service and perform the
following steps:
1) Get a pointer to the tasks root folder
2) Use the ITaskDefinition interface to create a new task definition
3) Register the trigger
4) Define the action to be executed.
|
|
These are the general steps to be followed. Once this is done we need to get a
interface pointer to the IPrincipal interface and define the runLevel which is
TASK_RUNLEVEL_HIGHEST. The Code snippet below shows the same:
|
IPrincipal *pPrincipal = NULL;
hr = pTask->get_Principal(&pPrincipal);
if( FAILED(hr) )
{
printf("\nPointer to principal: %x", hr );
CLEANUP
return 1;
}
printf("\nDone : %x" ), hr;
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
printf("\nDone : %x", hr );
if( FAILED(hr) )
{
printf(nCould not get principal : %x", hr );
CLEANUP
return 1;
}
pPrincipal->Release();
// ------------------------------------------------------
|
|
Once this done we save the task in the root folder to run under the current user
account.
|
// Save the task in the root folder.
IRegisteredTask *pRegisteredTask = NULL;
hr = pRootFolder->RegisterTaskDefinition(
_bstr_t( wszTaskName ),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(_bstr_t( L"S-1-5-32-545")),
//Well Known SID for \\Builtin\Users group
_variant_t(),
TASK_LOGON_GROUP,
_variant_t(L""),
&pRegisteredTask);
if( FAILED(hr) )
{
printf("\nError saving the Task : %x", hr );
CLEANUP
return1;
}
printf("\n Success! Task successfully registered. " );
|
|
The task is then started, run and deleted.
|
This is all needed to run the task under the administrative account under highest privileges.
|
|
I will be further extending this article to demonstrate an example of the service
broker model where the a normal user application communicates with a service
through RPC, which is one of the methods recommended by Microsoft to run
administrative applications.
|
Click Here to download source code
|
|
About the Author
|
|
R.Jaisvar,Technical Consultant
|
|
Dizyatec Solutions
|