1 year ago

#147181

test-img

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

Accepted video resources