How to use CACLS in c# windows service - c#

i want to block certain folder from users, using c# service. that means when you are starting the service though it is blocked or not, the final result is blocked folder. i have writen a code. but the responce is are you sure? please help to solve this
string Pathname = folder;
EventLog.WriteEntry(Pathname);
string Username = #"BUILTIN\Users";
string UserRights = "N";
if (Pathname == null || Pathname == "")
{
EventLog.WriteEntry("No File");
}
string CommandLine = '"' + System.IO.Path.GetFullPath(Pathname) + '"' + " /C ";
CommandLine += #" /T ";
CommandLine += #" /P " + Username + ":" + UserRights;
Process p = new Process();
p.StartInfo.FileName = "cacls.exe";
p.StartInfo.Arguments = CommandLine;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
p.StartInfo.CreateNoWindow = true;
p.Start();
string Response = p.StandardOutput.ReadToEnd();
EventLog.WriteEntry(Response);
if (Response == null || Response == "")
{
EventLog.WriteEntry("Error");
}

Don't call the command line cacls utility, instead use the .NET API to change permissions. Invoking command line utilities should always be seen as a last workaround for performing tasks. It is much better to access an API directly that is meant for programmatic access.
Directory.GetAccessControl(string) gets the current ACL.
Directory.SetAccessControl(string, DirectorySecurity) sets the ACL.
Generally when working with ACLs it's better to work only with granting rights and not use deny flags at all. Denying BUILTIN\Users is very broad and that deny will overrule any grant made to any user. It is better to construct an ACL that does not grant any rights to normal users and only give rights to the specific users that should have access.

You are redirecting the standard input for the CACLS process.
So you need to feed the process with your input (Like a stream.Writeline("Y");)
Look at this sample from MSDN
StreamWriter myStreamWriter = myProcess.StandardInput;
myStreamWriter.Writeline("Y"); // Could it be localized ??? -->Oui, Ja, Sì etc...
myStreamWriter.Close(); // This seems to be is important.....

Related

Psexec works on command line but not in ASP

