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:
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