I have created a c# program that runs a .cmd file when a button is clicked. However that .cmd file can be edited by anyone. How can I obfuscate/protect the .cmd file to stop it from being reverse engineered?
-
1It really would help us if you explained what you think “stop it from being edited” [is going to accomplish](https://meta.stackexchange.com/questions/66377/). – Dour High Arch Jun 16 '19 at 17:12
-
it will make sure no one can reverse engineer and steal the source code – Just Fluffy Jun 16 '19 at 17:14
-
2You could encrypt the file and [feed](https://stackoverflow.com/questions/1469764/run-command-prompt-commands) a cmd process with the decrypted version. – TaW Jun 16 '19 at 17:25
3 Answers
You can set the .cmd file to be read-only (right-click > properties > read-only) However, that is not very safe as the windows permission system is not exactly the best.
Idea
I would recommend checking the file, to see if it is unedited, before execution. To do this you could hash the file, and compare it to your hash. As long as you hardcode that hash into your software, it will be difficult to reverse-engineer.
Implementation
Calculating the correct checksum
string CMDFileChecksum()
using var md5 = MD5.Create();
using var stream = File.OpenRead(PATH_TO_YOUR_CMD)
var hash = md5.ComputeHash(stream); // Compute the hash
return BitConverter.ToString(hash)
.Replace("-", "").ToLowerInvariant(); // Convert the hash to a string
}
Checking file
Then you would need to run it once in order to get the correct hash. Copy the result and use it like this:
// Put your checksum as calculated by CMDFileChecksum() herer
const string correctChecksum = "CHECKSUM"; // Use const to bake the string into the code
if (correctChecksum == CMDFileChecksum())
{
// Run the CMD file
}
else
{
// The CMD file has been edited => throw error or warn user etc.
}
This will calculate the checksum of the file and compare it to the correct one. If the file has been modified, the file won't be executed. If this occurs you could download the correct file from the server, warn the user not to do that, or whatever you want really.

- 1
- 1

- 738
- 7
- 26
-
-
Ah, sorry. Didn't see the edit. If you want to stop it from being stolen you'll need some sort of encryption. But I don't think that a cmd is worth encrypting, what'd one even do with a stolen cmd? Probably more effort than it's worth – blenderfreaky Jun 16 '19 at 17:52
Is there a reason why you need to execute the .cmd file and not the contained commands directly from inside of your C# application?
You could try something like:
string cmdText = "/C **your commmand file code here**";
System.Diagnostics.Process.Start("cmd.exe", cmdText);
Don't forget the /C
part of the command string as it is vital.
This way your code wouldn't risk being stolen or edited by the end user.

- 77
- 2
- 10
-
.NET is not very hard to decompile, so this would propably not protect the code very well. See [ILSpy](https://github.com/icsharpcode/ILSpy) for .NET decompiling – blenderfreaky Jun 16 '19 at 18:00
-
1@blenderfreaky I realize that but it's still a step further from a plain text .cmd file without using encryption which may be way out of scope in OP's case. – nicktheone Jun 16 '19 at 18:02
-
My cmd code is 18 lines long so how would I convert that to make it work in c#? – Just Fluffy Jun 16 '19 at 18:10
-
You can use [string literals](https://stackoverflow.com/questions/1100260/multiline-string-literal-in-c-sharp) – blenderfreaky Jun 16 '19 at 18:13
-
For the sake of simplicity have you tried copying directly all the code as a whole string? – nicktheone Jun 16 '19 at 18:14
-
-
-
-
Also, if you're already copying the code into your solution, you could just use [Resources](https://stackoverflow.com/questions/90697/how-to-create-and-use-resources-in-net) – blenderfreaky Jun 16 '19 at 18:28
-
I pasted my 18 lines of cmd code into "/C **your command file code here**"; and got 193 errors like "; expected" and "Newline in constant". – Just Fluffy Jun 16 '19 at 18:30
-
Can you show an example of how to run the cmd code in c# but with 18 lines? – Just Fluffy Jun 16 '19 at 18:35
-
It may not be ideal but for debug purposes can’t you try executing with my method line by line? See what happens. – nicktheone Jun 16 '19 at 18:40
-
I pasted your code line by line into a button and when I click the button something shows up in my task bar and disappears in less than a second. – Just Fluffy Jun 16 '19 at 18:43
-
-
First: If you want to protect your cmd script you will need to encrypt it. There are many examples from simplistic to full-scale protection.
Strictly for testing here is a simplistic one:
string crypto(string input, bool encrypt)
{
Random rnd = new Random(123);
StringBuilder sb = new StringBuilder();
int sgn = encrypt ? 1 : -1;
for (int i = 0; i < input.Length; i++)
{
sb.Append( ((char) ( (byte)input[i] + sgn * rnd.Next(63))) .ToString());
}
return sb.ToString();
}
Next you need to feed the decrypted lines one by one into a process, which runs the cmd.exe
. For this you need to use the StdIn
property and redirect it to read from a stream
you feed from the lines..:
Process cmdProc = new Process();
cmdProc.StartInfo.FileName = "cmd.exe";
cmdProc.StartInfo.RedirectStandardOutput = true;
cmdProc.StartInfo.RedirectStandardInput = true;
cmdProc.StartInfo.UseShellExecute = false;
cmdProc.StartInfo.CreateNoWindow = true;
cmdProc.Start();
StreamWriter myStreamWriter = cmdProc.StandardInput;
myStreamWriter.WriteLine("@echo off"); // optional
foreach (var line in lines)
{
if (line.Trim().ToLower() != "pause")
myStreamWriter.WriteLine(line);
}
myStreamWriter.WriteLine("exit"); // optional
// show the output somewhere, if needed
textbox_out.Text += (cmdProc.StandardOutput.ReadToEnd());
A few notes:
As only one cmd process is used it will work with environment variables set in the script.
You can also grab the output after each line and strip the command, i.e. the 1st line, from it if you want to get only the output.
You can also redirect
StdErr
, which will help when finding all sorts of errors..The crypto function has many flaws, most notably it is not designed to work with double-byte encodings or higher that ascii characters.
Process
andStreamWriter
should be disposed of or put in ausing
clause.

- 53,122
- 8
- 69
- 111