2010-12-01 3 views
2

다음 코드를 사용하여 로컬 컴퓨터 하이브 ('SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ ProfileList \ % SID %')에서 레지스트리 키를 편집하고 있습니다. 실제로 레지스트리 키 (쓰기 권한 있음)를 열려고 시도하기 전까지는 문제가없는 것 같습니다. 'Requested registry access is not allowed.'이라는 메시지와 함께 SecurityException이 발생합니다. 확인한 다음 레지스트리 키와 내가 가장하는 사용자의 사용 권한을 다시 확인하고 모두 체크 아웃합니다. 가장 된 사용자의 계정에 로그인하면 코드가 제대로 실행되지만 제한된 사용자로 로그인하면 코드가 실패합니다. 스레드가 관리 권한을 부여받는 것을 제외하고는 가장이 모두 작동하는 것과 같습니다. 이 문제를 해결하는 방법에 대한 아이디어는 대단히 감사하겠습니다!레지스트리 키를 편집 할 수있는 관리자 계정이 작동하지 않음 (C#)

string KEY_STR = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + WindowsIdentity.GetCurrent().User.Value; 
WindowsImpersonationContext adminContext = null; 
IntPtr tokenHandle = new IntPtr(0); 
try 
{ 
    LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle); 
    if (tokenHandle.Equals(new IntPtr(0))) LogonUser(userName, computerName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle); 
    WindowsIdentity adminIdentity = new WindowsIdentity(tokenHandle); 
    adminContext = adminIdentity.Impersonate(); 
    RegistryKey key = Registry.LocalMachine.OpenSubKey(KEY_STR, true); 
    key.SetValue("State", 0x60001); 
    Console.Out.WriteLine("User profile changed to Mandatory."); 
} 
catch (Exception ex) 
{ 
    Console.Out.WriteLine("\nUnable to set profile to Mandatory:\n\t" + ex.Message); 
} 
finally 
{ 
    adminContext.Undo(); 
    if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); 
} 

답변

0

토큰은 레지스트리에 대한 쓰기 권한을 얻기에 충분하지 않았습니다. 대신이 작업을 수행하기 위해 시스템으로 실행중인 Windows 서비스를 사용할 것입니다.

1

여기에 맞춰보십시오.하지만 UAC가 켜져있는 Vista 또는 Win7 상자에 있을까요? 이 작업을 수행 할 권한을 높이려면 사용자 확인을 받아야합니다.

+0

Win7 상자에서 실행 중이지만 UAC가 꺼져 있습니다. – Trevor

1

나는이 스레드가 꽤 오래 알고, 어쩌면 당신은 이미이 문제를 해결,하지만 난 Win7에 상자에 문제없이 이런 식으로했다 :

string userName = "domain\\user"; // there's really just one slash, 
//but you have to escape it if hard-coding.. 
//if brought in by a text box, it would be just domain\user 

string password = "whatever"; 
string KEY_STR = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + WindowsIdentity.GetCurrent().User.Value; 

WindowsImpersonationContext adminContext = Impersonation.getWic(userName, password); 
if (adminContext != null) 
{ 
    try 
    { 
     RegistryKey key = Registry.LocalMachine.OpenSubKey(KEY_STR, true); 

     //NOTE: If this was on a remote machine, that line would just be: 
     // RegistryKey key = RegistryKey.OpenRemoteSubKey(RegistryHive.LocalMachine, computerName).OpenSubKey(KEY_STR, true); 

     key.SetValue("State", 0x60001); 
     Console.Out.WriteLine("User profile changed to Mandatory."); 
    } 
    catch (Exception ex) 
    { 
     Console.Out.WriteLine("\nUnable to set profile to Mandatory:\n\t" + ex.Message); 
     Impersonation.endImpersonation(); 
     adminContext.Undo(); 
    } 
    finally 
    { 
     Impersonation.endImpersonation(); 
     // The above line does what you had, here --    
     //if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); 
     adminContext.Undo(); 
    } 
} 

이 내 별도의 명의 도용 클래스입니다. doImpersonation()이 부분이 이미 분할 허용하는 동안이있는 경우, domain\user 또는 machinename\user 모양과 doImpersonation()에 전원을 전달하기 전에 구성 요소 부분으로 그들을 분할 사용자 이름을 걸릴 것 getWic() - 그것은 2 주 진입 점, getWic()doImpersonation()있다 이 코드는 getWic()에 필요하지 않습니다. 둘 다 WindowsImpersonationContext을 반환합니다.

using System; 
using System.Data; 
using System.Configuration; 
using System.Security.Permissions; 
using System.Security.Principal; 
using System.Runtime.InteropServices; 

[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)] 
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")] 
public class Impersonation 
{ 
    [DllImport("advapi32.dll", EntryPoint = "LogonUser")] 
    public static extern bool LogonUser(
     string lpszUsername, 
     string lpszDomain, 
     string lpszPassword, 
     int dwLogonType, 
     int dwLogonProvider, 
     ref IntPtr phToken); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, 
     int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    public extern static bool CloseHandle(IntPtr handle); 

    // Declare the Logon Types as constants 
    const int LOGON32_LOGON_INTERACTIVE = 2; 
    const int LOGON32_LOGON_NETWORK = 3; 
    const int LOGON32_LOGON_BATCH = 4; 
    const int LOGON32_LOGON_SERVICE = 5; 
    const int LOGON32_LOGON_UNLOCK = 7; 
    const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8; // Win2K or higher 
    const int LOGON32_LOGON_NEW_CREDENTIALS = 9; // Win2K or higher 

