330 likes | 471 Views
http://www.dei.uc.pt/~bcabral. “Reflection, Code Generation and Instrumentation in the .NET platform”. Bruno Cabral. University of Coimbra. Summary. PE File Metadata Introspection Assembly and Code generation Using RAIL. PE File. PE = Portable Executable
E N D
http://www.dei.uc.pt/~bcabral “Reflection, Code Generation and Instrumentation in the .NET platform” Bruno Cabral University of Coimbra
Summary • PE File • Metadata • Introspection • Assembly and Code generation • Using RAIL
PE File • PE = Portable Executable • Marked as Code and Execute Read for the OS loader and the CLR • _CorExeMain (mscoree.dll)
PE File • PE = Portable Executable • Marked as Code and Execute Read for the OS loader and the CLR • _CorExeMain (mscoree.dll)
PE File • Multiple Modules • Module = file
PE File - Metadata • "data about data" • Describes types • Member fields, methods, properties, events • Describes signatures • Fields, properties, methods, delegates, local vars • Describes types and references • Describes miscellaneous entities • Files, modules, assemblies
PE File - Metadata • CIL instructions reference metadata via TOKENS • First byte of token indicates type • Last three bytes of token are either row # (tables) or offsets (heaps) • Tokens are stored compressed in signatures (binary file viewers not very useful)
PE File - Metadata • Tokens (and types) in listing • MethodDef : (0x06000001) • User string: (0x70000001) • AssemblyRef : (0x23000001) • TypeRef : (0x01000003) • MemberRef : (0x0A000002) • Only two are directly referenced by CIL in this example: example: • String (by ldstr instruction) • MemberRef (by call instruction)
Introspection • Two major metadata APIs available • Managed: System.Reflection • Unmanaged: IMetaDataImport • Both are limited in different ways • System.Reflection does not permit access to CIL • System.Reflection does not reveal token values • IMetaDataImport cannot resolve *Ref tokens
Introspection • What can we do with System.Reflection? • See loaded assemblies • See referenced assemblies • See the types defined in the assembly • See the methods defined in a type • See attributes • …
Introspection • See loaded assemblies Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach( Assembly assembly in assemblies ) Console.WriteLine( assembly.FullName );
Introspection • See referenced assemblies AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies(); foreach( AssemblyName assemblyName in referencedAssemblies ) Console.WriteLine( "--> {0}", assemblyName.FullName );
Introspection • See the types defined in the assembly Assembly a = Assembly.LoadFrom("Teste.exe"); Module[] m = a.GetModules( ); Console.WriteLine("\n" + a.FullName ); Type[] types = m[0].GetTypes( ); foreach( Type type in types ) Console.WriteLine( "==> {0}", type.FullName );
Introspection • See the methods defined in a type Assembly a = Assembly.LoadFrom("HelloWorld.exe"); Module[] m = a.GetModules( ); Type[] types = m[0].GetTypes( ); Type type = types[0]; MethodInfo[] mInfo = type.GetMethods( ); foreach ( MethodInfo mi in mInfo ) Console.WriteLine(" {0}", mi);
Assembly and Code Generation • How to use System.Reflection.Emit to generate assemblies in run-time? • AssemblyBuilder, ModuleBuilder, TypeBuilder, MethodBuilder, … • ILGenerator
Assembly and Code Generation AssemblyName myAssemblyName = new AssemblyName(); myAssemblyName.Name = "MyAssembly"; myAssemblyName.Version = new Version("1.0.0.2004");
Assembly and Code Generation AssemblyBuilder myAssemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder myModuleBuilder = myAssemblyBuilder.DefineDynamicModule("MyModule", fileName); TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("MyType");
Assembly and Code Generation MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.HideBySig |MethodAttributes.Static, typeof(void), null); ILGenerator myILGenerator = myMethodBuilder.GetILGenerator(); myILGenerator.EmitWriteLine("Hello World!"); myILGenerator.Emit(OpCodes.Ret);
Assembly and Code Generation myTypeBuilder.CreateType(); myAssemblyBuilder.SetEntryPoint(myMethodBuilder); myAssemblyBuilder.Save(fileName);
What is missing? • Reflection • Generation • …
What is missing? • Reflection • Generation • INTRUMENTATION… • Structural Reflection • Behavioural Reflection • HOW TO DO IT?
Vision Statement • “Create an API that allows CLR assemblies to be manipulated and instrumented before they are loaded and executed“ • The reflection capabilities of the CLR are extremely powerful. • Query the existing types at runtime • Define new assemblies in memory and use Reflection.Emit to generate MSIL on-the-fly. • Our plan is to fill the gap between these two concepts.
Process and Methodology program Source Code Compile program.exe/dll PE Header Metadata IL Assembly JIT-compile RAIL IL x86 Operating System
Key features • ‘Rapid’ assembly instrumentation library • High level of abstraction, no need for handling all the internal details • Convenient object model for representation of all assembly modules • Flexible MSIL instruction handling • Use of design patterns
Application scenarios • Runtime analysis tools • Security verification • MSIL optimization • Application invisible proxy substitution • Software fault injection • Aspect Oriented Programming • Others!
What can we really do with RAIL? Replace References Add epilogues and prologues to methods Redirect methods access/call Redirect field accessRedirect field access to propertyRedirect field read and write access to methods Redirect property access Replace create new instructions with a static methodCreate, Run and Save assemblies
What can we really do with RAIL? Play with MSIL code!! private void Replace(MSIL.Code code, int pos) { MSIL.ILMethod ilm = new MSIL.ILMethod(OpCodes.Call, this.newMethod); code.Remove(pos); code.Insert(pos,ilm); }
Assembly Loading Interception • ResolveEventHandler currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler); • Load the assembly ourselves • Modify the CLR (SSCLI)??? • Others??
Conclusion • Code instrumentation is not a simple task • With RAIL it’s easy to develop high level functionalities • Assembly creation mechanisms can be very slow • The design patterns are very useful