C# : Generate valid Security Token and run the application in security context of given user

/* You can use this console application to generate the valid security token for the given user and run the specified command in the security context of the user. You will need to use attached. You need to download WtsApi32.NET.dll from http://www.dlldump.com/download-dll-files_new.php/dllfiles/W/wtsapi32.dll/5.1.2600.2180/download.html and add it to reference.*/

using System;
using System.IO;
using System.Text;
using Microsoft.Win32;
using System.Security;
using System.Threading;
using System.Reflection;
using System.Diagnostics;
using System.Configuration;
using System.Globalization;
using System.ComponentModel;
using System.Security.Principal;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using System.Data;

namespace TokenGenerationTest
class TokenGenerator
static void Main(string[] args)
string userName = @"username";
string passphrase = "password";
string commandPath = @"commandpath";//specify the command
string commandArguments = null;
TokenGenerator obj = new TokenGenerator();
// get the user's logon token
IntPtr hUser = IntPtr.Zero;
obj.QueryUserToken(userName, ref hUser);

Process p = null;
if (obj.CreateProcessAsUser(hUser, passphrase, commandPath, commandArguments, ref p))
System.Console.WriteLine("Created"); // p.WaitForExit();
System.Console.WriteLine("Not Created: " + hUser.ToString());
private bool CreateProcessAsUser(
IntPtr userToken,
string passphrase,
string commandPath,
string commandArguments,
ref Process newProcess)
// needed to create a new process
SecurityAttributes sa = new SecurityAttributes();
sa.InheritHandle = false;
sa.SecurityDescriptor = IntPtr.Zero;
sa.Length = Marshal.SizeOf(sa);

// bind the new process to the interactive desktop
StartupInfo si = new StartupInfo();
si.Desktop = "WinSta0\\Default";
si.Size = Marshal.SizeOf(si);
string targetProcess = @"C:\\Program Files\\Sudowin\\Server\\Sudowin.CreateTargetProcess.exe";
// build a formatted command path to call the Sudowin.ConsoleApplication with
string fcp = string.Format(

// i took this out for now until i decide whether or not
// i want to bother with command line switches in the callback
// application
//"\"{0}\" -c -p \"{1}\" \"{2}\" {3}",

"\"{0}\" \"{1}\" \"{2}\" {3}",
commandPath, commandArguments);

ProcessInformation pi;
bool newProcessCreated = Native.CreateProcessAsUser(
ref sa, ref sa,
(int)ProcessCreationFlags.CreateNoWindow | (int)ProcessPriorityTypes.Normal,
IntPtr.Zero, null, ref si, out pi);

if (newProcessCreated)
// get a managed reference to the process
newProcess = Process.GetProcessById(pi.ProcessId);
// free the unmanaged handles
return (newProcessCreated);

/// <summary>
/// Retrieves the logon token for the user that is
/// logged into the computer with a user name that is
/// equal to the parameter userName.
/// </summary>
/// <param name="userName">
/// User name to get token for.
/// </param>
/// <param name="userToken">
/// User logon token.
/// </param>
/// <returns>
/// True if the token was retrieved, otherwise false.
/// </returns>
private bool QueryUserToken(string userName, ref IntPtr userToken)
// open a handle to the localhost
IntPtr hSvr = WtsApi32.Native.WtsOpenServer(null);

// get a list of the sessions on the localhost
WtsApi32.WtsSessionInfo[] wsis;
wsis = WtsApi32.Managed.WtsEnumerateSessions(hSvr);
catch (Win32Exception e)
return (false);

// check all the sessions on the server to get the logon token
// of the user that has the same user name as the userName parameter
for (int x = 0; x < wsis.Length && userToken == IntPtr.Zero; ++x)
// declare 2 strings to hold the user name and domain name
string un = string.Empty, dn = string.Empty;

// compare the session's user name with the userName
// parameter and get the logon token if they are equal
if (WtsApi32.Managed.WtsQuerySessionInformation(
hSvr, wsis[x].SessionId,
out un)


hSvr, wsis[x].SessionId,
out dn)


((dn.ToLower() + "\\" + un.ToLower()) == userName.ToLower()))
WtsApi32.Native.WtsQueryUserToken(wsis[x].SessionId, ref userToken);

if (hSvr != IntPtr.Zero)

return (userToken != IntPtr.Zero);

Reference: http://www.dlldump.com/download-dll-files_new.php/dllfiles/W/wtsapi32.dll/5.1.2600.2180/download.html


Guest Author: Simon06 Mar 2014

Can't find WtsApi32.NET.dll and WtsApi32.dll won't add as a reference. Really annoying as I could really do nothing with this code!

  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name: