Background
I am working on a side software project for my company that involves
managing and administrating several computers in a lab. The project
currently uses VB.NET 2005. One aspect of my project involves
providing command line access from a lab computer to a central data
collection computer. This functionality has already been accomplished
by use of creating a service running under the SYSTEM account and
netcat (http://netcat.sourceforge.net/). Basically what happens is
when the lab computer is booted; a Windows service starts and creates a
netcat session with the central computer. The central machine already
has a netcat listener running so when the request comes in, an instant
command prompt of the lab computer is given on the central machine.
This solution has been thoroughly tested, signed off on, and works
great so there can not be any changes to this part of the project.
Here comes the problem. The netcat session is running under the
context of SYSTEM, localsystem, or NT Authority. As some of you may
know, the SYSTEM account is noninteractive and does not have access to
the default desktop. Let's take for example you wanted to start
Notepad from this session. Enter the command and nothing happens.
This is because SYSTEM can not access WINSTA0 and no commands with
graphics or forms can be run.
The next phase of our project involves running interactive programs on
the desktop of any user that happens to be logged in (and perhaps those
who are not). From experiments I have found that a netcat session
running under the currently logged in user is able to run all GUI
programs. My dilemma is creating a program that can be run under the
SYSTEM service and launch a program or another netcat session with
alternate credentials.
As a side note, Microsoft does provide a well know utility called
runas. This is of course what I would use but I have found that it
will not work under a netcat session. After entering the command, the
password is never asked for and it dumps me right back to the prompt.
I have also tried several other third-party runas utilities such as
sanur and CPAU but none of them works either.
Requirements
1. Parent process running under SYSTEM context from Windows service.
2. Child process must run under alternate credentials and be able to
launch a GUI application or another netcat instance.
3. Child process window must have the ability to start without a
window.
4. Run under Windows XP SP2.
5. Child process should have access to the default desktop.
6. Program written in VB.NET, .NET framework 2.0. Desired but I will
take anything in .NET (C#), C++, or C
Methods
Over the course of several weeks I have tried many different things.
Here is what I have gone through.
Method 1 - .NET Process Class
This is the simplest way to create another process. This is not meant
to create a process under another user but more of a reality check.
Some interesting points are found by running the program under both a
normal account (running straight from Visual Studio IDE) and the SYSTEM
account. Under a normal account a DOS window briefly flashes and the
program runs as expected. This is still a bug as the CreateNoWindow
property is set to True and a window is still created. Under the
SYSTEM account the same program starts a netcat session but never
connects to the listener.
Problem: No alternate credentials
Method 2 - .NET Process Class Using Username, Domain, and Password
.NET 2.0 added a new feature to the framework that allows programmers
to spawn a process all within .NET. Just one problem, there is a
bigger bug. Even if the CreateNoWindow property is set to True, a
window is still created and this time it stays maximized. Under the
SYSTEM account an exception is thrown
"System.ComponentModel.Win32Exception: Access is denied."
According to MSDN
(http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.startinfo.aspx),
System.Diagnostics.Process is just a wrapper for the
CreateProcessWithLogonW API. As I will explain later this presents its
own problems. Microsoft also mentions that even though
WindowStyle=hidden and CreateNoWindow=True, a window will still be
created. I have seen in other articles that this is not intentional
but a bug.
Problem: Exception thrown, Window in normal account.
Method 3 - Windows API LogonUser and CreateProcessAsUser
>From everything I have read this should be the one that works no matter
what but alas it does not. My primary guide to this method is by K.
Scott Allen
(http://odetocode.com/Blogs/scott/archive/2004/10/28/602.aspx). This
method uses two API functions, LogonUser and CreateProcessAsUser.
LogonUser acquires a security token from the kernel. That token is
then passed to CreateProcessAsUser along with what program and
arguments to run. Under a normal account I get a 1314 -
ERROR_PRIVILEGE_NOT_HELD
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1300-1699_.asp)
when CreateProcessAsUser is called. When running under SYSTEM I get
1307 - ERROR_INVALID_OWNER when CreateProcessAsUser is called.
Problem: 1307 under SYSTEM, 1314 under normal account.
Method 4 - Windows API LogonUser, DuplicateTokenEx, and
CreateProcessAsUser
This is a slight change from method 3 as DuplicateTokenEx is added and
is still the front runner for a finial solution. DuplicateTokenEx
transforms the token retrieved from LogonUser into a primary token.
Once again a 1314 is thrown under a normal account. Under the SYSTEM
account a 1004 - ERROR_INVALID_FLAGS error is thrown on
DuplicateTokenEx and 1307 is thrown on CreateProcessAsUser.
A few interesting problems pop up when using this solution. For one,
the command to launch can be passed two different ways, through
lpApplicationName or lpCommandLine. MSDN says that lpApplicationName
can be used to pass the command name and lpCommandLine for the
arguments. You can also set lpApplicationName to nothing and pass both
the command and arguments through lpCommandLine. I have tried both
methods and I have not found any combination that works. Under certain
variations I also get a 2 - ERROR_FILE_NOT_FOUND / 5 -
ERROR_ACCESS_DENIED on LogonUser and 2 - ERROR_FILE_NOT_FOUND for
CreateProcessAsUser. I have also used a known good application
(notepad) and location to add to the mix and confirm the results.
Once again according to MSDN documentation
(http://support.microsoft.com/?id=285879) certain permissions must be
set for both the calling account and alternate account. When running
under SYSTEM, the calling account should have all permissions as it is
the OS. Also the alternate account should have all the desired
permissions because MAXIMUM_ALLOWED is set in DuplicateTokenEx.
Perhaps there is another API that I must call to set these but I have
not found one yet. Also there might be an API that could check the
permissions?
Problem: 1004, 1307, 2 under SYSTEM, 1314, 2, 5 under normal account.
Method 5 - Windows API LogonUser, DuplicateTokenEx, and
CreateProcessAsUserW
This is the same as method 4 but uses the Unicode version of
CreateProcessAsUser. I have read in several forums that this will
solve the problem under Windows XP. A normal account produces a 2 -
ERROR_FILE_NOT_FOUND under CreateProcessAsUserW. Under SYSTEM 1004 is
thrown for DuplicateTokenEx and 2 for CreateProcessAsUser.
Additionally 123 - ERROR_INVALID_NAME is thrown in some variations.
Problem: 1004, 2 under SYSTEM, 2, 5 under normal account.
Method 6 - Windows API CreateProcessWithLogonW
This API function is new 2000, XP, and 2003 Server and combines the
functions of LogonUser and CreateProcessAsUserW. From many forums,
many users accomplished their goals by using CreateProcessWithLogonW.
A caveat of CreateProcessWithLogonW is that it can't be called from
the SYSTEM account according to the MSDN documentation
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createprocesswithlogonw.asp)
which defeats the purpose of my program.
Under a normal account, the program almost makes due. A window is
created (which I think I can fix by tweaking one of the lpStartupInfo
properties) and a nonfatal 203 - ERROR_ENVVAR_NOT_FOUND error thrown,
but it does run. Under SYSTEM a 203 is thrown but nothing happens.
Problem: CreateProcessWithLogonW will not run under SYSTEM account
Method 7 - The Kitchen Sink
I have seen many different variations on method 4 floating around out
on the Internet. This is my attempt to throw everything at the wall
and see what sticks. GetProcessWindowStation, OpenWindowStation,
SetProcessWindowStation, and OpenDesktop have been added to the mix.
The bottom line is CreateProcessAsUser is throws a 1314 error and
GetProcessWindowStation throws a 5 - ERROR_ACCESS_DENIED. Under the
normal account. Under SYSTEM GetProcessWindowStation throws a 2 -
ERROR_FILE_NOT_FOUND and a 1307 for CreateProcessAsUser.
Problem: 2, 1307 under SYSTEM, 5, 1314 under normal account.
Method 7 - .NET Impersionation
I quickly saw that this was not going to work. You can set a section
of code to run under differed credentials but you can not start a new
process under different credentials. I figured I would just throw this
one in for completeness.
Problem: No alternate credentials
Possible Fixes?
· Perhaps the command to be processed is not formatted correctly. I
have also tried a known good application (notepad) and usually get the
same results.
· Additional permissions must be added to the account but I don't
know what the API would be to do this.
· Additional API's needed?
Conclusion
It appears that everything was OK in Microsoft land until SP2 and
Windows 2003 hit the market. Apparently Microsoft purposely sabotaged
some of their API's so that you can not easily spawn a process with
alternate credentials from the SYSTEM account. There has to be a way
of doing this, surely Microsoft didn't paint themselves into a corner
on this one. What happens if the OS wants to create a process under a
different user (such as when a service is started under an account)?
Sorry for such a long article but I wanted to show how completely I
have researched this problem. Any constructive suggestions are
welcomed with open arms and if you have a working example then I will
be your new best friend.
Code is provided below. I did not run each method concurrently, I
simply commented out methods and tested one at a time. You may get 6 -
ERROR_INVALID_HANDLE if LogonUser is called more than once. You will
have to replace user/pass where needed.
Full Project: http://www.ycoderscookbook.com/Files/raex.rar
Code
Option Strict On
Option Explicit On
Imports System
Imports System.Runtime.InteropServices
Imports System.Security.Principal
Imports System.Security.Permissions
Imports System.Threading
<Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum,
UnmanagedCode:=True), _
Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum,
Name:="FullTrust")>
Module raex
Dim strUser As String = Nothing
Dim strPassword As String = Nothing
Dim strServer As String = "192.168.1.109"
Dim strPort As String = "2000"
Dim strApplication As String = Nothing
#Region "Const"
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const WINSTA_ALL_ACCESS As Integer = &H37F
Const READ_CONTROL As Integer = &H20000
Const WRITE_DAC As Integer = &H40000
Const DESKTOP_WRITEOBJECTS As Integer = &H80
Const DESKTOP_READOBJECTS As Integer = &H1
Const GENERIC_ALL As Integer = &H10000000
Const MAXIMUM_ALLOWED As Integer = &H2000000
Const SECURITY_IMPERSONATION As Integer = 2
Const TOKEN_PRIMARY As Integer = 1
Const LOGON_NETCREDENTIALS_ONLY As Integer = &H1&
Const CREATE_DEFAULT_ERROR_MODE As Integer = &H4000000
#End Region
#Region "Structures"
Public Structure PROCESS_INFO
Public hProcess As IntPtr
Public hThread As IntPtr
Public dwProcessId As Integer
Public dwThreadId As Integer
End Structure
Public Structure STARTUP_INFO
Public cb As Integer
Public lpReserved As Integer
<MarshalAs(UnmanagedType.LPTStr)> Public lpDesktop As String
<MarshalAs(UnmanagedType.LPTStr)> Public lpTitle As String
Public dwX As Long
Public dwY As Integer
Public dwXSize As Integer
Public dwYSize As Integer
Public dwXCountChars As Integer
Public dwYCountChars As Integer
Public dwFillAttribute As Integer
Public dwFlags As Integer
Public wShowWindow As Short
Public cbReserved2 As Short
Public lpReserved2 As Integer
Public hStdInput As Integer
Public hStdOutput As Integer
Public hStdError As Integer
End Structure
Public Structure SECURITY_ATTRIBUTES
Public nLength As Integer
Public lpSecurityDescriptor As IntPtr
Public bInheritHandle As Boolean
End Structure
#End Region
#Region "API Imports"
<DllImport("C:\\Windows\\System32\\advapi32.dll")> _
Public Function
CreateProcessWithLogonW(<MarshalAs(UnmanagedType.LPWStr)> ByVal
lpUsername As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpDomain As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpPassword As String, _
ByVal dwLogonFlags As
Integer, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpApplicationName As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpCommandLine As String, _
ByVal lpCreationFlags As
Integer, _
ByVal lpVoid As Integer, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpCurrentDirectory As String, _
ByRef lpStartupInfo As
STARTUP_INFO, _
ByRef lpProcessInfo As
PROCESS_INFO) As Integer
End Function
<DllImport("C:\\Windows\\System32\\advapi32.dll")> _
Public Function LogonUser(ByVal lpUsername As String, _
ByVal lpDomain As String, _
ByVal lpPassword As String, _
ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, _
ByRef pToken As IntPtr) As Boolean
End Function
<DllImport("C:\\Windows\\System32\\user32.dll",
SetLastError:=True)> _
Public Function GetProcessWindowStation() As IntPtr
End Function
<DllImport("C:\\Windows\\System32\\user32.dll",
SetLastError:=True)> _
Public Function OpenWindowStation(ByVal lpszWinSta As String, _
ByVal fInherit As Boolean, _
ByVal dwDesiredAccess As UInteger)
As IntPtr
End Function
<DllImport("C:\\Windows\\System32\\user32.dll",
SetLastError:=True)> _
Public Function SetProcessWindowStation(ByVal hWinSta As IntPtr) As
Boolean
End Function
<DllImport("C:\\Windows\\System32\\user32.dll",
SetLastError:=True)> _
Public Function OpenDesktop(ByVal lpszDesktop As String, _
ByVal dwFlags As Integer, _
ByVal fInherit As Boolean, _
ByVal dwDesiredAccess As UInteger) As
IntPtr
End Function
<DllImport("C:\\Windows\\System32\\advapi32.dll",
SetLastError:=True)> _
Public Function ImpersonateLoggedOnUser(ByVal hToken As IntPtr) As
Boolean
End Function
<DllImport("C:\\Windows\\System32\\advapi32.dll",
SetLastError:=True)> _
Public Function CreateProcessAsUser(ByVal pToken As IntPtr, _
ByVal lpApplicationName As String,
_
ByRef lpCommandLine As String, _
ByRef lpProcessAttributes As
SECURITY_ATTRIBUTES, _
ByRef lpThreadAttributes As
SECURITY_ATTRIBUTES, _
ByVal bInheritHandles As Boolean, _
ByVal dwCreationFlags As Integer, _
ByRef lpEnvironment As IntPtr, _
ByVal lpCurrentDirectory As String,
_
ByRef lpStartupInfo As
STARTUP_INFO, _
ByRef lpProcessInfo As
PROCESS_INFO) As Boolean
End Function
<DllImport("C:\\Windows\\System32\\advapi32.dll",
SetLastError:=True)> _
Public Function CreateProcessAsUserW(ByVal pToken As IntPtr, _
ByVal lpApplicationName As String, _
ByRef lpCommandLine As String, _
ByRef lpProcessAttributes As
SECURITY_ATTRIBUTES, _
ByRef lpThreadAttributes As
SECURITY_ATTRIBUTES, _
ByVal bInheritHandles As Boolean, _
ByVal dwCreationFlags As Integer, _
ByRef lpEnvironment As IntPtr, _
ByVal lpCurrentDirectory As String, _
ByRef lpStartupInfo As STARTUP_INFO, _
ByRef lpProcessInfo As PROCESS_INFO) As
Boolean
End Function
<DllImport("C:\\Windows\\System32\\advapi32.dll",
SetLastError:=True)> _
Public Function DuplicateTokenEx(ByVal hExistingToken As IntPtr, _
ByVal dwDesiredAccess As UInteger,
_
ByRef lpTokenAttributes As
SECURITY_ATTRIBUTES, _
ByVal ImpersonationLevel As
Integer, _
ByVal TokenType As Integer, _
ByRef phNewToken As IntPtr) As
Boolean
End Function
#End Region
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")>
_
Sub Main()
Try
Dim bReturn As Boolean
Dim strNC As String = System.Environment.CurrentDirectory +
"\nc.exe "
Dim strNCArgs As String = strServer + " " + strPort + " -e
cmd.exe"
Dim strNotepad As String = "c:\windows\notepad.exe"
'token returned from LogonUser and CreateProcessAsUser
Dim pUserToken As IntPtr = IntPtr.Zero
'Security attributes struct
Dim pSecurityAttributes As SECURITY_ATTRIBUTES
pSecurityAttributes.bInheritHandle = True
pSecurityAttributes.nLength =
Marshal.SizeOf(pSecurityAttributes)
pSecurityAttributes.lpSecurityDescriptor = IntPtr.Zero
'Start information struct
Dim pStartInfo As STARTUP_INFO = Nothing
pStartInfo.cb = Len(pStartInfo)
pStartInfo.lpTitle = ""
pStartInfo.dwFlags = 0&
pStartInfo.lpDesktop = "winsta0\default"
'Process information struct
Dim pProcessInfo As PROCESS_INFO
'Enviroment variable
Dim pEnviroment As IntPtr = IntPtr.Zero
'Method 1 - Use the built in .NET process class no user
startProcessNoUser()
'method 2 - .NET with new 2.0 user and password
startProcess()
'method 3 - Windows API LogonUser and CreateProcessAsUser
bReturn = LogonUser("U3er", ".", "Pa33Word",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, pUserToken)
System.Console.WriteLine("Method 3 LogonUser - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = CreateProcessAsUser(pUserToken,
System.Environment.CurrentDirectory + "\nc.exe", strServer + " " +
strPort + " -e cmd.exe", Nothing, Nothing, False, 0, Nothing,
System.Environment.CurrentDirectory, pStartInfo, pProcessInfo)
System.Console.WriteLine("Method 3 CreateProcessAsUser - "
+ CStr(Marshal.GetLastWin32Error()))
System.Console.WriteLine()
'Method 4 - Same as 3 but add DuplicateTokenEx after
LogonUser
'Primary token
Dim DupedToken As IntPtr = IntPtr.Zero
bReturn = LogonUser("U3er", ".", "Pa33Word",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, pUserToken)
System.Console.WriteLine("Method 4 LogonUser - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = DuplicateTokenEx(pUserToken, MAXIMUM_ALLOWED,
pSecurityAttributes, SECURITY_IMPERSONATION, TOKEN_PRIMARY, DupedToken)
System.Console.WriteLine("Method 4 DuplicateTokenEx - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = CreateProcessAsUser(pUserToken, strNC, strNCArgs,
pSecurityAttributes, pSecurityAttributes, False, 0, Nothing,
System.Environment.CurrentDirectory, pStartInfo, pProcessInfo)
System.Console.WriteLine("Method 4 CreateProcessAsUser - "
+ CStr(Marshal.GetLastWin32Error()))
System.Console.WriteLine()
'Method 5 - Same as 4 but use the unicode version of
CreateProcessAsUser (CreateProcessAsUserW)
bReturn = LogonUser("U3er", ".", "Pa33Word",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, pUserToken)
System.Console.WriteLine("Method 5 LogonUser - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = DuplicateTokenEx(pUserToken, MAXIMUM_ALLOWED,
pSecurityAttributes, SECURITY_IMPERSONATION, TOKEN_PRIMARY, DupedToken)
System.Console.WriteLine("Method 5 DuplicateTokenEx - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = CreateProcessAsUserW(pUserToken, strNC,
strNCArgs, pSecurityAttributes, pSecurityAttributes, False, 0, Nothing,
System.Environment.CurrentDirectory, pStartInfo, pProcessInfo)
System.Console.WriteLine("Method 5 CreateProcessAsUserW - "
+ CStr(Marshal.GetLastWin32Error()))
System.Console.WriteLine()
'Method 6 - Use the API CreateProcessWithLogonW
Dim iReturn As Integer
iReturn = CreateProcessWithLogonW("U3er",
System.Environment.MachineName, "Pa33Word", LOGON_NETCREDENTIALS_ONLY,
Nothing, System.Environment.CurrentDirectory + strNC + " " + strNCArgs,
CREATE_DEFAULT_ERROR_MODE, Nothing,
System.Environment.CurrentDirectory, pStartInfo, pProcessInfo)
System.Console.WriteLine("Method 6 CreateProcessWithLogonW
- " + CStr(Marshal.GetLastWin32Error()))
System.Console.WriteLine()
'Method 7 - APIs with everything but the kitchen thrown in
Dim hwinstaSave As IntPtr
Dim hwinsta As IntPtr
Dim hdesk As IntPtr
hwinstaSave = GetProcessWindowStation()
System.Console.WriteLine("Method 7 GetProcessWindowStation
- " + CStr(Marshal.GetLastWin32Error()))
hwinsta = OpenWindowStation("winsta0", False,
WINSTA_ALL_ACCESS)
System.Console.WriteLine("Method 7 OpenWindowStation - " +
CStr(Marshal.GetLastWin32Error()))
SetProcessWindowStation(hwinsta)
System.Console.WriteLine("Method 7 SetProcessWindowStation
- " + CStr(Marshal.GetLastWin32Error()))
hdesk = OpenDesktop("default", 0, False, READ_CONTROL And
WRITE_DAC And DESKTOP_WRITEOBJECTS And DESKTOP_READOBJECTS)
System.Console.WriteLine("Method 7 OpenDesktop - " +
CStr(Marshal.GetLastWin32Error()))
SetProcessWindowStation(hwinstaSave)
System.Console.WriteLine("Method 7 SetProcessWindowStation
- " + CStr(Marshal.GetLastWin32Error()))
'use method 4
bReturn = LogonUser("U3er", ".", "Pa33Word",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, pUserToken)
System.Console.WriteLine("Method 7 LogonUser - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = DuplicateTokenEx(pUserToken, MAXIMUM_ALLOWED,
pSecurityAttributes, SECURITY_IMPERSONATION, TOKEN_PRIMARY, DupedToken)
System.Console.WriteLine("Method 7 DuplicateTokenEx - " +
CStr(Marshal.GetLastWin32Error()))
bReturn = CreateProcessAsUser(pUserToken, strNC, strNCArgs,
Nothing, Nothing, False, 0, Nothing,
System.Environment.CurrentDirectory, pStartInfo, pProcessInfo)
System.Console.WriteLine("Method 7 CreateProcessAsUser - "
+ CStr(Marshal.GetLastWin32Error()))
System.Console.WriteLine()
'Method 8 - Use some crazy ideas from .NET to set
impersonation
'get token from LogonUser API
bReturn = LogonUser("U3er", ".", "Pa33Word",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, pUserToken)
System.Console.WriteLine("Method 8 LogonUser - " +
CStr(Marshal.GetLastWin32Error()))
Dim newId As New WindowsIdentity(pUserToken)
Dim impersonatedUser As WindowsImpersonationContext =
newId.Impersonate()
'Use method 1
startProcessNoUser()
Console.ReadKey()
Catch ex As Exception
Console.WriteLine(" Exception thrown " + ex.ToString)
End Try
End Sub
Public Sub startProcessNoUser()
Try
Dim p As New Process
p.StartInfo.Arguments = strServer + " " + strPort + " -e
cmd.exe"
p.StartInfo.CreateNoWindow = True
p.StartInfo.ErrorDialog = False
p.StartInfo.FileName = System.Environment.CurrentDirectory
+ "\nc.exe"
p.StartInfo.UseShellExecute = False
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
p.StartInfo.RedirectStandardOutput = True
Console.WriteLine("Method 1 .NET No User - Command: " +
p.StartInfo.FileName + " " + p.StartInfo.Arguments)
p.Start()
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
Public Sub startProcess()
Try
Dim p As New Process
p.StartInfo.UserName = "U3er"
Dim ssPass As New System.Security.SecureString
Dim c As Char
For Each c In "Pa33Word"
ssPass.AppendChar(c)
Next
p.StartInfo.Password = ssPass
p.StartInfo.Domain = System.Environment.MachineName
p.StartInfo.Arguments = strServer + " " + strPort + " -e
cmd.exe"
p.StartInfo.CreateNoWindow = True
p.StartInfo.ErrorDialog = False
p.StartInfo.FileName = System.Environment.CurrentDirectory
+ "\nc.exe"
p.StartInfo.UseShellExecute = False
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
p.StartInfo.RedirectStandardOutput = True
Console.WriteLine("Method 1 .NET No User - User: " +
p.StartInfo.Domain + "\" + p.StartInfo.UserName + " Command: " +
p.StartInfo.FileName + " " + p.StartInfo.Arguments)
p.Start()
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
End Module
However, when it concerns starting interactive programs as SYSTEM -
there was an old utility from Keith Brown (ca 1999) - assystem (if my
memory serves me right) that did exactly that.
I also have my old sample utility CreateProcessAsUser that does that
and is available together with source code
here:http://www.harper.no/valery/oldsite/CreateProcessAsUser.zip. My
utility can start interactive programs as any user or as SYSTEM and
grants all necessary access rights to the winstation/desktop.
hope this will help you to solve your problems,
-valery.
http://www.harper.no/valery
tan...@gmail.com wrote: