A Steganographic .NET Executable

3 minute read Published:

A simple introduction to steganography with .NET


A while ago, alcopaul suggested a .NET executable that could store a secret message inside. While I did not followed his strict theory, I did wrote a working proof of concept, very basic and dirty but, well, it’s only a POC. Here we go (dirty code, do not judge me):

Our includes for this application.

using System;
using System.Reflection;
using System.IO;
using System.Windows.Forms;
using System.Security.Cryptography;

I’ll now show you the methods I’m using here.

private static byte[] JoinTwoByteArrays(byte[] arrayA, byte[] arrayB)
		{
			byte[] outputBytes = new byte[arrayA.Length + arrayB.Length];
			Buffer.BlockCopy(arrayA, 0, outputBytes, 0, arrayA.Length);
			Buffer.BlockCopy(arrayB, 0, outputBytes, arrayA.Length, arrayB.Length);
			return outputBytes;
		}
private static byte[] encryptdata(byte[] bytearraytoencrypt, string key, string iv)
{
	AesCryptoServiceProvider dataencrypt = new AesCryptoServiceProvider();
	dataencrypt.BlockSize = 128;
	dataencrypt.KeySize = 128;
	dataencrypt.Key = System.Text.Encoding.UTF8.GetBytes(key);
	dataencrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv);
	dataencrypt.Padding = PaddingMode.PKCS7;
	dataencrypt.Mode = CipherMode.CBC;
	ICryptoTransform crypto1 = dataencrypt.CreateEncryptor(dataencrypt.Key, dataencrypt.IV);
	byte[] encrypteddata = crypto1.TransformFinalBlock(bytearraytoencrypt, 0, bytearraytoencrypt.Length);
	crypto1.Dispose();
	return encrypteddata;
	}
private static byte[] decryptdata(byte[] bytearraytodecrypt, string key, string iv)
	{
	AesCryptoServiceProvider keydecrypt = new AesCryptoServiceProvider();
	keydecrypt.BlockSize = 128;
	keydecrypt.KeySize = 128;
	keydecrypt.Key = System.Text.Encoding.UTF8.GetBytes(key);
	keydecrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv);
	keydecrypt.Padding = PaddingMode.PKCS7;
	keydecrypt.Mode = CipherMode.CBC;
	ICryptoTransform crypto1 = keydecrypt.CreateDecryptor(keydecrypt.Key, keydecrypt.IV);
	byte[] returnbytearray = crypto1.TransformFinalBlock(bytearraytodecrypt, 0, bytearraytodecrypt.Length);
	crypto1.Dispose();
	return returnbytearray;
	}

A basic method for joining two byte[] arrays and, of course, a standard AES encrypt/decrypt routine I’ve found somewhere. I could write my own but I was kind of in a hurry so I got this, credits to the creator, whoever you are. You can use your own, code your own, use other cypher, it does not matter, the concept should still work.

Our main function explained.

int mysize = 7168; //original program size (clean, no messages hidden)
byte[] hostbytes = File.ReadAllBytes (Assembly.GetExecutingAssembly ().Location); //current bytes
int currentsize = hostbytes.Length; //original byte size
int msgsize = currentsize - mysize; //message size, duh!

Now that we finish getting the message size, lets read/write it, depending on the user needs!

Those are the arguments to call the program from the terminal.

//args[0] = mode - enc or dec
//args[1] = the message
//args[2] = the password

Here we check if we have arguments to process and if not, we run normally and keep the message hidden.

if (args.Length > 0) {
		if (args [0] == "enc") { //if 1st arg is encrypt, we declare the message and password too
			string message = args [1];
			string passwd= args [2];
			//lets encrypt the message with the given password and IV
			byte[] crypted = encryptdata(System.Text.Encoding.UTF8.GetBytes(message), passwd, "0123456789101112");
			byte[] joined = JoinTwoByteArrays(hostbytes, crypted);
			//now we join the host byte array with the message, this is the same as appending to the EOF
else if (args [0] == "dec") { //if 1st arg is decrypt, we must gather the message bytes
			string passwd= args [1];
			Stream stream = new MemoryStream(hostbytes); //getting a stream from the whole file bytes
			BinaryReader b = new BinaryReader(stream); //invoking a reader 
			b.BaseStream.Seek (mysize, SeekOrigin.Begin); //setting the position to the end of the original app
			byte[] encmsg = b.ReadBytes(msgsize); //read the message
			byte[] decrypted = decryptdata (encmsg, passwd, "0123456789101112"); //decrypt it
			MessageBox.Show (System.Text.Encoding.UTF8.GetString (decrypted)); //display it!
		}

Screenshots of the proof of concept:

Encrypt & Decrypt

This is still a very basic example, you could modify it to do some pretty cool stuff (perhaps using Mono.Cecil), inject your message into any .NET assembly, etc. Check the full code here.

I’ll probably release a ELF version of this soon, probably in Vala.

TMZ