using System;
using System.Runtime.InteropServices;
namespace WindowsImpersonation
{
/* Original C++ Structure
BOOL CreateProcessWithLogonW(
in LPCWSTR lpUsername,
in LPCWSTR lpDomain,
in LPCWSTR lpPassword,
in DWORD dwLogonFlags,
in LPCWSTR lpApplicationName,
in LPWSTR lpCommandLine,
in DWORD dwCreationFlags,
in LPVOID lpEnvironment,
in LPCWSTR lpCurrentDirectory,
in LPSTARTUPINFOW lpStartupInfo,
out LPPROCESS_INFORMATION lpProcessInfo
);
*/
/// <summary>
/// Summary description for WindowsImpersonate.
/// </summary>
public class WindowsImpersonate
{
public const int LOGON_WITH_PROFILE = 0x1;
public const int LOGON_NETCREDENTIALS_ONLY = 0x2;
public const int CREATE_DEFAULT_ERROR_MODE = 0x4000000;
public const int CREATE_NEW_CONSOLE = 0x10;
public const int CREATE_NEW_PROCESS_GROUP = 0x200;
public const int CREATE_SEPARATE_WOW_VDM = 0x800;
public const int CREATE_SUSPENDED = 0x4;
public const int CREATE_UNICODE_ENVIRONMENT = 0x400;
public const int ABOVE_NORMAL_PRIORITY_CLASS = 0x8000;
public const int BELOW_NORMAL_PRIORITY_CLASS = 0x4000;
public const int HIGH_PRIORITY_CLASS = 0x80;
public const int IDLE_PRIORITY_CLASS = 0x40;
public const int NORMAL_PRIORITY_CLASS = 0x20;
public const int REALTIME_PRIORITY_CLASS = 0x100;
[StructLayout (LayoutKind.Sequential)]
public struct LPPROCESS_INFORMATION
{
public int hProcess; //Handle to the newly created process. The handle is used to specify the process in all functions that perform operations on the process object.
public int hThread; //Handle to the primary thread of the newly created process. The handle is used to specify the thread in all functions that perform operations on the thread object.
public int dwProcessID; //Value that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated.
public int dwThreadID; //Value that can be used to identify a thread. The value is valid from the time the thread is created until the time the thread is terminated.
}
[StructLayout (LayoutKind.Sequential)]
public struct LPSTARTUPINFO
{
public int cb; //size of structure in bytes
public String lpReserved; //set to NULL - reserved;
public String lpDesktop; //specifies either the name of the desktop, or the name of both the desktop and window station for this process
public String lpTitle; //title displayed in the title bar if a new console window is created
public int dwX; //If dwFlags specifies STARTF_USEPOSITION, this member is the x offset of the upper left corner of a window if a new window is created, in pixels. Otherwise, this member is ignored.
public int dwY; //If dwFlags specifies STARTF_USEPOSITION, this member is the y offset of the upper left corner of a window if a new window is created, in pixels. Otherwise, this member is ignored.
public int dwXSize; //If dwFlags specifies STARTF_USESIZE, this member is the width of the window if a new window is created, in pixels. Otherwise, this member is ignored.
public int dwYSize; //If dwFlags specifies STARTF_USESIZE, this member is the height of the window if a new window is created, in pixels. Otherwise, this member is ignored.
public int dwXCountChars; //If dwFlags specifies STARTF_USECOUNTCHARS, if a new console window is created in a console process, this member specifies the screen buffer width, in character columns. Otherwise, this member is ignored.
public int dwYCountChars; //If dwFlags specifies STARTF_USECOUNTCHARS, if a new console window is created in a console process, this member specifies the screen buffer height, in character rows. Otherwise, this member is ignored.
public int dwFillAttribute; //If dwFlags specifies STARTF_USEFILLATTRIBUTE, this member is the initial text and background colors if a new console window is created in a console application. Otherwise, this member is ignored. This value can be any combination of the following values: FOREGROUND_BLUE, FOREGROUND_GREEN, FOREGROUND_RED, FOREGROUND_INTENSITY, BACKGROUND_BLUE, BACKGROUND_GREEN, BACKGROUND_RED, and BACKGROUND_INTENSITY.
public int dwFlags; //Flags
public int wShowWindow; //If dwFlags specifies STARTF_USESHOWWINDOW, this member can be any of the SW_ constants defined in Winuser.h. Otherwise, this member is ignored.
public int cbReserved2; //Reserved for use by the C Runtime; must be zero.
public int lpReserved2; //Reserved for use by the C Runtime; must be NULL.
public int hStdInput; //If dwFlags specifies STARTF_USESTDHANDLES, this member is a handle to be used as the standard input handle for the process. Otherwise, this member is ignored.
public int hStdOutput; //If dwFlags specifies STARTF_USESTDHANDLES, this member is a handle to be used as the standard output handle for the process. Otherwise, this member is ignored.
public int hStdError; //If dwFlags specifies STARTF_USESTDHANDLES, this member is a handle to be used as the standard error handle for the process. Otherwise, this member is ignored.
}
[DllImport("Advapi32.dll", EntryPoint="CreateProcessWithLogonW", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern int CreateProcessWithLogonW(String lpUsername, String lpDomain, String lpPassword, int dwLogonFlags, String lpApplicationName, String lpCommandLine, int dwCreationFlags, String lpEnvironment, String lpCurrentDirectory, LPSTARTUPINFO lpStatupInfo, ref LPPROCESS_INFORMATION lpProcessInfo);
[DllImport("kernel32", EntryPoint="CloseHandle", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern int CloseHandle(int hObject);
public WindowsImpersonate()
{
int ret;
LPSTARTUPINFO myStartUpInfo = new LPSTARTUPINFO();
myStartUpInfo.cb = Marshal.SizeOf(myStartUpInfo);
myStartUpInfo.dwFlags = 0x0;
LPPROCESS_INFORMATION myProcessInfo = new LPPROCESS_INFORMATION();
ret = CreateProcessWithLogonW("USERNAME", "DOMAIN", "PASSWORD", LOGON_NETCREDENTIALS_ONLY, "C:/WINNT/NOTEPAD.EXE", null, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, null, null, myStartUpInfo, ref myProcessInfo);
//Close our handles to this process since we wont be the one using it
CloseHandle(myProcessInfo.hThread);
CloseHandle(myProcessInfo.hProcess);
Console.WriteLine(ret.ToString());
Console.ReadLine();
}
}
}