Hello, I wrote a windows service that is supposed to start an interactive GUI app. I realize a service will not readily do this so I've pieced together the code below to bypass that. However, the call to CreateProcessAs User always returns a 1314 error: 'A required privilege is not held by the client.'
I realize from the doc's that the calling process must have SE_TCB_NAME privilaege to assign new privileges to the new process and I have done that in a method further below.
So I'm not sure why this is not launching the app. To keep things simple, I'm running notepad.exe from a cmd console, I'm just running this code as its own app so there's no service on top to muddle things up. Also I'm running it locally to make things simpler, but still that error keeps popping up. Also I'm on XP.
Would someone that has had experience with this please tell me what's wrong? Thanks in advance!!
public static void Main(string[] args)
{
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
try
{
string userName, domainName;
//USE YOUR LOGIN INFO HERE
domainName = "mydomain";
userName = "user";
pwd="mypass";
tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;
bool returnValue = LogonUser(userN ame, domainName, pwd,
LOGON32_LOGON_I NTERACTIVE, LOGON32_PROVIDE R_DEFAULT,
ref tokenHandle);
if(false == returnValue)
{
int ret = Marshal.GetLast Win32Error();
Console.WriteLi ne("LogonUser failed with error code : {0}", ret);
int errorCode = 0x5;
throw new System.Componen tModel.Win32Exc eption(errorCod e);
}
SECURITY_ATTRIB UTES pSec = new SECURITY_ATTRIB UTES();
SECURITY_ATTRIB UTES tSec = new SECURITY_ATTRIB UTES();
pSec.nLength = Marshal.SizeOf( pSec);
tSec.nLength = Marshal.SizeOf( tSec);
bool retVal = DuplicateTokenE x(tokenHandle, (uint)TokenAcce ssLevels.AllAcc ess, ref pSec,
SECURITY_IMPERS ONATION_LEVEL.S ecurityIdentifi cation, TOKEN_TYPE.Toke nPrimary,
out dupeTokenHandle );
if(false == retVal)
{
CloseHandle(tok enHandle);
Console.WriteLi ne("Exception thrown in trying to duplicate token.");
return;
}
WindowsIdentity newId = new WindowsIdentity (dupeTokenHandl e);
WindowsImperson ationContext impersonatedUse r = newId.Impersona te();
PROFILEINFO aPI = new PROFILEINFO();
aPI.dwSize = 32;
aPI.lpUserName = WindowsIdentity .GetCurrent().N ame;
bool retLoadProfile = LoadUserProfile (newId.Token, ref aPI);
StringBuilder CommandLine = new StringBuilder(@ "cmd /c C:\windows\syst em32\notepad.ex e");
const uint NORMAL_PRIORITY _CLASS = 0x0020;
PROCESS_INFORMA TION pInfo = new PROCESS_INFORMA TION();
STARTUPINFO sInfo = new STARTUPINFO();
IntPtr aToken=newId.To ken;
SetPrivs(ref aToken);
sInfo.wShowWind ow = 5;
sInfo.lpTitle = "Hello!";
sInfo.lpDesktop ="winsta0\\defa ult";
uint dwCreationFlags = NORMAL_PRIORITY _CLASS| CREATE_NEW_CONS OLE;
IntPtr pEnv = IntPtr.Zero;
if(CreateEnviro nmentBlock(out pEnv, dupeTokenHandle , true))
{
dwCreationFlags |= CREATE_UNICODE_ ENVIRONMENT;
}
else
{
pEnv = IntPtr.Zero;
}
bool retCreateProces s = CreateProcessAs User(newId.Toke n,
null,
CommandLine,
ref pSec,
ref tSec,
false,
NORMAL_PRIORITY _CLASS,
pEnv,
null,
ref sInfo,
out pInfo);
int err = Marshal.GetLast Win32Error();
Console.WriteLi ne("CreateProce ss="+retCreateP rocess.ToString ()+". With error:"+ err.ToString()) ;
// Check the identity.
Console.WriteLi ne("After impersonation: " + WindowsIdentity .GetCurrent().N ame);
Console.ReadKey ();
// Stop impersonating the user.
impersonatedUse r.Undo();
// Free the tokens.
if(tokenHandle != IntPtr.Zero)
CloseHandle(tok enHandle);
if(dupeTokenHan dle != IntPtr.Zero)
CloseHandle(dup eTokenHandle);
}
catch(Exception ex)
{
Console.WriteLi ne("Exception occurred. " + ex.Message);
}
}
}
In this method as an experiment I tried setting all privileges to see if perhaps I had been missing one but generally I will be setting TCB(if that's the right one to set.)
You'll note that I'm setting the Current Process Privilage to TCB because the Doc's say that that needs to be done.
private static bool SetPrivs(ref IntPtr theToken)
{
const int SE_PRIVILEGE_EN ABLED = 0x0002;
List<string> aPrivs = new List<string>();
aPrivs.Add(SE_C REATE_TOKEN_NAM E);
aPrivs.Add(SE_A SSIGNPRIMARYTOK EN_NAME);
aPrivs.Add(SE_L OCK_MEMORY_NAME );
aPrivs.Add(SE_I NCREASE_QUOTA_N AME);
aPrivs.Add(SE_U NSOLICITED_INPU T_NAME);
aPrivs.Add(SE_M ACHINE_ACCOUNT_ NAME);
aPrivs.Add(SE_T CB_NAME);
aPrivs.Add(SE_S ECURITY_NAME);
aPrivs.Add(SE_T AKE_OWNERSHIP_N AME);
aPrivs.Add(SE_L OAD_DRIVER_NAME );
aPrivs.Add(SE_S YSTEM_PROFILE_N AME);
aPrivs.Add(SE_S YSTEMTIME_NAME) ;
aPrivs.Add(SE_P ROF_SINGLE_PROC ESS_NAME);
aPrivs.Add(SE_I NC_BASE_PRIORIT Y_NAME);
aPrivs.Add(SE_C REATE_PAGEFILE_ NAME);
aPrivs.Add(SE_C REATE_PERMANENT _NAME);
aPrivs.Add(SE_B ACKUP_NAME);
aPrivs.Add(SE_R ESTORE_NAME);
aPrivs.Add(SE_S HUTDOWN_NAME);
aPrivs.Add(SE_D EBUG_NAME);
aPrivs.Add(SE_A UDIT_NAME);
aPrivs.Add(SE_S YSTEM_ENVIRONME NT_NAME);
aPrivs.Add(SE_C HANGE_NOTIFY_NA ME);
aPrivs.Add(SE_R EMOTE_SHUTDOWN_ NAME);
aPrivs.Add(SE_U NDOCK_NAME);
aPrivs.Add(SE_S YNC_AGENT_NAME) ;
aPrivs.Add(SE_E NABLE_DELEGATIO N_NAME);
aPrivs.Add(SE_M ANAGE_VOLUME_NA ME);
aPrivs.Add(SE_I MPERSONATE_NAME );
aPrivs.Add(SE_C REATE_GLOBAL_NA ME);
SetCurrProcPriv (SE_TCB_NAME);
foreach(string aPriv in aPrivs)
{
TOKEN_PRIVILEGE S aTP = new TOKEN_PRIVILEGE S();
LUID luid = new LUID();
aTP.PrivilegeCo unt = 1;
aTP.Privileges = new int[3];
aTP.Privileges[2] = SE_PRIVILEGE_EN ABLED;
aTP.Privileges[1] = luid.HighPart;
aTP.Privileges[0] = luid.LowPart;
try
{
LookupPrivilege Value(IntPtr.Ze ro, aPriv, ref luid);
bool isSuccess=Adjus tTokenPrivilege s(theToken, false, ref aTP, Marshal.SizeOf( aTP), IntPtr.Zero, IntPtr.Zero);
if(!isSuccess)
return false;
else
return true;
}
catch (Exception e)
{
Console.WriteLi ne(e.Message);
Console.ReadKey ();
}
}
return false;
}
private static IntPtr SetCurrProcPriv (string thePrivilegeNam e)
{
IntPtr hToken =new IntPtr();
bool isSuccess=false ;
LUID luid = new LUID();
IntPtr aCurrProc = GetCurrentProce ss();
TOKEN_PRIVILEGE S aTP=new TOKEN_PRIVILEGE S();
STARTUPINFO si=new STARTUPINFO();
si.cb = (int)Marshal.Si zeOf(si);
isSuccess = OpenProcessToke n(aCurrProc,
TOKEN_QUERY | TOKEN_ADJUST_PR IVILEGES |
TOKEN_ADJUST_SE SSIONID |TOKEN_ADJUST_D EFAULT |
TOKEN_ASSIGN_PR IMARY | TOKEN_DUPLICATE , out hToken);
if(!isSuccess)
Console.WriteLi ne("Error OpenProcessToke n " + Marshal.GetLast Win32Error().To String());
isSuccess = LookupPrivilege Value(IntPtr.Ze ro, thePrivilegeNam e, ref luid);
if(!isSuccess)
Console.WriteLi ne("Error OpenProcessToke n " + Marshal.GetLast Win32Error().To String());
aTP.PrivilegeCo unt = 1;
aTP.Privileges = new int[3];
aTP.Privileges[0] = luid.LowPart;
aTP.Privileges[1] = luid.HighPart;
aTP.Privileges[2] = SE_PRIVILEGE_EN ABLED;
isSuccess = AdjustTokenPriv ileges(hToken, false, ref aTP, Marshal.SizeOf( aTP), IntPtr.Zero, (IntPtr)Marshal .SizeOf(aTP));
if(!isSuccess)
return IntPtr.Zero;
else
return hToken;
}