    // Declare the Logon Providers as constants 
    const int LOGON32_PROVIDER_DEFAULT = 0; 
    const int LOGON32_PROVIDER_WINNT50 = 3; 
    const int LOGON32_PROVIDER_WINNT40 = 2; 
    const int LOGON32_PROVIDER_WINNT35 = 1; 

    // Declare the Impersonation Levels as constants 
    const int SecurityAnonymous = 0; 
    const int SecurityIdentification = 1; 
    const int SecurityImpersonation = 2; 
    const int SecurityDelegation = 3; 

    private static WindowsIdentity newId; 
    private static IntPtr tokenHandle = new IntPtr(0); 
    private static IntPtr dupeTokenHandle = new IntPtr(0); 

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] 
    public static WindowsImpersonationContext doImpersonation(string svcUserName, string domainName, string password) 
    { 
     // Initialize tokens 
     tokenHandle = IntPtr.Zero; 
     dupeTokenHandle = IntPtr.Zero; 

     // Call LogonUser to obtain a handle to an access token 
     bool returnValue = LogonUser(svcUserName, domainName, password, 
     LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_WINNT50, ref tokenHandle); 

     if (returnValue == false) 
     { 
      int ret = Marshal.GetLastWin32Error(); 

      //Check for errors 
      if (ret != NO_ERROR) 
       throw new Exception("LogonUser failed with error code : " + GetError(ret)); 
     } 

     bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle); 
     if (retVal == false) 
     { 
      CloseHandle(tokenHandle); 
      throw new Exception("Exception thrown in trying to duplicate token."); 
     } 
     else 
     { 
      // Begin Impersonation 
      bool bRetVal = DuplicateToken(tokenHandle, 
      (int)SecurityImpersonation, ref dupeTokenHandle); 

      newId = new WindowsIdentity(dupeTokenHandle); 
      WindowsImpersonationContext impersonatedUser = newId.Impersonate(); 
      return impersonatedUser; 
     } 
    } 

    public static void endImpersonation() 
    { 
     if (dupeTokenHandle != IntPtr.Zero) 
      CloseHandle(dupeTokenHandle); 
     if (tokenHandle != IntPtr.Zero) 
      CloseHandle(tokenHandle); 
    } 

    public static WindowsImpersonationContext getWic(string userNameStringFromTextbox, string password) 
    { 
     try 
     { 
      // Establish impersonation 
      string svcUser = userNameStringFromTextbox; 
      string[] arrUser = new string[2]; 
      arrUser = svcUser.Split('\\'); 
      string domain = arrUser[0]; 
      string svcUserName = arrUser[1]; 

      // Get Password: Convert from Base-64 String to decrypted string    
      //string keyLength = ConfigurationManager.AppSettings["keyLength"].ToString(); 
      //string keyLocation = ConfigurationManager.AppSettings["keyLocation"].ToString(); 
      //password = RSAEncrypt.DecryptData(password, keyLength, keyLocation); 

      WindowsImpersonationContext wic = doImpersonation(svcUserName, domain, password); 
      return wic; 
     } 
     catch (Exception ex) 
     { 
      ErrorLog.ErrorRoutine(new Exception("getWic() Error: " + ex.ToString()), ErrorMessage.NOTIFY_APP_ERROR); 
      return null; 
     } 
    } 

    #region Errors 
    const int NO_ERROR = 0; 

    const int ERROR_ACCESS_DENIED = 5; 
    const int ERROR_ALREADY_ASSIGNED = 85; 
    const int ERROR_BAD_DEVICE = 1200; 
    const int ERROR_BAD_NET_NAME = 67; 
    const int ERROR_BAD_PROVIDER = 1204; 
    const int ERROR_CANCELLED = 1223; 
    const int ERROR_EXTENDED_ERROR = 1208; 
    const int ERROR_INVALID_ADDRESS = 487; 
    const int ERROR_INVALID_PARAMETER = 87; 
    const int ERROR_INVALID_PASSWORD = 1216; 
    const int ERROR_MORE_DATA = 234; 
    const int ERROR_NO_MORE_ITEMS = 259; 
    const int ERROR_NO_NET_OR_BAD_PATH = 1203; 
    const int ERROR_NO_NETWORK = 1222; 
    const int ERROR_SESSION_CREDENTIAL_CONFLICT = 1219; 

    const int ERROR_BAD_PROFILE = 1206; 
    const int ERROR_CANNOT_OPEN_PROFILE = 1205; 
    const int ERROR_DEVICE_IN_USE = 2404; 
    const int ERROR_NOT_CONNECTED = 2250; 
    const int ERROR_OPEN_FILES = 2401; 

    private struct ErrorClass 
    { 
     public int num; 
     public string message; 
     public ErrorClass(int num, string message) 
     { 
      this.num = num; 
      this.message = message; 
     } 
    } 

    private static ErrorClass[] ERROR_LIST = new ErrorClass[] { 
     new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"), 
     new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"), 
     new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"), 
     new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"), 
     new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"), 
     new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"), 
     new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), 
     new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"), 
     new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"), 
     new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"), 
     new ErrorClass(ERROR_MORE_DATA, "Error: More Data"), 
     new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"), 
     new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"), 
     new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"), 
     new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"), 
     new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"), 
     new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"), 
     new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), 
     new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"), 
     new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"), 
     new ErrorClass(ERROR_SESSION_CREDENTIAL_CONFLICT, "Error: Credential Conflict"), 
    }; 

    private static string GetError(int errNum) 
    { 
     foreach (ErrorClass er in ERROR_LIST) 
     { 
      if (er.num == errNum) return er.message; 
     } 
     return "Error: Unknown, " + errNum; 
    } 
    #endregion 
} 
관련 문제