📄 29a-7.021
字号:
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -