Wie nicht erhöht in Vista (.NET) laufen
-
10-07-2019 - |
Frage
Ich habe eine Anwendung, die ich als Administrator ausgeführt haben.
Ein kleiner Teil dieser Anwendung ist andere Anwendungen mit Process.Start starten
Die gestarteten Anwendungen werden auch als Administratoren ausgeführt werden, aber ich würde lieber sieht sie als der ‚normale‘ Benutzer ausgeführt werden.
Wie kann ich das erreichen?
/ johan /
Lösung
Der Prozess des WinSafer API ermöglichen, als ein begrenzter, normal oder erhöhter Benutzer gestartet werden.
Beispiel Verbrauch:
CreateSaferProcess(@"calc.exe", "", SaferLevel.NormalUser);
Der Quellcode:
//http://odetocode.com/Blogs/scott/archive/2004/10/28/602.aspx
public static void CreateSaferProcess(String fileName, String arguments, SaferLevel saferLevel)
{
IntPtr saferLevelHandle = IntPtr.Zero;
//Create a SaferLevel handle to match what was requested
if (!WinSafer.SaferCreateLevel(
SaferLevelScope.User,
saferLevel,
SaferOpen.Open,
out saferLevelHandle,
IntPtr.Zero))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try
{
//Generate the access token to use, based on the safer level handle.
IntPtr hToken = IntPtr.Zero;
if (!WinSafer.SaferComputeTokenFromLevel(
saferLevelHandle, // SAFER Level handle
IntPtr.Zero, // NULL is current thread token.
out hToken, // Target token
SaferTokenBehaviour.Default, // No flags
IntPtr.Zero)) // Reserved
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try
{
//Now that we have a security token, we can lauch the process
//using the standard CreateProcessAsUser API
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = String.Empty;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
// Spin up the new process
Boolean bResult = Windows.CreateProcessAsUser(
hToken,
fileName,
arguments,
IntPtr.Zero, //process attributes
IntPtr.Zero, //thread attributes
false, //inherit handles
0, //CREATE_NEW_CONSOLE
IntPtr.Zero, //environment
null, //current directory
ref si, //startup info
out pi); //process info
if (!bResult)
throw new Win32Exception(Marshal.GetLastWin32Error());
if (pi.hProcess != IntPtr.Zero)
Windows.CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
Windows.CloseHandle(pi.hThread);
}
finally
{
if (hToken != IntPtr.Zero)
Windows.CloseHandle(hToken);
}
}
finally
{
WinSafer.SaferCloseLevel(saferLevelHandle);
}
}
P / Invoke Erklärungen:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace PInvoke
{
public class WinSafer
{
/// <summary>
/// The SaferCreateLevel function opens a SAFER_LEVEL_HANDLE.
/// </summary>
/// <param name="scopeId">The scope of the level to be created.</param>
/// <param name="levelId">The level of the handle to be opened.</param>
/// <param name="openFlags">Must be SaferOpenFlags.Open</param>
/// <param name="levelHandle">The returned SAFER_LEVEL_HANDLE. When you have finished using the handle, release it by calling the SaferCloseLevel function.</param>
/// <param name="reserved">This parameter is reserved for future use. IntPtr.Zero</param>
/// <returns></returns>
[DllImport("advapi32", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool SaferCreateLevel(SaferLevelScope scopeId, SaferLevel levelId, SaferOpen openFlags,
out IntPtr levelHandle, IntPtr reserved);
/// <summary>
/// The SaferComputeTokenFromLevel function restricts a token using restrictions specified by a SAFER_LEVEL_HANDLE.
/// </summary>
/// <param name="levelHandle">SAFER_LEVEL_HANDLE that contains the restrictions to place on the input token. Do not pass handles with a LevelId of SAFER_LEVELID_FULLYTRUSTED or SAFER_LEVELID_DISALLOWED to this function. This is because SAFER_LEVELID_FULLYTRUSTED is unrestricted and SAFER_LEVELID_DISALLOWED does not contain a token.</param>
/// <param name="inAccessToken">Token to be restricted. If this parameter is NULL, the token of the current thread will be used. If the current thread does not contain a token, the token of the current process is used.</param>
/// <param name="outAccessToken">The resulting restricted token.</param>
/// <param name="flags">Specifies the behavior of the method.</param>
/// <param name="lpReserved">Reserved for future use. This parameter should be set to IntPtr.EmptyParam.</param>
/// <returns></returns>
[DllImport("advapi32", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool SaferComputeTokenFromLevel(IntPtr levelHandle, IntPtr inAccessToken,
out IntPtr outAccessToken, SaferTokenBehaviour flags, IntPtr lpReserved);
/// <summary>
/// The SaferCloseLevel function closes a SAFER_LEVEL_HANDLE that was opened by using the SaferIdentifyLevel function or the SaferCreateLevel function.</summary>
/// <param name="levelHandle">The SAFER_LEVEL_HANDLE to be closed.</param>
/// <returns>TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastWin32Error.</returns>
[DllImport("advapi32", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool SaferCloseLevel(IntPtr levelHandle);
} //class WinSafer
/// <summary>
/// Specifies the behaviour of the SaferComputeTokenFromLevel method
/// </summary>
public enum SaferTokenBehaviour : uint
{
/// <summary></summary>
Default = 0x0,
/// <summary>If the OutAccessToken parameter is not more restrictive than the InAccessToken parameter, the OutAccessToken parameter returns NULL.</summary>
NullIfEqual = 0x1,
/// <summary></summary>
CompareOnly = 0x2,
/// <summary></summary>
MakeInert = 0x4,
/// <summary></summary>
WantFlags = 0x8
}
/// <summary>
/// The level of the handle to be opened.
/// </summary>
public enum SaferLevel : uint
{
/// <summary>Software will not run, regardless of the user rights of the user.</summary>
Disallowed = 0,
/// <summary>Allows programs to execute with access only to resources granted to open well-known groups, blocking access to Administrator and Power User privileges and personally granted rights.</summary>
Untrusted = 0x1000,
/// <summary>Software cannot access certain resources, such as cryptographic keys and credentials, regardless of the user rights of the user.</summary>
Constrained = 0x10000,
/// <summary>Allows programs to execute as a user that does not have Administrator or Power User user rights. Software can access resources accessible by normal users.</summary>
NormalUser = 0x20000,
/// <summary>Software user rights are determined by the user rights of the user.</summary>
FullyTrusted = 0x40000
}
/// <summary>
/// The scope of the level to be created.
/// </summary>
public enum SaferLevelScope : uint
{
/// <summary>The created level is scoped by computer.</summary>
Machine = 1,
/// <summary>The created level is scoped by user.</summary>
User = 2
}
public enum SaferOpen : uint
{
Open = 1
}
} //namespace PInvoke
Andere Tipps
Von: http://go.microsoft.com/fwlink/?LinkId=81232
Eine häufig gestellte Frage ist, wie man startet einen nicht erhöhten Anwendung von ein erhöhter Prozess oder mehr im Grunde, wie ich starte eine Prozess meines un-erhöhte Token sobald ich renne erhöht. Schon seit gibt es keine direkte Möglichkeit, dies zu tun, die Situation kann in der Regel vermieden werden durch Start der ursprünglichen Anwendung als Standardbenutzer und nur diejenigen, erhebend Abschnitte der Anwendung, die erfordern Administratorrechte. Diese Art und Weise gibt es immer ein nicht-erhöhen Verfahren, die verwendet werden können, um zu starten zusätzliche Anwendungen wie die aktuell Desktop-Benutzer angemeldet. Manchmal jedoch eine erhöhte Prozess muss ein anderes erhalten Anwendung ausgeführt un-erhöht. Diese kann unter Verwendung der Aufgabe erreicht werden Scheduler in Windows Vista. Das erhöhter Prozess kann eine Aufgabe registrieren zu laufen wie das aktuell angemeldet Desktop-Benutzer.
Hier ist ein Beispiel dafür, wie das unver erhöhten Prozess zu planen (wieder aus dem gleichen Link)
//---------------------------------------------------------------------
// This file is part of the Microsoft .NET Framework SDK Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation. See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------
/****************************************************************************
* Main.cpp - Sample application for Task Scheduler V2 COMAPI * Component: Task Scheduler
* Copyright (c) 2002 - 2003, Microsoft Corporation
* This sample creates a task to that launches as the currently logged on deskup user. The task launches as soon as it is registered. *
****************************************************************************/
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <comdef.h>
#include <comutil.h>
//Include Task header files - Included in Windows Vista Beta-2 SDK from MSDN
#include <taskschd.h>
#include <conio.h>
#include <iostream>
#include <time.h>
using namespace std;
#define CLEANUP \
pRootFolder->Release();\
pTask->Release();\
CoUninitialize();
HRESULT CreateMyTask(LPCWSTR, wstring);
void __cdecl wmain(int argc, wchar_t** argv)
{
wstring wstrExecutablePath;
WCHAR taskName[20];
HRESULT result;
if( argc < 2 )
{
printf("\nUsage: LaunchApp yourapp.exe" );
return;
}
// Pick random number for task name
srand((unsigned int) time(NULL));
wsprintf((LPWSTR)taskName, L"Launch %d", rand());
wstrExecutablePath = argv[1];
result = CreateMyTask(taskName, wstrExecutablePath);
printf("\nReturn status:%d\n", result);
}
HRESULT CreateMyTask(LPCWSTR wszTaskName, wstring wstrExecutablePath)
{
// ------------------------------------------------------
// Initialize COM.
TASK_STATE taskState;
int i;
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if( FAILED(hr) )
{
printf("\nCoInitializeEx failed: %x", hr );
return 1;
}
// Set general COM security levels.
hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
0,
NULL);
if( FAILED(hr) )
{
printf("\nCoInitializeSecurity failed: %x", hr );
CoUninitialize();
return 1;
}
// ------------------------------------------------------
// 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;
}
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if( FAILED(hr) )
{
printf("ITaskService::Connect failed: %x", hr );
pService->Release();
CoUninitialize();
return 1;
}
// ------------------------------------------------------
// Get the pointer to the root task folder. This folder will hold the
// new task that is registered.
ITaskFolder *pRootFolder = NULL;
hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );
if( FAILED(hr) )
{
printf("Cannot get Root Folder pointer: %x", hr );
pService->Release();
CoUninitialize();
return 1;
}
// Check if the same task already exists. If the same task exists, remove it.
hr = pRootFolder->DeleteTask( _bstr_t( wszTaskName), 0 );
// Create the task builder object to create the task.
ITaskDefinition *pTask = NULL;
hr = pService->NewTask( 0, &pTask );
pService->Release(); // COM clean up. Pointer is no longer used.
if (FAILED(hr))
{
printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
pRootFolder->Release();
CoUninitialize();
return 1;
}
// ------------------------------------------------------
// Get the trigger collection to insert the registration trigger.
ITriggerCollection *pTriggerCollection = NULL;
hr = pTask->get_Triggers( &pTriggerCollection );
if( FAILED(hr) )
{
printf("\nCannot get trigger collection: %x", hr );
CLEANUP
return 1;
}
// Add the registration trigger to the task.
ITrigger *pTrigger = NULL;
hr = pTriggerCollection->Create( TASK_TRIGGER_REGISTRATION, &pTrigger );
pTriggerCollection->Release(); // COM clean up. Pointer is no longer used.
if( FAILED(hr) )
{
printf("\nCannot add registration trigger to the Task %x", hr );
CLEANUP
return 1;
}
pTrigger->Release();
// ------------------------------------------------------
// Add an Action to the task.
IExecAction *pExecAction = NULL;
IActionCollection *pActionCollection = NULL;
// Get the task action collection pointer.
hr = pTask->get_Actions( &pActionCollection );
if( FAILED(hr) )
{
printf("\nCannot get Task collection pointer: %x", hr );
CLEANUP
return 1;
}
// Create the action, specifying that it is an executable action.
IAction *pAction = NULL;
hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction );
pActionCollection->Release(); // COM clean up. Pointer is no longer used.
if( FAILED(hr) )
{
printf("\npActionCollection->Create failed: %x", hr );
CLEANUP
return 1;
}
hr = pAction->QueryInterface( IID_IExecAction, (void**) &pExecAction );
pAction->Release();
if( FAILED(hr) )
{
printf("\npAction->QueryInterface failed: %x", hr );
CLEANUP
return 1;
}
// Set the path of the executable to the user supplied executable.
hr = pExecAction->put_Path( _bstr_t( wstrExecutablePath.c_str() ) );
if( FAILED(hr) )
{
printf("\nCannot set path of executable: %x", hr );
pExecAction->Release();
CLEANUP
return 1;
}
hr = pExecAction->put_Arguments( _bstr_t( L"" ) );
if( FAILED(hr) )
{
printf("\nCannot set arguments of executable: %x", hr );
pExecAction->Release();
CLEANUP
return 1;
}
// ------------------------------------------------------
// Save the task in the root folder.
IRegisteredTask *pRegisteredTask = NULL;
hr = pRootFolder->RegisterTaskDefinition(
_bstr_t( wszTaskName ),
pTask,
TASK_CREATE,
_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
return 1;
}
printf("\n Success! Task successfully registered. " );
for (i=0; i<100; i++)//give 10 seconds for the task to start
{
pRegisteredTask->get_State(&taskState);
if (taskState == TASK_STATE_RUNNING)
{
printf("\nTask is running\n");
break;
}
Sleep(100);
}
if (i>= 100) printf("Task didn't start\n");
//Delete the task when done
hr = pRootFolder->DeleteTask(
_bstr_t( wszTaskName ),
NULL);
if( FAILED(hr) )
{
printf("\nError deleting the Task : %x", hr );
CLEANUP
return 1;
}
printf("\n Success! Task successfully deleted. " );
// Clean up.
CLEANUP
CoUninitialize();
return 0;
}
Ich hatte die gleiche Anforderung und ich komme zu der Lösung den Taskplaner-Dienst von Windows zu verwenden.
Also, zuerst der Task Scheduler Managed Wrapper