允许程序权限在启动时从任何帐户更改PC名称?

时间:2013-08-04 22:05:56

标签: c windows startup uac impersonation

我正在编写一个基本程序,在启动时将PC的活动NIC发送到服务器并相应地更改PC的主机名。该过程概述如下。

计划执行流程:

  1. 由任何帐户自动启动
  2. 收集有效的NIC地址
  3. 将NIC地址发送到服务器
  4. 接收分配的PC主机名
  5. 比较当前和分配的主机名
  6. 根据需要更改主机名
  7. 我让程序按照设计完美地执行步骤1-5。它能够收集活动的NIC地址,为服务器准备数据包并接收响应。问题是程序何时到达步骤6.在Windows XP上,如果仅以管理员身份登录,程序将更改主机名而不会出现问题。在Windows Vista,7和8上,程序无法更改计算机主机名(由于需要UAC提升),或者如果登录到没有管理员权限的用户帐户,则缺少必要的权限。

    向程序添加应用程序清单以向用户和Windows发出信号,表明程序需要管理员权限,程序无法启动,因为Windows Vista及更高版本无法启动需要管理员权限的程序启动。

    在上一次清单修改之后,我在作为管理员的计算机上创建了一个单独的用户帐户,以便该程序可以模拟管理员帐户并具有对计算机的完全访问权限,而无需活动用户成为管理员。再次在Windows XP上它完美无缺。在Windows 7上,程序将抛出“Permission Denied”消息。我已尝试过使用advapi32.dll和userenv.dll进行Process.Start以及C Sharp模拟,如下所示。

    允许程序权限在启动时从任何帐户更改PC名称的最佳方法是什么?

    process.start方法

    ProcessStartInfo myProcess = new ProcessStartInfo(path);
    myProcess.UserName = username;
    myProcess.Password = MakeSecureString(password);
    myProcess.WorkingDirectory = @"C:\Windows\System32";
    myProcess.UseShellExecute = false;
    myProcess.Verb = "runas";
    Process.Start(myProcess);
    

    模拟方法

    static void Imp()
            {
                WindowsImpersonationContext m_ImpersonationContext = null;
                WindowsIdentity m_ImpersonatedUser;
                IntPtr token = IntPtr.Zero;
                IntPtr tokenDuplicate = IntPtr.Zero;
                const int SecurityImpersonation = 2;
                const int TokenType = 1;
                const int LOGON32_LOGON_INTERACTIVE = 2;
                const int LOGON32_PROVIDER_DEFAULT = 0;
    
                try
                {
                    if (RevertToSelf())
                    {
                        Console.WriteLine("Before impersonation: " +
                                          WindowsIdentity.GetCurrent().Name);
    
                        String userName = "sfadmin";
                        //IntPtr password = GetPassword();
    
                        if (LogonUser(userName, Environment.MachineName,
                                      "d31ux3", LOGON32_LOGON_INTERACTIVE,
                                      LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                        {
                            if (DuplicateToken(token, SecurityImpersonation, ref tokenDuplicate) != 0)
                            {
                                m_ImpersonatedUser = new WindowsIdentity(tokenDuplicate);
                                using (m_ImpersonationContext = m_ImpersonatedUser.Impersonate())
                                {
                                    if (m_ImpersonationContext != null)
                                    {
                                        Console.WriteLine("After Impersonation succeeded: " +
                                            Environment.NewLine +
                                            "User Name: " +
                                            WindowsIdentity.GetCurrent(
                                               TokenAccessLevels.MaximumAllowed).Name +
                                            Environment.NewLine +
                                            "SID: " +
                                            WindowsIdentity.GetCurrent(
                                               TokenAccessLevels.MaximumAllowed).User.Value);
    
                                        #region LoadUserProfile
                                        // Load user profile
                                        ProfileInfo profileInfo = new ProfileInfo();
                                        profileInfo.dwSize = Marshal.SizeOf(profileInfo);
                                        profileInfo.lpUserName = userName;
                                        profileInfo.dwFlags = 1;
                                        Boolean loadSuccess =
                                                LoadUserProfile(tokenDuplicate, ref profileInfo);
    
                                        if (!loadSuccess)
                                        {
                                            Console.WriteLine("LoadUserProfile() failed with error code: " +
                                                              Marshal.GetLastWin32Error());
                                            throw new Win32Exception(Marshal.GetLastWin32Error());
                                        }
    
                                        if (profileInfo.hProfile == IntPtr.Zero)
                                        {
                                            Console.WriteLine(
                                                "LoadUserProfile() failed - HKCU handle " +
                                                "was not loaded. Error code: " +
                                                Marshal.GetLastWin32Error());
                                            throw new Win32Exception(Marshal.GetLastWin32Error());
                                        }
                                        #endregion
    
                                        CloseHandle(token);
                                        CloseHandle(tokenDuplicate);
    
                                        // Do tasks after impersonating successfully
                                        //AccessFileSystem();
    
                                        RunAs("SolarFrost.exe", "sfadmin", "d31ux3");
    
    
                                        // Access HKCU after loading user's profile
                                        //AccessHkcuRegistry(profileInfo.hProfile);
    
                                        // Unload user profile
                                        // MSDN remarks
                                        // http://msdn.microsoft.com/en-us/library/bb762282(VS.85).aspx
                                        // Before calling UnloadUserProfile you should
                                        // ensure that all handles to keys that you have opened in the
                                        // user's registry hive are closed. If you do not
                                        // close all open registry handles, the user's profile fails
                                        // to unload. For more information, see Registry Key
                                        // Security and Access Rights and Registry Hives.
                                        UnloadUserProfile(tokenDuplicate, profileInfo.hProfile);
    
                                        // Undo impersonation
                                        m_ImpersonationContext.Undo();
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("DuplicateToken() failed with error code: " +
                                                  Marshal.GetLastWin32Error());
                                throw new Win32Exception(Marshal.GetLastWin32Error());
                            }
                        }
                    }
                }
                catch (Exception Ex)
                {
                    System.IO.File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", Ex.ToString() + "\r\n");
                }
                finally
                {
                    if (token != IntPtr.Zero) CloseHandle(token);
                    if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate);
    
                    Console.WriteLine("After finished impersonation: " +
                                      WindowsIdentity.GetCurrent().Name);
                }
    

1 个答案:

答案 0 :(得分:0)

您可以使用Windows中的Task Scheduler设置任务。将任务设置为在启动时运行,无论是否有人已登录。还要确保任务在highest privilege运行(复选框)。这应该可以解决你的问题。