Quantcast
Channel: Common Language Runtime Internals and Architecture forum
Viewing all articles
Browse latest Browse all 1710

System.ComponentModel.Win32Exception "Access Denied" retrieving process information as local admin using impersonation

$
0
0

Hi everyone.

I am encountering an issue when trying to get other processes informations from my app. This app is an "updater". When it starts, it checks if the process to update is running. And here is the issue. Some informations on the running processes throw a System.ComponentModel.Win32Exception "Access denied" Exception. I was able to understand the reason of the exception : the updater is lauched from a "user" account and the user cannot read other user's processes. Because the updater runs in a Terminal Service session, other users may have the app to update running. If that is the case, the updater should warn the user, but instead of doing it, it crashes when reader the running process info.

After reading a lot about over the internet, I decided to use impersonation to execute the updater so that it will execute as a different account. Because the updater must access a network share, I set a domain administrator account.

The code runs fine, the impersonation works, but the exception is still there, even when the the code is executed with the domain admin account. I also tried to put the domain admin account in the local "Administrators" group.

So... I don't understand what is going wrong...

Can you help me please ?

(The updater runs on a Windows Server 2003 x86, the .NET framework is the 3.5)

Here is the simplified code that trows the exception :

WrapperImpersonationContext c = new WrapperImpersonationContext("MyDomain", "MyDomainAdmin", "MyPassword") ;

int errorCode = 0 ;

c.Enter(out errorCode) ; // Impersonation...

Console.WriteLine(Environment.UserName) ; // = MyDomainAdmin, Impersonation OK!

// Looking for running process called "test". It may return mine or other users processes

Process[] ret = Process.GetProcessesByName("test"); List<Process> retList = new List<Process>(); for(int i = 0; i < ret.Length; i++) {

// The process here is a process that belongs to another user, that's why I get an exception FileInfo fi = new FileInfo(ret[i].MainModule.FileName); // System.ComponentModel.Win32Exception!!! Access denied on MainModule... }


Here is theWrapperImpersonationContext class code :

using System; using System.Runtime.InteropServices; using System.Security.Principal; using System.Security.Permissions; using System.ComponentModel; namespace Common.ApplicationUpdater { public class WrapperImpersonationContext { [DllImport("advapi32.dll", SetLastError = true)] public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle); private const int LOGON32_PROVIDER_DEFAULT = 0; private const int LOGON32_LOGON_INTERACTIVE = 2; private string m_Domain; private string m_Password; private string m_Username; private IntPtr m_Token; private WindowsImpersonationContext m_Context = null; protected bool IsInContext { get { return m_Context != null; } } public WrapperImpersonationContext(string domain, string username, string password) { m_Domain = domain; m_Username = username; m_Password = password; } [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] public bool Enter(out int errorCode) { errorCode = 0; if(this.IsInContext) return true; m_Token = new IntPtr(0); try { m_Token = IntPtr.Zero; bool logonSuccessfull = LogonUser( m_Username, m_Domain, m_Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref m_Token); if(logonSuccessfull ) { WindowsIdentity identity = new WindowsIdentity(m_Token); m_Context = identity.Impersonate(); } else { errorCode = Marshal.GetLastWin32Error(); return false; } return true; } catch(Exception ex) { errorCode = (int) Marshal.GetHRForException(ex); return false; } } [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] public void Leave() { if(this.IsInContext == false) return; m_Context.Undo(); if(m_Token != IntPtr.Zero) CloseHandle(m_Token); m_Context = null; } }

}

Thank you for helping me!

Best regards.


Matteo, .NET Developer and System Engineer





Viewing all articles
Browse latest Browse all 1710

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>