I am using PsExec to remotely fire a program. I can fire the actual program (not displayed here) or cmd.exe remotely with no problems whatsoever from the command line. When I try to fire it from ASP and C#, it will not trigger the command prompt, even though I am using the same exact string. Here is the string I am using that works every time, and the code that doesn't. Help please!
Working String: C:\psexec \\10.0.0.25 -u Administrator -p password -d -i cmd.exe
Non-working code:
ProcessStartInfo psi = new ProcessStartInfo(#"C:\PsExec.exe")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
Arguments = #"\\10.0.0.25 -u Administrator -p password -d -i cmd.exe"
};
process.StartInfo = psi;
var success = process.Start();
One option, assuming you have control over the machine, is to setup the psexec command as a Task Scheduler job, then execute the task scheduler job from your ASP app. You can configure the task scheduler to run as an administrator, and when you fire off the job it will run under that credentials. You won't get any output that way though, so if that's an issue there may not be a good choice.
See How to run existing windows 7 task using command prompt for an example of running the task..
It's been a while since I was a system administrator, but if I recall correctly psexec has to be run from an administrative command prompt. Maybe the account your app is running under doesn't have rights to reach across the network and do stuff to a remote machine?
Put this in your Page_Load temporarily:
Response.Write(Environment.UserName);
and run it again, it should show you the name you're looking for at the top of your app.
Well, I am right now doing some automation and have figured out a few things. Please see below code maybe it will help you out
public static void PSExec_Method()
{
try
{
string userName = #"ABC";
string password = "ABC";
string remoteMachine = "ABC";
//How to restart AppPool
//string operation = "stop";
//string apppoolname = "APPPOOL";
//string command = #"%SYSTEMROOT%\System32\inetsrv\appcmd " + operation + " apppool /apppool.name:\"" + apppoolname + "\"";
string command = #"powershell -noninteractive Get-Content C:\tmp\tmp.csv -Head 5";
//string command = #"ipconfig";
string PSPath = #"C:\PSTools\PsExec.exe";
string fullcommand = PSPath + " -u " + userName + " -p " + password + " \\\\" + remoteMachine + " -h cmd.exe /c " + command;
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = fullcommand;
process.Start();
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.WriteLine(process.StandardError.ReadToEnd());
process.WaitForExit();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}

Calling Sav32Cli.exe from asp.net c# application "Code 2 - If some error preventing further execution is discover "

I have integrated Sav32Cli.exe in my asp.net c# application & its working fine in my local machine but when we move it on the testing server I am getting the following error "Code 2 - If some error preventing further execution is discover "
The scenario is If only 1 person performs the activity it works fine but concurrent connection performs the same activity then I am getting this error for some connections.
Actual scenario : We have the page where users upload the pdf file & as soon as the file is uploaded on the server we perform the scanning via sop-hos and when multiple users perform the same activity I am getting the following error : Code 2 - If some error preventing further execution is discover. So I would like to know from you guys what should I do to bypass this error & implement the scanning successfully into my application.
Below is the code I have written to integrate the scanning into my application :
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
try
{
string filePath = sFileDetails.DirectoryName + "\\" + sFileName;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "C:\\Program Files (x86)\\Sophos\\Sophos Anti-Virus\\sav32cli.exe";
startInfo.Arguments = String.Format(#" -ss ""{0}""", filePath);
process.StartInfo = startInfo;
process.StartInfo.Verb = "runas";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
string output = process.StandardOutput.ReadToEnd();
StringBuilder objStrBuilder = new StringBuilder();
objStrBuilder.AppendLine("Status " + output.ToString());
int i = process.ExitCode;
objStrBuilder.AppendLine("Code " + i.ToString());
File.WriteAllText(sFileDetails.DirectoryName + "\\" + Convert.ToString(System.Guid.NewGuid()) + ".txt", Convert.ToString(objStrBuilder));
if (i > 0)
{
return false;
}
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
process.Close();
process.Dispose();
}
Have you considered using SAVIDI for this - https://www.sophos.com/medialibrary/PDFs/partners/sophossavdidsna.ashx
SAV32CLI will take long time to load all the virus data into memory, I would expect around 5 seconds. This is fine when you're scanning your hard disk but per file it would be rather slow. If you're launching multiple instances then it would be quite a memory drain also.
If your throughput needs improving, I would suggest looking at SAVIDI. In this scenario there is service which loads the virus data once at startup and you can then ask it to scan a file/directory.
This post and attachment in the thread could help you:
https://community.sophos.com/products/endpoint-security-control/f/sophos-endpoint-software/9420/sophos-sav-di-icap-code-sample
Regards.
Sav32Cli.exe requires more permission to execute in web app. So impersonation technique helped me to solve this issue.
This link helped me to solve this issue : Click Here

How to rar/unrar with command line parameters

I've looked through the internet on how winrar's command line parameters work, and this is what I have so far
void LOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\WinRAR.exe";
p.StartInfo.Arguments = "rar a -p" + pw + " PL_LOCKED_ARCHIVE.rar " + fld;
p.Start();
}
void UNLOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\WinRAR.exe";
p.StartInfo.Arguments = "unrar x -p" + pw + " PL_LOCKED_ARCHIVE.rar";
p.Start();
}
However it doesn't seem to create any archive anywhere, with a test folder being C:\PicsAndStuff
The StartInfo you define results in running WinRAR.exe with command line:
C:\Program Files\WinRAR\WinRAR.exe unrar x -p pw PL_LOCKED_ARCHIVE.rar
That is of course wrong as you do not want to run WinRAR.exe with first argument being a reference to console version Rar.exe or UnRAR.exe. The result is most likely an error message because of invalid command rar respectively unrar as the first argument must be a or x for WinRAR.exe.
So first of all you need to correct StartInfo:
void LOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\Rar.exe";
p.StartInfo.Arguments = "a -p" + pw + " PL_LOCKED_ARCHIVE.rar " + fld;
p.Start();
}
void UNLOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\UnRAR.exe";
p.StartInfo.Arguments = "x -p" + pw + " PL_LOCKED_ARCHIVE.rar";
p.Start();
}
Further all commands and switches of console version Rar.exe are briefly explained when simply running Rar.exe without any parameter in a command prompt window. Also UnRAR.exe outputs a brief help if executed without any parameter.
Last but not least there is a complete manual for Rar.exe which of course can also extract files and folders from a RAR archive which makes additional usage of UnRAR.exe useless. The manual is text file Rar.txt in program files folder of WinRAR which you should read from top to bottom. I suggest to build the command line while reading it and test the command line first from within a command prompt window.
Note 1:
Rar.exe is shareware. Only UnRAR.exe is freeware.
Note 2:
GUI version WinRAR.exe supports more than console version Rar.exe and therefore the list of switches differ slightly. Complete documentation for WinRAR.exe can be found in help of WinRAR opened with Help - Help Topics or pressing key F1. Open in help on tab Contents the item Command line mode and read. WinRAR.exe is also shareware.
You need to encrypt both file data and headers.
According to Documentation (Command line mode > Switches > "-hp[pwd] - encrypt both file data and headers"):
This switch is similar to -p[p], but switch -p encrypts only file data
and leaves other information like file names visible. This switch
encrypts all sensitive archive areas including file data, file names,
sizes, attributes, comments and other blocks, so it provides a higher
security level.
This is how you can access to it using command line:
Syntax: rar a -hp[MyPassword] -r [filepath] [folderpath]
"C:\Program Files\WinRAR\WinRAR.exe" a -hp12345678 -r d:\zipProject d:\Project
C# Code:
void LOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\WinRAR.exe";
p.StartInfo.Arguments = "rar a -hp" + pw + " PL_LOCKED_ARCHIVE.rar " + fld;
p.Start();
}

