Using System.Reflection namespace in .NET viruses Intro The simplest way to create executables (they called assemblies) in .NET platform is usage of System.Reflection namespace. But Microsoft advisedly restricted it's capabilities: it can create new assemblies, analyze objects but cannot disassemble IL code. To overcome this the only way exists: to disassemble manually. Fortunately it was done: there are some .NET disassemblers. It is possible to use them in viruses. Basics The structure of .NET executables is very complicated, lower it will be descri- bed briefly. Full description you can find in .NET Framework documentation (Partition II Metadata) and MSDN. Every .NET assembly is self-describing. This means that all information about assembly may be obtained from it. This information is written in metadata. Usually metadata is placed in the .text section of file. Microsoft used self-invented assembler code called CIL (common intermediate language). This code is compiled in native computer code while loading executable. That's why .NET programs are cross-platform. At the abstract level, assemblies consist of modules, they consist of types (classes). Types consist of members, which divides on fields, events, properties and methods (particular case is constructors). Types can be nested. Each method consists of IL code and exception handlers. The hierarchy of classes to create and analyse objects: Assembly AssemblyBuilder Assembly.GetModules() || AssemblyBuilder.DefineModule() \/ Module ModuleBuilder Module.GetTypes() || ModuleBuilder.DefineType() \/ Type TypeBuilder Type.GetFields() || TypeBuilder.DefineField() Type.GetProperties() || TypeBuilder.DefineProperty() Type.GetEvents() || TypeBuilder.DefineEvent() Type.GetMethods() || TypeBuilder.DefineMethod() Type.GetConstructors() || TypeBuilder.DefineConstructor() \/ FieldInfo FieldBuilder PropertyInfo PropertyBuilder EventInfo EventBuilder MethodBase MethodBuilder ----- ConstructorInfo ConstructorBuilder---- |.GetILGenerator() || \/ ILGenerator .Emit() .EmitCall() .DeclareLocal() .DefineLabel() .MarkLabel() .BeginExceptionBlock() .BeginExceptFilterBlock() .BeginCatchBlock() .BeginFaultBlock() .BeginFinallyBlock() .EndExceptionBlock() All these objects have literal names and referenced by them. Every assembly can be digitally signed. To create bodies of methods and constructors ILGenerator class defined. Emit and EmitCall methods of this class create IL instructions. For creation of try-catch (try-finally) frames special methods of this class intended. Algorithm of .NET virus What we need to do: 1) Analyse victim 2) Analyse self 3) Create new assembly. 4) Add types of self with all underlying methods and nested types to new assembly 5) Add types of victim with all underlying methods and nested types to new assembly. When adding entrypoint method add code that runs viral thread at its start and termitates viral thread at its end. 6) Fill all methods with IL code and exception handling frames Snail To demonstrate possibility of .NET infection I wrote a sample virus, called Snail (because of its speed). It tries to infect each EXE file in current directory and all directories above. To disassemble .NET executables it uses ILReader disassembler as a separate DLL. This DLL is added to each infected file as overlay data. Theoretically virus can run on non-Windows platforms with installed .NET Framework (MacOSX, FreeBSD). Virus makes copy of a victim file and creates new assembly with same name as victim. It adds victim's classes and viral classes to it. If everything okay copy is deleted, otherwise original file is restored. Virus is written on C#. No need to use IL for coding .NET viruses! It's size is about 100kB - I think this is not much with HDD capacities of hundreds GB. Snail uses some anti-av tricks. It mixes original code with trash (instructions nop and ldloc/pop). Also it uses obfuscation. This means it create objects (classes, members) with random names. They look like: vmtdmtQdutszak, idRIaiqBlhgigF. It's very difficult to analyse file with such names of objects. Virus places victim's objects and created objects in hashtables. Every initial object corresponds with created object. This needed to avoid situation when infected program refers infector (virus) and cannot run without it. Console and GUI apps can be infected. Virus copies unmanaged (Win32) resource section to infected file. For assemblies with managed (.NET) resources separate file created that stores resources. (I couldn't find way to add managed resource in assembly - btw, how to solve this?) Anyway this feature may be turned off. Assemblies can be signed with RSA hash. Virus removes these hashes while infecting. Assemblies with EXE extension usually are not used by other assemblies so no problems appear with key validation. This feature also may be turned off by commenting #define in source. When exploring new platform I noticed an interesting its feature. When virus thread is running and main program ends, thread is not terminated (unlike Windows applications where termination of process implies termination of all threads). Therefore main thread in infected application aborts viral thread at the end of execution. .NET allows to set exception handlers on thread termination, so that thread is terminated correctly. Going on To make functional virus for .NET there are several ways: 1) Try to merge (using ILDASM and ILASM tools) ILReader.DLL with viruses. But ILReader.DLL cannot analyse assemblies with initialized binary data like this: byte [] x = {1,2,3}; To overcome: fix ILReader.DLL (inheriting its classes by own ones) or get this data manually. 2) Write own rebuilder library. This work is at full speed. .NET will be the base of future Windows versions so that .NET viruses will dominate in future. /whale 2004