1 year ago
#147181
MonEr
Call SetTokenInformation always returns False
I'm trying to create a new process using CreateProcessWithTokenEx
on Session 1 using the following code (Powershell which runs C#):
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION {
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct SECURITY_DESCRIPTOR {
public byte revision;
public byte size;
public short control;
public IntPtr owner;
public IntPtr group;
public IntPtr sacl;
public IntPtr dacl;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO {
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES {
public int length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
public static class Kernel32 {
[DllImport("advapi32.dll")]
public static extern bool OpenProcessToken(IntPtr Thread, UInt32 Access, out IntPtr Handle);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
public static extern bool DuplicateTokenEx(
IntPtr ExistingTokenHandle,
uint dwDesiredAccess,
IntPtr lpThreadAttributes,
int TokenType,
int ImpersonationLevel,
ref IntPtr DuplicateTokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
public static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessWithTokenW(
IntPtr hToken,
short dwLogonFlags,
string lpApplicationName,
string lpCommandLine,
int dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public extern static bool SetTokenInformation(IntPtr handle, uint tokenInformationClass, IntPtr dwSessionId, uint tokenInformationLegnth);
}
"@
$userProcess = Get-WmiObject -Class Win32_Process -Filter 'Name = "explorer.exe"' | select -First 1
$marshal = [System.Runtime.InteropServices.Marshal]
$si = New-Object STARTUPINFO
$si.wShowWindow = 5
$si.lpDesktop = "winsta0\default"
$si.cb = $marshal::SizeOf($si)
$sd = New-Object SECURITY_DESCRIPTOR
$sd.revision = 1
$sd.control = 4
$userToken = [IntPtr]0
$process = Get-Process -id $userProcess.ProcessId
$null = [kernel32]::OpenProcessToken($process.Handle, 2, [ref]$userToken)
$token = [IntPtr]0
$null = [kernel32]::DuplicateTokenEx($userToken, 0xFFFF, 0, 2, 1, [ref]$token)
$env = [intPtr]0
$null = [kernel32]::CreateEnvironmentBlock([ref]$env, $token, $false)
$dwSessionId = [IntPtr]1
$tokenSessionClassId = 12
[kernel32]::SetTokenInformation($token, $tokenSessionClassId, $dwSessionId, [IntPtr]::Size)
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
$pi = New-Object PROCESS_INFORMATION
$null = [kernel32]::CreateProcessWithTokenW($token, 1, "C:\windows\my.exe", $null, 0x0410, $env, "c:", [ref]$si, [ref]$pi)
The problem, my process created with SessionId=0 and not SessionId=1, When I'm trying to change the SessionId using SetTokenInformation
The return value is always False
and the return value of GetLastWin32Error()
is 203-ERROR_ENVVAR_NOT_FOUND
What I'm doing wrong?
Is there is a better way to create a process on Session!=0 ?
EDIT: Not sure that the error code 203 is from CreateProcessWithTokenW
function
c#
powershell
winapi
createprocess
0 Answers
Your Answer