C# run executable from remote server on remote client - c#

I have the following function for connecting to a remote client machine and running an executable on it.
I copied it from a response on this site, but don't have the link anymore, so I'm not sure who to give credit to.
public static void ConnectToRemoteClient(string client_machine, string user, string password, string target_exe )
{
var connection = new ConnectionOptions();
// The '.\' is for a local user on the remote machine
// or 'mydomain\user' for a domain user
connection.Username = user;
connection.Password = password;
object[] theProcessToRun = { target_exe };
var wmiScope = new ManagementScope($#"\\{client_machine}\root\cimv2", connection);
wmiScope.Connect();
using (var managementClass = new ManagementClass(wmiScope, new ManagementPath("Win32_Process"), new ObjectGetOptions()))
{
managementClass.InvokeMethod("Create", theProcessToRun );
}
}
It is called using the following syntax:
string exe = string.Format("taskkill.exe {0} {1}", #"/F", #"/PID 8704");
ConnectToRemoteClient("ClientMachine", #"Domain\Username", #"password", exe);
It works just fine for executables that exist on the remote client machine.
However, I want to call an executable from a server, and run it on that remote client machine.
Not sure how best to approach this. I tried feeding it the following:
ConnectToRemoteClient("ClientMachine", #"Domain\User", #"password", #"\\ServerName\MyDir\Myfile.exe");
But it never initiated the executable on the machine. No error messages.
The reason I want to do this, is to save me from having to copy the large executable and supporting files to each client, but rather just run it from the server depot on each remote client.
Do I have to call a CMD window and feed it the \\ServerName\MyDir\Myfile.exe in order to get it to work properly? or is there a way I can make this work?

You are connecting to the remote machine using the passed credentials, but that only establishes your rights to open WMI. The command you then pass to WMI to execute is not running as the credentials you pass in, but under the LocalSystem account credentials.
LocalSystem does not have access to the network share.
To do this you need to remotely execute PSEXEC (https://ss64.com/nt/psexec.html) which allows you to pass the parameters to launch the application as. PSEXEC runs as LocalSystem but allows you to pass credentials to use when it launches your designated application. The launched program will then impersonate the user you pass in, and will have access to the network share.

Related

Retrieve processes information remote computer using C#

I'm developing a desktop application using C# language. I'm trying to retrieve all the current active processes on the remote computer with the following code:
else if (infocomboBox.SelectedIndex == 2)
{
string compname = compnameLabel.Text;
Process[] remoteAll = Process.GetProcesses(compnameLabel.Text);
foreach (Process process in remoteAll)
{
ListViewItem item = new ListViewItem(process.ProcessName);
item.Tag = process;
listProcessView.Items.Add(item);
}
}
I put the code inside the button_click function.
I can't seem to retrieve it with an error saying "InvalidOperationException was unhandled"
"Couldn't connect to remote machine"
Log in username and password is disabled on the remote computer. Firewall and antivirus are off also.
Refer below for the error screenshot
Screenshot of the error
What is exactly the problem? Can anybody give solution?
Thank you very much in advance!
I would try to verify from a command line that the hostname is resolvable.
ping theOtherComputerName
If that resolves to an IP address and responds then you've eliminated one possible issue. Next up would have to be connection issues.
I believe the GetProcesses command tries to login to the remote machine using the current username and password, so you would need the same username and password on the other machine,
OR you'll need to impersonate an admin user on the remote machine doing something like this impersonate user in c#

WMI remote connect in c# uses wrong username

I'm trying to create program in C#, that will retrieve some data from local or remote server. Local part is working great, remote connection does not at all. I'm getting access denied.
Here is the code
public void ConnectToWmi()
{
var options = new ConnectionOptions();
options.Username = "admin";
options.Password = "admin";
options.Impersonation = ImpersonationLevel.Impersonate;
options.EnablePrivileges = true;
var scope = new ManagementScope("\\SERVER_NAME\root\cimv2",options);
scope.Connect();
}
I have verified using wbemtest.exe, that connection acctually works.
When I examinated both connections using Wireshark I noticed strange thing - wbemtest is sending correct username "admin" but my program is sending username of current user logged on computer.
So i experimented a little and created administrator account with credentials username "admin" password "admin" on computer that I'm running my program on. And it works!
So in short: Why is my C# program using credentials of currently logged in user instead of credentials that I supplied to it in the code?
more info
server is running as virtual machine in Hyper V on my notebook
client OS is win 8.1, server is win 7
connection between client and server works and all firewalls are disabled

Problem with remote install by WMI : the installation package is not accessible form the remote machine

I want to install a MSI package on a remote computer.
The local and remote computer both are members of a domain called "adn.lan"
and the user/password I pass as parameter to connection has full access to remote machine.
When I set connection.Authority to "ntdlmdomain:adran.lan" the return parameter shows the "Invalid parameter" and when I leave it as null and make it as remarked, the connect() would connect successfully but when it try to install package the return parameter shows that the addressed package is inaccessible.
Here is the code I've tried with.
ConnectionOptions connection = new ConnectionOptions();
//connection.Authority = "ntdlmdomain:adn.lan"; // "kerberos:" + domain + #"\" + machine;
connection.Username = username;
connection.Password = password;
//connection.Impersonation = ImpersonationLevel.Identify ;
connection.Authentication = AuthenticationLevel.Packet;
ManagementScope scope = new ManagementScope("\\\\RemoteMachineName\\root\\CIMV2", connection);
scope.Connect();
ManagementPath p = new ManagementPath("Win32_Product");
ManagementClass classInstance = new ManagementClass(scope, p, null);
ManagementBaseObject inParams = classInstance.GetMethodParameters("Install");
inParams["AllUsers"] = true;
inParams["Options"] = string.Empty;
inParams["PackageLocation"] = "\\\\LocalMachineName\\Share\\Prescription.msi";
ManagementBaseObject outParams = classInstance.InvokeMethod("Install", inParams, null);
string retVal = outParams["ReturnValue"].ToString();
When I set theconnection.Impersonation to Identity the result would be "Access denied".
If I understand your question and followup comment, you found that it would not work when the package path was on a different machine than the target machine (i.e. a UNC path, normally accessible from the target machine). But the installation works when you copy the package to the target machine and pass a local path on the target machine.
I believe the reason for the failure is due to the nature of DCOM impersonation levels.
Impersonate allows you to use the credentials of the caller on the target machine -- but not to connect from the target machine to another machine. To make that second hop using the same credentials requires Delegate level. (Problem is, that has security risks, so all the guidance says "warning warning warning" and everything makes it hard by default.)
When you asked the target machine to access the installation package on a separate network location, that was a "second hop" which would require credentials, but impersonate meant you could only use your credentials on the target machine, not passed from there to the remote file location.
TechNet has a nice summary of the impersonation levels, see Table 6.6 DCOM Impersonation Levels at the top of WMI Security Settings.
p.s. For fun, you might see if there's a way to do it without copying to the target machine. If you could find a way to expose the installation package file to the network in a way that allowed anonymous access, I wonder if that second hop would be allowed since only anonymous credentials were needed? Not sure though. And there might be an awful lot of guessing and testing going on, if you're anything like me : )

I want to copy and run .exe file on a remote Windows machine?

i have copied the exe file and it was no problem, useing the following code, but now i want to run it, can anyboyd help me on this.
NOTE: i have the access to servers through remote desktop, but cant do this manually, coz there are dozens of them, cant get a program running on it like psex or whatever.
WindowsIdentity wi = new WindowsIdentity(token);
//Next I set the WindowsImportsonationContext
WindowsImpersonationContext impctx = wi.Impersonate();
System.IO.File.Copy("C:\\output.html", "\\\\PW42\\c$\\output1.html", true);
System.Diagnostics.Process p = new System.Diagnostics.Process();
try
{
System.Diagnostics.Process.Start(#"\\PW42\c$\txt.bat");
//runFile();
}
catch
{
Console.WriteLine("error");
}
Depending on what access you have on the server you can use a program like psexec or using WMI to launch the file remotely.
A sample psexec command would be
psexec \\computername -u remoteusername filepath(on remote computer) arguments
Psexec can copy the file beforehand if requested and can run against a list of computers instead (replacing \\computername with #computer-list.txt). With WMI you need to connect to the Win32_Process class and Create a new object to start it. The second post in this thread could work.
Unfortunately both of these options require multiple firewall rules (like RPC and WMI) to be available from the running workstation. If your company only has RDP access enabled through the firewall, neither of these will probably work.

Network Authentication when running exe from WMI

I have a C# exe that needs to be run using WMI and access a network share. However, when I access the share I get an UnauthorizedAccessException. If I run the exe directly the share is accessible. I am using the same user account in both cases.
There are two parts to my application, a GUI client that runs on a local PC and a backend process that runs on a remote PC. When the client needs to connect to the backend it first launches the remote process using WMI (code reproduced below). The remote process does a number of things including accessing a network share using Directory.GetDirectories() and reports back to the client.
When the remote process is launched automatically by the client using WMI, it cannot access the network share. However, if I connect to the remote machine using Remote Desktop and manually launch the backend process, access to the network share succeeds.
The user specifed in the WMI call and the user logged in for the Remote Desktop session are the same, so the permissions should be the same, shouldn't they?
I see in the MSDN entry for Directory.Exists() it states "The Exists method does not perform network authentication. If you query an existing network share without being pre-authenticated, the Exists method will return false." I assume this is related? How can I ensure the user is authenticated correctly in a WMI session?
ConnectionOptions opts = new ConnectionOptions();
opts.Username = username;
opts.Password = password;
ManagementPath path = new ManagementPath(string.Format("\\\\{0}\\root\\cimv2:Win32_Process", remoteHost));
ManagementScope scope = new ManagementScope(path, opts);
scope.Connect();
ObjectGetOptions getOpts = new ObjectGetOptions();
using (ManagementClass mngClass = new ManagementClass(scope, path, getOpts))
{
ManagementBaseObject inParams = mngClass.GetMethodParameters("Create");
inParams["CommandLine"] = commandLine;
ManagementBaseObject outParams = mngClass.InvokeMethod("Create", inParams, null);
}
Having followed the link suggested by Isalamon above (thanks) I followed Jestro's advice and have rewritten using psexec.exe (which can be downloaded from http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx) instead of WMI. It feels like a bit of a kludge to do it this way, but it seems to work.
New code for anyone who is experiencing similar problems:
Process proc = new Process();
proc.StartInfo.FileName = "PsExec.exe";
proc.StartInfo.Arguments = string.Format("\\\\{0} -d -u {1}\\{2} -p {3} {4}",
remoteHost,
domain,
username,
password,
commandLine);
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
WMI just uses impersonation when executing the remote process, which does not give you network access. If you are ok going outside managed code, you can just map a UNC path in the remote process WMI started using whatever credentials you want. Then, you have the network access you want. I use NetUseAdd and NetUseDel from netapi32.dll to map the UNC path. See http://pinvoke.net/ for details on the using the APIs.
I know you've sorted it by using PSEXEC, which is a fantastic program, but if you did want to go back to WMI, have you tried enabling the following in your ConnectionOptions:
The flag EnablePrivileges
setting the Impersonation to ImpersonationLevel.Impersonate
Which does the following:
Gets or sets a value indicating whether user privileges need to be
enabled for the connection operation. This property should only be
used when the operation performed requires a certain user privilege to
be enabled (for example, a machine restart).
http://msdn.microsoft.com/en-us/library/system.management.connectionoptions.enableprivileges.aspx
Gets or sets the COM impersonation level to be used for operations in this connection.
http://msdn.microsoft.com/en-us/library/system.management.connectionoptions.impersonation.aspx
I think they should tell your WMI to actually allow the program to have the correct credentials and thus access your network share
You can write all you commands to batch file to the remote machine which includes net use (no need to use a drive letter) to do an authentication. Works fine that way. I am still working on an alternative.

Categories

Resources