question

abbasshaikh-3984 avatar image
0 Votes"
abbasshaikh-3984 asked RLWA32-6355 edited

unhandle exception for normal user click not for admin user

Hi,

I had popup a UI using win32 api creaprocessasuser. It works as I use admin user login. but it give two exception
1. unhandled exception (in event handler)as a normal user try to launch pop UI.

Description: The process was terminated due to an unhandled exception.
Exception Info: System.ObjectDisposedException
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Form.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.ContainerControl.FocusActiveControlInternal()
at System.Windows.Forms.Form.SetVisibleCore(Boolean)
at System.Windows.Forms.Control.set_Visible(Boolean)
at System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
at System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
at System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
at WinFormPrintDriverApp.Program.Main(System.String[])


Faulting application name: myapplication.exe, version: 1.0.0.0, time stamp: 0xab4b49da
Faulting module name: KERNELBASE.dll, version: 6.3.9600.19671, time stamp: 0x5e67335c
Exception code: 0xe0434352
Fault offset: 0x00013d28
Faulting process id: 0x1d84
Faulting application start time: 0x01d77a36c724e6f6
Faulting application path: c:\testpath\myapplication.exe
Faulting module path: C:\Windows\SYSTEM32\KERNELBASE.dll
Report Id: 0ae714c2-e62a-11eb-8106-0050568ffd89
Faulting package full name:
Faulting package-relative application ID:


what might be issue? Any help appreciated to resolve this isue.










windows-serverwindows-api
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Presumably there is something in the code that requires Administrator privileges. Show a relevant snippet of the code used to call the CreateProcessAsUser function with as much detailed information as possible.

0 Votes 0 ·

1 Answer

abbasshaikh-3984 avatar image
0 Votes"
abbasshaikh-3984 answered RLWA32-6355 edited



my code:

public static bool StartProcessAsCurrentUser(string appPath, string cmdLine, string currentUserName, string workDir = null, bool visible = true)
{
var hUserToken = IntPtr.Zero;
var startInfo = new STARTUPINFO();
var procInfo = new PROCESS_INFORMATION();
var pEnv = IntPtr.Zero;
int iResultOfCreateProcessAsUser;

         startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));

          
         try
         {
                
             if (!GetSessionUserToken(ref hUserToken, currentUserName))
               {
                     throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed.");
                 }

             uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
             startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
             startInfo.lpDesktop = "winsta0\\default";
                

             if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))
             {
                 throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");
             }
                

             if (!CreateProcessAsUser(hUserToken,
                 appPath, // Application Name
                 cmdLine, // Command Line
                 IntPtr.Zero,
                 IntPtr.Zero,
                 false,
                 dwCreationFlags,
                 pEnv,
                 workDir, // Working directory
                 ref startInfo,
                 out procInfo))
             {
                 iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
                 throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed.  Error Code -" + iResultOfCreateProcessAsUser);
             }

             iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
         }
         catch(Exception ex)
         { 
             log.Info("StartProcessAsCurrentUser exeption msg:"+ex.Message +" stacktrace:"+ex.StackTrace); 
         }
         finally
         {
             CloseHandle(hUserToken);
             if (pEnv != IntPtr.Zero)
             {
                 DestroyEnvironmentBlock(pEnv);
             }
             CloseHandle(procInfo.hThread);
             CloseHandle(procInfo.hProcess);
         }

return true;
}
}

private static bool GetSessionUserToken(ref IntPtr phUserToken, string currentUserName)
{


         var bResult = false;
         var hImpersonationToken = IntPtr.Zero;
         var activeSessionId = INVALID_SESSION_ID;
         try
         {
             ITerminalServicesManager manager = new TerminalServicesManager();

             using (ITerminalServer server = manager.GetLocalServer())
             {
                 server.Open();
                 foreach (ITerminalServicesSession session in server.GetSessions())
                 {
                     if (session.UserName.ToUpper() == currentUserName.ToUpper())
                     {
                         activeSessionId = (uint)session.SessionId;
    
                         break;
                     }
    
                 }
             }
    

             // If enumerating did not work, fall back to the old method
             if (activeSessionId == INVALID_SESSION_ID)
             {
                 activeSessionId = WTSGetActiveConsoleSessionId();
             }
             log.Info("Method GetSessionUserToken:  activeSessionId:" + activeSessionId);
             if (WTSQueryUserToken(activeSessionId, ref hImpersonationToken) != 0)
             {
                 // Convert the impersonation token to a primary token
                 bResult = DuplicateTokenEx(hImpersonationToken, 0, IntPtr.Zero,
                     (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, (int)TOKEN_TYPE.TokenPrimary, ref phUserToken);

                 CloseHandle(hImpersonationToken);
             }
             log.Info("GetSessionUserToken ends.");
         }
         catch(Exception ex)
         {
             log.Info("GetSessionUserToken exception:." + ex.Message);
         }
             return bResult;
     }
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Some things don't make sense to me. Ordinarily, the WTSQueryUserToken function requires that the caller is running as LocalSystem with the SE_TCB_NAME privilege. So even an elevated process running under an Administrator account would not be able to call this function successfully.

Also, what application is the code attempting to start? Perhaps a standard user does not have access to the application while an Administrator does.

0 Votes 0 ·

I can't agree more. The snippet cannot identify whether WTSQueryUserToken has problem or not. It is possible that hUserToken is NULL at CreateProcessAsUser.
And According to CreateProcessAsUser, The answer and the following comments,

Typically, the process that calls the CreateProcessAsUser function must have the SE_INCREASE_QUOTA_NAME privilege and may require the SE_ASSIGNPRIMARYTOKEN_NAME privilege if the token is not assignable. If this function fails with ERROR_PRIVILEGE_NOT_HELD (1314), use the CreateProcessWithLogonW function instead.


0 Votes 0 ·

As far as I can see the posted code cannot obtain a valid token to use because the call to WTSQueryUserToken will always fail. Execution continues and eventually the posted GetSessionUserToken function returns false to the caller. The call to CreateProcessAsUser is never reached.

0 Votes 0 ·