Related
This question already has an answer here:
When calling Windows API functions from C#, which source for signatures to trust: .NET Framework source code or PInvoke?
(1 answer)
Closed 6 months ago.
I'm trying to change user name and password of a Windows service in C# via WinAPI calls. I have created the service myself using WinAPI's CreateService(), based off of the code in this Stack Overflow answer.
If I use the same credentials in a call to ChangeServiceConfigA(), I'm told that user name and password are incorrect. I can change everything else with ChangeServiceConfigA(), even the password, but once I try to set user name and password, I get said error.
My code looks like this:
private const uint SERVICE_NO_CHANGE = 0xffffffff;
[Flags]
private enum ServiceAccessRights
{
QueryConfig = 0x1,
ChangeConfig = 0x2,
QueryStatus = 0x4,
EnumerateDependants = 0x8,
Start = 0x10,
Stop = 0x20,
PauseContinue = 0x40,
Interrogate = 0x80,
UserDefinedControl = 0x100,
Delete = 0x00010000,
StandardRightsRequired = 0xF0000,
AllAccess = StandardRightsRequired | QueryConfig | ChangeConfig |
QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
Interrogate | UserDefinedControl
}
private enum ServiceBootFlag : UInt32
{
Start = 0x00000000,
SystemStart = 0x00000001,
AutoStart = 0x00000002,
DemandStart = 0x00000003,
Disabled = 0x00000004,
ServiceNoChange = SERVICE_NO_CHANGE
}
private enum ServiceError : UInt32
{
Ignore = 0x00000000,
Normal = 0x00000001,
Severe = 0x00000002,
Critical = 0x00000003,
ServiceNoChange = SERVICE_NO_CHANGE
}
private enum ServiceType : UInt32
{
ServiceFileSystemDriver = 0x00000002,
ServiceKernelDrvier = 0x00000001,
ServiceWin32OwnProcess = 0x00000010,
ServiveWin32ShareProcess = 0x00000020,
ServiceNoChange = SERVICE_NO_CHANGE
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ChangeServiceConfigA(IntPtr hService, ServiceType dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName);
public static bool ChangeService(string serviceName, string? userName, string? password)
{
IntPtr scm = OpenSCManager(ScmAccessRights.Connect);
try
{
IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.ChangeConfig);
if (service == IntPtr.Zero)
return false;
if (!ChangeServiceConfigA(service,
ServiceType.ServiceNoChange,
ServiceBootFlag.ServiceNoChange,
ServiceError.ServiceNoChange,
null, null, IntPtr.Zero, null,
userName, password, null))
throw new ApplicationException(":( sadface");
CloseServiceHandle(service);
return true;
}
finally
{
CloseServiceHandle(scm);
}
}
Argh, I found the answer by accident when doing the other WinAPI thing I meant to do:
QueryServiceConfigA() uses ANSI strings (while QueryServiceConfigW() uses Unicode), but most importanly, QueryServiceConfig() is an alias that automatically chooses the right one.
Declared like this, it works like a charm:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ChangeServiceConfig(IntPtr hService, ServiceType dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName);
My code is working but I need the simplified code and it's not working for the Authenticated Users group. Any other ways to calculate effective permissions?
Is there an API in .NET for getting effective folder permissions for a specific user? I know how get permissions by using DirectorySecurity.GetAccessRules(). But in this case I should manually analyze all permissions for user, permissions for groups, that include the user, inherited permissions and user permission for folder.
Is there a function in the Windows API that can return these permissions via platform invoke?
namespace DemoProject1
{
class Program
{
static Dictionary<String, String> rightsmap = new Dictionary<String, String>();
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint GetEffectiveRightsFromAcl(IntPtr pDacl, ref TRUSTEE pTrustee, ref ACCESS_MASK pAccessRights);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
struct TRUSTEE
{
IntPtr pMultipleTrustee; // must be null
public int MultipleTrusteeOperation;
public TRUSTEE_FORM TrusteeForm;
public TRUSTEE_TYPE TrusteeType;
[MarshalAs(UnmanagedType.LPStr)]
public string ptstrName;
}
enum TRUSTEE_FORM
{
TRUSTEE_IS_SID,
TRUSTEE_IS_NAME,
TRUSTEE_BAD_FORM,
TRUSTEE_IS_OBJECTS_AND_SID,
TRUSTEE_IS_OBJECTS_AND_NAME
}
enum TRUSTEE_TYPE
{
TRUSTEE_IS_UNKNOWN,
TRUSTEE_IS_USER,
TRUSTEE_IS_GROUP,
TRUSTEE_IS_DOMAIN,
TRUSTEE_IS_ALIAS,
TRUSTEE_IS_WELL_KNOWN_GROUP,
TRUSTEE_IS_DELETED,
TRUSTEE_IS_INVALID,
TRUSTEE_IS_COMPUTER
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
static extern uint GetNamedSecurityInfo(
string pObjectName,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
out IntPtr pSidOwner,
out IntPtr pSidGroup,
out IntPtr pDacl,
out IntPtr pSacl,
out IntPtr pSecurityDescriptor);
enum ACCESS_MASK : uint
{
FILE_TRAVERSE = 0x20,
FILE_LIST_DIRECTORY = 0x1,
FILE_READ_DATA = 0x1,
FILE_READ_ATTRIBUTES = 0x80,
FILE_READ_EA = 0x8,
FILE_ADD_FILE = 0x2,
FILE_WRITE_DATA = 0x2,
FILE_ADD_SUBDIRECTORY = 0x4,
FILE_APPEND_DATA = 0x4,
FILE_WRITE_ATTRIBUTES = 0x100,
FILE_WRITE_EA=0x10,
FILE_DELETE_CHILD = 0x40,
DELETE = 0x10000,
READ_CONTROL = 0x20000,
WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000,
////////FILE_EXECUTE =0x20,
}
[Flags]
enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY
}
static void Main(string[] args)
{
//String UserName = "NT Authority\\Authenticated Users";
String UserName = "TEST-INC-34\\Test1";
String Path = "E:\\f1";
IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
ACCESS_MASK mask = new ACCESS_MASK();
uint ret = GetNamedSecurityInfo(Path,
SE_OBJECT_TYPE.SE_FILE_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor);
TRUSTEE t = new TRUSTEE();
t.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME;
t.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER;
t.ptstrName = UserName;
//Console.WriteLine(t.ptstrName+" "+ t.TrusteeType);
ret = GetEffectiveRightsFromAcl(pDacl, ref t, ref mask);
int i = 0;
List<string> effectivePermissionList = new List<string>();
string[] rights = new string[14] {"Full Control" ,"Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
rightsmap.Add("FILE_READ_DATA", "List folder / read data");
rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
rightsmap.Add("FILE_READ_EA", "Read extended attributes");
rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
rightsmap.Add("FILE_WRITE_DATA", "Create files / write files");
rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
rightsmap.Add("DELETE", "Delete");
rightsmap.Add("READ_CONTROL", "Read permission");
rightsmap.Add("WRITE_DAC", "Change permission");
rightsmap.Add("WRITE_OWNER", "Take ownership");
foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
{
if ((mask & item) == item)
{
effectivePermissionList.Add(rightsmap[item.ToString()]);
i++;
}
}
//Console.WriteLine(i);
if (i == 16)
{
effectivePermissionList.Insert(0,"Full Control");
}
string user = System.IO.File.GetAccessControl(Path).GetOwner(typeof(System.Security.Principal.NTAccount)).ToString();
if (user.Equals(UserName))
{
if (!effectivePermissionList.Contains("Read permission"))
{
effectivePermissionList.Add("Read permission");
}
if (!effectivePermissionList.Contains("Change permission"))
{
effectivePermissionList.Add("Change permission");
}
}
foreach (string r in rights)
{
if (effectivePermissionList.Contains(r))
{
Console.WriteLine(r);
}
}
Console.ReadLine();
}
}
}
This is the exact answer for my question:
namespace EffectiveRightsUsingAuthzAPI
{
class Program
{
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint GetEffectiveRightsFromAcl(IntPtr pDacl, ref TRUSTEE pTrustee, ref ACCESS_MASK pAccessRights);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
struct TRUSTEE
{
IntPtr pMultipleTrustee; // must be null
public int MultipleTrusteeOperation;
public TRUSTEE_FORM TrusteeForm;
public TRUSTEE_TYPE TrusteeType;
[MarshalAs(UnmanagedType.LPStr)]
public string ptstrName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REQUEST
{
public int DesiredAccess;
public byte[] PrincipalSelfSid;
public OBJECT_TYPE_LIST[] ObjectTypeList;
public int ObjectTypeListLength;
public IntPtr OptionalArguments;
};
[StructLayout(LayoutKind.Sequential)]
public struct OBJECT_TYPE_LIST
{
OBJECT_TYPE_LEVEL Level;
int Sbz;
IntPtr ObjectType;
};
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REPLY
{
public int ResultListLength;
public IntPtr GrantedAccessMask;
public IntPtr SaclEvaluationResults;
public IntPtr Error;
};
public enum OBJECT_TYPE_LEVEL : int
{
ACCESS_OBJECT_GUID = 0,
ACCESS_PROPERTY_SET_GUID = 1,
ACCESS_PROPERTY_GUID = 2,
ACCESS_MAX_LEVEL = 4
};
enum TRUSTEE_FORM
{
TRUSTEE_IS_SID,
TRUSTEE_IS_NAME,
TRUSTEE_BAD_FORM,
TRUSTEE_IS_OBJECTS_AND_SID,
TRUSTEE_IS_OBJECTS_AND_NAME
}
enum AUTHZ_RM_FLAG : uint
{
AUTHZ_RM_FLAG_NO_AUDIT = 1,
AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION = 2,
AUTHZ_RM_FLAG_NO_CENTRAL_ACCESS_POLICIES = 4,
}
enum TRUSTEE_TYPE
{
TRUSTEE_IS_UNKNOWN,
TRUSTEE_IS_USER,
TRUSTEE_IS_GROUP,
TRUSTEE_IS_DOMAIN,
TRUSTEE_IS_ALIAS,
TRUSTEE_IS_WELL_KNOWN_GROUP,
TRUSTEE_IS_DELETED,
TRUSTEE_IS_INVALID,
TRUSTEE_IS_COMPUTER
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
static extern uint GetNamedSecurityInfo(
string pObjectName,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
out IntPtr pSidOwner,
out IntPtr pSidGroup,
out IntPtr pDacl,
out IntPtr pSacl,
out IntPtr pSecurityDescriptor);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeContextFromSid", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeContextFromSid(
int Flags,
IntPtr UserSid ,
IntPtr AuthzResourceManager,
IntPtr pExpirationTime,
LUID Identitifier,
IntPtr DynamicGroupArgs,
out IntPtr pAuthzClientContext
);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeResourceManager", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeResourceManager(
int flags,
IntPtr pfnAccessCheck,
IntPtr pfnComputeDynamicGroups,
IntPtr pfnFreeDynamicGroups,
string name,
out IntPtr rm
);
[DllImport("authz.dll", EntryPoint = "AuthzAccessCheck", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool AuthzAccessCheck(int flags,
IntPtr hAuthzClientContext,
ref AUTHZ_ACCESS_REQUEST pRequest,
IntPtr AuditEvent,
IntPtr pSecurityDescriptor,
byte[] OptionalSecurityDescriptorArray,
int OptionalSecurityDescriptorCount,
ref AUTHZ_ACCESS_REPLY pReply,
out IntPtr phAccessCheckResults);
enum ACCESS_MASK : uint
{
FILE_TRAVERSE = 0x20,
FILE_LIST_DIRECTORY = 0x1,
FILE_READ_DATA = 0x1,
FILE_READ_ATTRIBUTES = 0x80,
FILE_READ_EA = 0x8,
FILE_ADD_FILE = 0x2,
FILE_WRITE_DATA = 0x2,
FILE_ADD_SUBDIRECTORY = 0x4,
FILE_APPEND_DATA = 0x4,
FILE_WRITE_ATTRIBUTES = 0x100,
FILE_WRITE_EA = 0x10,
FILE_DELETE_CHILD = 0x40,
DELETE = 0x10000,
READ_CONTROL = 0x20000,
WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000,
////////FILE_EXECUTE =0x20,
}
[Flags]
enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY
}
static void Main(string[] args)
{
//String UserName = "NT Authority\\Authenticated Users";
do {
Console.WriteLine("UserName:");
String UserName = Console.ReadLine();
Console.WriteLine("Path:");
String Path = Console.ReadLine();
IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
ACCESS_MASK mask = new ACCESS_MASK();
uint ret = GetNamedSecurityInfo(Path,
SE_OBJECT_TYPE.SE_FILE_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION | SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION,
out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor);
IntPtr hManager = IntPtr.Zero;
bool f = AuthzInitializeResourceManager(1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out hManager);
NTAccount ac = new NTAccount(UserName);
SecurityIdentifier sid = (SecurityIdentifier)ac.Translate(typeof(SecurityIdentifier));
byte[] bytes = new byte[sid.BinaryLength];
sid.GetBinaryForm(bytes, 0);
String _psUserSid = "";
foreach (byte si in bytes)
{
_psUserSid += si;
}
LUID unusedSid = new LUID();
IntPtr UserSid = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, UserSid, bytes.Length);
IntPtr pClientContext = IntPtr.Zero;
if (f)
{
f = AuthzInitializeContextFromSid(0, UserSid, hManager, IntPtr.Zero, unusedSid, IntPtr.Zero, out pClientContext);
AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST();
request.DesiredAccess = 0x02000000;
request.PrincipalSelfSid = null;
request.ObjectTypeList = null;
request.ObjectTypeListLength = 0;
request.OptionalArguments = IntPtr.Zero;
AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY();
reply.GrantedAccessMask = IntPtr.Zero;
reply.ResultListLength = 0;
reply.SaclEvaluationResults = IntPtr.Zero;
IntPtr AccessReply = IntPtr.Zero;
reply.Error = Marshal.AllocHGlobal(1020);
reply.GrantedAccessMask = Marshal.AllocHGlobal(sizeof(uint));
reply.ResultListLength = 1;
int i = 0;
Dictionary<String, String> rightsmap = new Dictionary<String, String>();
List<string> effectivePermissionList = new List<string>();
string[] rights = new string[14] { "Full Control", "Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
rightsmap.Add("FILE_READ_DATA", "List folder / read data");
rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
rightsmap.Add("FILE_READ_EA", "Read extended attributes");
rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
rightsmap.Add("FILE_WRITE_DATA", "Create files / write files");
rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
rightsmap.Add("DELETE", "Delete");
rightsmap.Add("READ_CONTROL", "Read permission");
rightsmap.Add("WRITE_DAC", "Change permission");
rightsmap.Add("WRITE_OWNER", "Take ownership");
f = AuthzAccessCheck(0, pClientContext, ref request, IntPtr.Zero, pSecurityDescriptor, null, 0, ref reply, out AccessReply);
if (f)
{
int granted_access = Marshal.ReadInt32(reply.GrantedAccessMask);
mask = (ACCESS_MASK)granted_access;
foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
{
if ((mask & item) == item)
{
effectivePermissionList.Add(rightsmap[item.ToString()]);
i++;
}
}
}
Marshal.FreeHGlobal(reply.GrantedAccessMask);
if (i == 16)
{
effectivePermissionList.Insert(0, "Full Control");
}
Console.WriteLine(".......................");
foreach (string r in rights)
{
if (effectivePermissionList.Contains(r))
{
Console.WriteLine(r);
}
}
}
Console.WriteLine("_________________________________________________\n");
} while (true);
Console.ReadLine();
}
}
}
Is there api in .net for getting effective folder permissions for user?
I know how get permissions by using `DirectorySecurity.GetAccessRules().
But in this case I should manually analyze all permissions for user: permissions for groups, that include the user, inherited permissions and user permission for folder.
Is there a function in the Windows API that can return these permissions via platform invoke?
class Program
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REQUEST
{
public int DesiredAccess;
public byte[] PrincipalSelfSid;
public OBJECT_TYPE_LIST[] ObjectTypeList;
public int ObjectTypeListLength;
public IntPtr OptionalArguments;
};
[StructLayout(LayoutKind.Sequential)]
public struct OBJECT_TYPE_LIST
{
OBJECT_TYPE_LEVEL Level;
int Sbz;
IntPtr ObjectType;
};
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REPLY
{
public int ResultListLength;
public IntPtr GrantedAccessMask;
public IntPtr SaclEvaluationResults;
public IntPtr Error;
};
public enum OBJECT_TYPE_LEVEL : int
{
ACCESS_OBJECT_GUID = 0,
ACCESS_PROPERTY_SET_GUID = 1,
ACCESS_PROPERTY_GUID = 2,
ACCESS_MAX_LEVEL = 4
};
enum AUTHZ_RM_FLAG : uint
{
AUTHZ_RM_FLAG_NO_AUDIT = 1,
AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION = 2,
AUTHZ_RM_FLAG_NO_CENTRAL_ACCESS_POLICIES = 4,
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
static extern uint GetNamedSecurityInfo(
string pObjectName,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
out IntPtr pSidOwner,
out IntPtr pSidGroup,
out IntPtr pDacl,
out IntPtr pSacl,
out IntPtr pSecurityDescriptor);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeContextFromSid", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeContextFromSid(
int Flags,
IntPtr UserSid ,
IntPtr AuthzResourceManager,
IntPtr pExpirationTime,
LUID Identitifier,
IntPtr DynamicGroupArgs,
out IntPtr pAuthzClientContext
);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeResourceManager", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeResourceManager(
int flags,
IntPtr pfnAccessCheck,
IntPtr pfnComputeDynamicGroups,
IntPtr pfnFreeDynamicGroups,
string name,
out IntPtr rm
);
[DllImport("authz.dll", EntryPoint = "AuthzAccessCheck", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool AuthzAccessCheck(int flags,
IntPtr hAuthzClientContext,
ref AUTHZ_ACCESS_REQUEST pRequest,
IntPtr AuditEvent,
IntPtr pSecurityDescriptor,
byte[] OptionalSecurityDescriptorArray,
int OptionalSecurityDescriptorCount,
ref AUTHZ_ACCESS_REPLY pReply,
out IntPtr phAccessCheckResults);
enum ACCESS_MASK : uint
{
FILE_TRAVERSE = 0x20,FILE_LIST_DIRECTORY = 0x1,FILE_READ_DATA = 0x1,FILE_READ_ATTRIBUTES = 0x80,FILE_READ_EA = 0x8,FILE_ADD_FILE = 0x2,FILE_WRITE_DATA = 0x2,FILE_ADD_SUBDIRECTORY = 0x4,FILE_APPEND_DATA = 0x4,FILE_WRITE_ATTRIBUTES = 0x100,FILE_WRITE_EA = 0x10,FILE_DELETE_CHILD = 0x40,DELETE = 0x10000,READ_CONTROL = 0x20000,WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000,
}
[Flags]
enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
}
static void Main(string[] args)
{
//String UserName = "NT Authority\\Authenticated Users";
do {
Console.WriteLine("UserName:");
String UserName = Console.ReadLine();
SecurityIdentifier sid = null;
NTAccount ac = new NTAccount(UserName);
try
{
sid = (SecurityIdentifier)ac.Translate(typeof(SecurityIdentifier));
}
catch (Exception e)
{
Console.WriteLine("Not a group or user");
continue;
}
Console.WriteLine("Path:");
String Path = Console.ReadLine();
if (!(File.Exists(Path) || Directory.Exists(Path)))
{
Console.WriteLine("Invalid Path");
continue;
}
IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
ACCESS_MASK mask = new ACCESS_MASK();
uint ret = GetNamedSecurityInfo(Path,
SE_OBJECT_TYPE.SE_FILE_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION | SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION,
out pSidOwner,
out pSidGroup,
out pDacl,
out pSacl,
out pSecurityDescriptor);
IntPtr hManager = IntPtr.Zero;
bool f = AuthzInitializeResourceManager(1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out hManager);
byte[] bytes = new byte[sid.BinaryLength];
sid.GetBinaryForm(bytes, 0);
String _psUserSid = "";
foreach (byte si in bytes)
{
_psUserSid += si;
}
LUID unusedSid = new LUID();
IntPtr UserSid = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, UserSid, bytes.Length);
IntPtr pClientContext = IntPtr.Zero;
if (f)
{
f = AuthzInitializeContextFromSid(0, UserSid, hManager, IntPtr.Zero, unusedSid, IntPtr.Zero, out pClientContext);
AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST();
request.DesiredAccess = 0x02000000;
request.PrincipalSelfSid = null;
request.ObjectTypeList = null;
request.ObjectTypeListLength = 0;
request.OptionalArguments = IntPtr.Zero;
AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY();
reply.GrantedAccessMask = IntPtr.Zero;
reply.ResultListLength = 0;
reply.SaclEvaluationResults = IntPtr.Zero;
IntPtr AccessReply = IntPtr.Zero;
reply.Error = Marshal.AllocHGlobal(1020);
reply.GrantedAccessMask = Marshal.AllocHGlobal(sizeof(uint));
reply.ResultListLength = 1;
int i = 0;
Dictionary<String, String> rightsmap = new Dictionary<String, String>();
List<string> effectivePermissionList = new List<string>();
string[] rights = new string[14] { "Full Control", "Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
rightsmap.Add("FILE_READ_DATA", "List folder / read data");
rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
rightsmap.Add("FILE_READ_EA", "Read extended attributes");
rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
rightsmap.Add("FILE_WRITE_DATA", "Create files / write files");
rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
rightsmap.Add("DELETE", "Delete");
rightsmap.Add("READ_CONTROL", "Read permission");
rightsmap.Add("WRITE_DAC", "Change permission");
rightsmap.Add("WRITE_OWNER", "Take ownership");
f = AuthzAccessCheck(0, pClientContext, ref request, IntPtr.Zero, pSecurityDescriptor, null, 0, ref reply, out AccessReply);
if (f)
{
int granted_access = Marshal.ReadInt32(reply.GrantedAccessMask);
mask = (ACCESS_MASK)granted_access;
foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
{
if ((mask & item) == item)
{
effectivePermissionList.Add(rightsmap[item.ToString()]);
i++;
}
}
}
Marshal.FreeHGlobal(reply.GrantedAccessMask);
if (i == 16)
{
effectivePermissionList.Insert(0, "Full Control");
}
Console.WriteLine(".......................");
foreach (string r in rights)
{
if (effectivePermissionList.Contains(r))
{
Console.WriteLine(r);
}
}
}
Console.WriteLine("_________________________________________________\n");
} while (true);
// Console.ReadLine();
}
}
I want to change the text that shows when invoking CryptoApi operation that requires smart card PIN. Current prompt is pretty generic (and in system's language), "Please enter your authentication PIN":
This dialog shows when calling CryptSignMessage in COM object, but the call is made from C# WPF desktop app (.NET 4.5). How can I customize the dialog? I've found PP_PIN_PROMPT_STRING parameter for CryptSetProvParam function, but the function requires HCRYPTPROV and I don't have that handle. All I have is reader's name and signing certificate. Just can't wrap my head around it.
Is it possible to customize PIN dialog from either C++ or C# (preferably C#)?
I believe the following should work. As I don't have anything setup to test collecting the information I can't verify.
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CryptSetProvParam(IntPtr hProv, uint dwParam, [In] byte[] pbData, uint dwFlags);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
const uint NTE_BAD_KEYSET = 0x80090016;
const uint PROV_RSA_FULL = 1;
const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
const uint CRYPT_NEWKEYSET = 0x00000008;
const uint PP_PIN_PROMPT_STRING = 0x2C;
public void SetPinText(string text)
{
byte[] data = Encoding.UTF8.GetBytes(text);
IntPtr hCryptProv = IntPtr.Zero;
try
{
if (!CryptAcquireContext(out hCryptProv, null, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (Convert.ToUInt32(Marshal.GetLastWin32Error()) == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET))
throw new Exception("Unable to acquire crypt context.");
}
else
{
throw new Exception("Unable to acquire crypt context.");
}
}
if (!CryptSetProvParam(hCryptProv, PP_PIN_PROMPT_STRING, data, 0))
throw new Exception("Unable to set prompt string.");
}
finally
{
if (hCryptProv != IntPtr.Zero)
{
CryptReleaseContext(hCryptProv, 0);
}
}
}
I am trying to execute a program with admin rights through a C# application, which gets invoked with user rights only.
Code
ProcessStartInfo psi;
try
{
psi = new ProcessStartInfo(#"WINZIP32.EXE");
psi.UseShellExecute = false;
SecureString pw = new SecureString();
pw.AppendChar('p');
pw.AppendChar('a');
pw.AppendChar('s');
pw.AppendChar('s');
pw.AppendChar('w');
pw.AppendChar('o');
pw.AppendChar('r');
pw.AppendChar('d');
psi.Password = pw;
psi.UserName = "administrator";
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
It does start winzip, but only with user rights. Is there something I am doing wrong or is it even possible to start a process with higher rights?
thank you!
Edit:
Here is the reason behind the question, maybe it helps to understand what i actually need.
I used winzip for example to get a general idea what's incorrect with my code. The actual problem is, our company uses 2 versions of a program. But before you start any of the versions you need to import a dll file with regsvr32 (with admin rights). Now I would like to write a program that let the user select the version, import the dll and starts the correct application.
You need to set ProcessStartInfo.UseShellExecute to true and ProcessStartInfo.Verb to runas:
Process process = null;
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = "WINZIP32.EXE";
processStartInfo.Verb = "runas";
processStartInfo.WindowStyle = ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;
process = Process.Start(processStartInfo);
This will cause the application to run as the administrator. UAC will however prompt the user to confirm. If this is not desirable then you'll need to add a manifest to permanently elevate the host process privilages.
You can run a process as another user(even an administrator) using the CreateProcessAsUser function (Win32 API).
CreateProcessAsUser accepts a user token as the first parameter, that is an impersonation token.
You have to use DLLImport to load the function from the Windows DLL.
Take a look at this example implementation that i have used in one of my projects :
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
public uint nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
internal enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
internal enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public class ProcessAsUser
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel,
Int32 dwTokenType,
ref IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
UInt32 DesiredAccess,
ref IntPtr TokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
ref IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
IntPtr lpEnvironment);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(
IntPtr hObject);
private const short SW_SHOW = 5;
private const uint TOKEN_QUERY = 0x0008;
private const uint TOKEN_DUPLICATE = 0x0002;
private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
private const int GENERIC_ALL_ACCESS = 0x10000000;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_FORCEONFEEDBACK = 0x00000040;
private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
private const int STARTF_RUNFULLSCREEN = 0x00000020;
private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock)
{
bool result = false;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);
//if this member is NULL, the new process inherits the desktop
//and window station of its parent process. If this member is
//an empty string, the process does not inherit the desktop and
//window station of its parent process; instead, the system
//determines if a new desktop and window station need to be created.
//If the impersonated user already has a desktop, the system uses the
//existing desktop.
si.lpDesktop = #"WinSta0\Default"; //Modify as needed
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
//Set other si properties as required.
result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);
if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Debug.WriteLine(message);
}
return result;
}
/// <summary>
/// LaunchProcess As User Overloaded for Window Mode
/// </summary>
/// <param name="cmdLine"></param>
/// <param name="token"></param>
/// <param name="envBlock"></param>
/// <param name="WindowMode"></param>
/// <returns></returns>
private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock,uint WindowMode)
{
bool result = false;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);
//if this member is NULL, the new process inherits the desktop
//and window station of its parent process. If this member is
//an empty string, the process does not inherit the desktop and
//window station of its parent process; instead, the system
//determines if a new desktop and window station need to be created.
//If the impersonated user already has a desktop, the system uses the
//existing desktop.
si.lpDesktop = #"WinSta0\Default"; //Default Vista/7 Desktop Session
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
//Check the Startup Mode of the Process
if (WindowMode == 1)
si.wShowWindow = SW_SHOW;
else if (WindowMode == 2)
{ //Do Nothing
}
else if (WindowMode == 3)
si.wShowWindow = 0; //Hide Window
else if (WindowMode == 4)
si.wShowWindow = 3; //Maximize Window
else if (WindowMode == 5)
si.wShowWindow = 6; //Minimize Window
else
si.wShowWindow = SW_SHOW;
//Set other si properties as required.
result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);
if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Debug.WriteLine(message);
}
return result;
}
private static IntPtr GetPrimaryToken(int processId)
{
IntPtr token = IntPtr.Zero;
IntPtr primaryToken = IntPtr.Zero;
bool retVal = false;
Process p = null;
try
{
p = Process.GetProcessById(processId);
}
catch (ArgumentException)
{
string details = String.Format("ProcessID {0} Not Available", processId);
Debug.WriteLine(details);
throw;
}
//Gets impersonation token
retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
if (retVal == true)
{
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = (uint)Marshal.SizeOf(sa);
//Convert the impersonation token into Primary token
retVal = DuplicateTokenEx(
token,
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref primaryToken);
//Close the Token that was previously opened.
CloseHandle(token);
if (retVal == false)
{
string message = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
}
else
{
string message = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
//We'll Close this token after it is used.
return primaryToken;
}
private static IntPtr GetEnvironmentBlock(IntPtr token)
{
IntPtr envBlock = IntPtr.Zero;
bool retVal = CreateEnvironmentBlock(ref envBlock, token, false);
if (retVal == false)
{
//Environment Block, things like common paths to My Documents etc.
//Will not be created if "false"
//It should not adversley affect CreateProcessAsUser.
string message = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
return envBlock;
}
public static bool Launch(string appCmdLine /*,int processId*/)
{
bool ret = false;
//Either specify the processID explicitly
//Or try to get it from a process owned by the user.
//In this case assuming there is only one explorer.exe
Process[] ps = Process.GetProcessesByName("explorer");
int processId = -1;//=processId
if (ps.Length > 0)
{
processId = ps[0].Id;
}
if (processId > 1)
{
IntPtr token = GetPrimaryToken(processId);
if (token != IntPtr.Zero)
{
IntPtr envBlock = GetEnvironmentBlock(token);
ret = LaunchProcessAsUser(appCmdLine, token, envBlock);
if (envBlock != IntPtr.Zero)
DestroyEnvironmentBlock(envBlock);
CloseHandle(token);
}
}
return ret;
}
Ref:
How to start a Process as administrator mode in C#
Elevating process privilege programmatically?
var psi = new ProcessStartInfo
{
FileName = "notepad",
UserName = "admin",
Domain = "",
Password = pass,
UseShellExecute = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
Verb = "runas";
};
Process.Start(psi);
//
var pass = new SecureString();
pass.AppendChar('s');
pass.AppendChar('e');
pass.AppendChar('c');
pass.AppendChar('r');
pass.AppendChar('e');
pass.AppendChar('t');
Process.Start("notepad", "admin", pass, "");
//Vista or higher check
if (System.Environment.OSVersion.Version.Major >= 6)
{
p.StartInfo.Verb = "runas";
}
Ref: How to run/start a new process with admin rights? ASP.net Forum
Another way is to impersonate the admin user. You can do this by
calling the Logon function and impersonate the user whose token you
will get then. For impersonating a user in code, look at:
WindowsImpersonationContext
Class
. Use the check
http://www.csharpfriends.com/Forums/ShowPost.aspx?PostID=31611 for
GetCurrentUser to see whether impersonation succeeded.
Code Snippet:
System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;
processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.FileName = "regedit.exe";
if (System.Environment.OSVersion.Version.Major >= 6) // Windows Vista or higher
{
processStartInfo.Verb = "runas";
}
else
{
// No need to prompt to run as admin
}
processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;
try
{
process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (process != null)
{
process.Dispose();
}
}
//Try this with administrator login, i have not tested yet..
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
// Test harness.
// If you incorporate this code into a DLL, be sure to demand FullTrust.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
private void button1_Click(object sender, EventArgs e)
{
SafeTokenHandle safeTokenHandle;
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
bool returnValue = LogonUser("administrator", "", "password",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);
Console.WriteLine("LogonUser called.");
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}
using (safeTokenHandle)
{
Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);
// Check the identity.
Console.WriteLine("Before impersonation: "
+ WindowsIdentity.GetCurrent().Name);
// Use the token handle returned by LogonUser.
WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;
processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.FileName = "regedit.exe";
//if (System.Environment.OSVersion.Version.Major >= 6) // Windows Vista or higher
//{
// processStartInfo.Verb = "runas";
//}
//else
//{
// // No need to prompt to run as admin
//}
processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;
try
{
process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (process != null)
{
process.Dispose();
}
}
// Check the identity.
Console.WriteLine("After impersonation: "
+ WindowsIdentity.GetCurrent().Name);
}
// Releasing the context object stops the impersonation
// Check the identity.
Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
}
}