C# Git Command issue

I am developing an App where I need to Run Git Command from C#. I used Process to run Commands if I am passing user Name and password then Is says UserName or Password is Incorrect but it actual working Conventional. Below is my Code:-
public static void PullCode(string gitCommand)
{
string strPassword = "Password";
ProcessStartInfo gitInfo = new ProcessStartInfo();
Process gitProcess = new Process();
gitInfo.CreateNoWindow = true;
gitInfo.UserName = "UserNAme";
gitInfo.Password = Misc.ConvertPassword(strPassword);
gitInfo.UseShellExecute = false;
gitInfo.FileName = #"C:\Program Files (x86)\Git\bin\git.exe"; //git repostory directory path
gitInfo.Arguments = gitCommand; //git command such as "fetch orign"
gitInfo.WorkingDirectory = #"E:\Code Demo\testrepo"; //YOUR_GIT_REPOSITORY_PATH Where you want to Copy Data
gitInfo.RedirectStandardError = true;
gitInfo.RedirectStandardOutput = true;
using( var proc = new System.Diagnostics.Process() )
{
proc.StartInfo = gitInfo;
proc.Start();
var output = proc.StandardOutput.ReadToEnd();
var error = proc.StandardError.ReadToEnd();
var logRaw = string.IsNullOrEmpty( output ) && !string.IsNullOrEmpty( error )
? error.Split( '\n' ).ToArray()
: output.Split( '\n' ).ToArray();
proc.WaitForExit();
proc.Close();
}
}
You have two options. The first one is to set the configuration for your git repo (or globally) to use the git askpass witch is "git config core.askpass git-gui--askpass". Call this as the first command for your process. The drawback here is that each time you do a modifying command it will ask for password.
Or you can have your own executable witch will ask for password once, and have the option to store the password into your application. But here you will have to be careful since if you don't store it properly it will be a security risk.

Netstat focus on (find port)

Im recently trying to execute the following line ;
string strCmdText;
strCmdText = "netstat -np TCP | find " + quote + number + quote + "";
System.Diagnostics.Process.Start("netstat.exe", strCmdText);
Logs.Write("LISTEN_TO(" + Registry_val1.Text + ")", strCmdText);
now what this has to do is basicly find all TCP ports that contain '80' in them and show them up in my custom-made log system that will make a logbook in my folder called;
LISTEN_TO(80)-{date_time}.txt
inside this .txt it should contain the command issued text, however all i get is a time.
i debugged this command as above, and unfortunately all i know is that the CMDtext is set correctly, and that my logging system works correctly, leaving me with no choice that NETSTAT may be closed as soon as the query is launched?
hopefully i provided anough information, as this is my first post.
Regards,
Co
Due to vague description, here's an other-sort same code i tried to do, however still remain getting only a time.
const string quote = "\"";
Process p = new Process();
p.StartInfo.FileName = "cmd";
p.StartInfo.Arguments = "netstat -np TCP | find " + quote + number + quote + "";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
String output = p.StandardOutput.ReadToEnd();
Logs.Write("LISTEN_TO(" + Registry_val1.Text + ")", output);
basicly, you could see this as; textbox1.text = output; execpt now the output is being putten to a log file.
I don't understand why you use netstat in the first place. The .Net framework has a load of classes that give all kind of data, in this case IPGlobalProperties has the method you need.
var ip = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
foreach(var tcp in ip.GetActiveTcpConnections()) // alternative: ip.GetActiveTcpListeners()
{
if (tcp.LocalEndPoint.Port == number
|| tcp.RemoteEndPoint.Port == number)
{
Logs.Write(
String.Format(
"{0} : {1}",
tcp.LocalEndPoint.Address,
tcp.RemoteEndPoint.Address));
}
}
The benefit of using the build-in classes is the ease of shaping and selecting whatever you need and most important: you spare yourself and your user an out-of-process call and parsing of output.
You may try this:
strCmdText = "cmd /c \"netstat -np TCP | find " + quote + number + quote + "\"";
if this does not work, try first to use the command in a cmd prompt to make sure it returns data.
cmd /c "netstat -an | find "80"

Categories