-9

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?

  • 1
    It 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
  • 2
    You 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 Answers3

2

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.

Community
  • 1
  • 1
blenderfreaky
  • 738
  • 7
  • 26
  • Where do I put all that code? – Just Fluffy Jun 16 '19 at 17:22
  • 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
0

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.

nicktheone
  • 77
  • 2
  • 10
0

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 and StreamWriter should be disposed of or put in a using clause.

TaW
  • 53,122
  • 8
  • 69
  • 111