150 likes | 260 Views
http://rail.dei.uc.pt. Bruno Cabral. Summary. Vision Statement Process and Methodology Key Features Application scenarios What can we really do with RAIL? Conclusion. Vision Statement.
E N D
http://rail.dei.uc.pt Bruno Cabral
Summary • Vision Statement • Process and Methodology • Key Features • Application scenarios • What can we really do with RAIL? • Conclusion
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 //Create the RAssemblyDef objects of the two assemblies RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste.exe"); RAssemblyDef rAssembly2 = RAssemblyDef.LoadAssembly("Teste2.dll"); //Get the type to copy from assembly Teste2.dll to assembly Teste.exe RType typeToCopy = rAssembly2.RModuleDef.GetType("Bar"); //Copies the type Bar to Teste.exe assembly rAssembly.RModuleDef.CopyType(typeToCopy,typeToCopy.Name); //Creates the RType instances of the to types RType oldType = rAssembly.RModuleDef.GetType("Foo"); RType newType = rAssembly.RModuleDef.GetType("Bar"); //Creates the ReferenceReplacer visitor object ReferenceReplacer rr = new ReferenceReplacer(oldType,newType); //Aplly the change to the assembly an its members rAssembly.Accept(rr); //Remove the previous used type Foo rAssembly.RModuleDef.RemoveType("Foo"); //Save the new assembly rAssembly.SaveAssembly("Teste.exe");
What can we really do with RAIL? Add epilogues and prologues to methods //Create the RAssemblyDef instance for the Teste3.exe assembly RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe"); //Get the RType object of the FooBar type RType rtd = rAssembly.RModuleDef.GetType("FooBar"); //Create an array of RParameter objects RParameter [] paramsz = new RParameter[1]; //Set the first element of the array paramsz[0] = new RParameter(0,rAssembly.GetType("System.String")); //Get the method which code is to be inserted at the start of the method RMethodDef rmd0 = (RMethodDef)rtd.GetMethod("WriteToScreenBefore",rAssembly.GetType("System.Void"),paramsz); //Get the method which code is to be inserted at the end of the method RMethodDef rmd1 = (RMethodDef)rtd.GetMethod("WriteToScreenAfter",rAssembly.GetType("System.Void"),paramsz); //Get the method to instrument RMethodDef rmd2 = (RMethodDef)rtd.GetMethod("MyMethod",rAssembly.GetType("System.Void"),paramsz); //Create the CodeTransformer object CodeTransformer cc = new CodeTransformer(); //Set the transformations to make in the code cc.InsertAtMethodStart(rmd0); cc.InsertAtMethodEnd(rmd1); //Apply the change to the code rmd2.Accept(cc); //Save the new assembly rAssembly.SaveAssembly("Teste3.exe");
What can we really do with RAIL? Redirect methods access/call //Create the RAssemblyDef instance for the Teste3.exe assembly RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe"); //Get the RType object for the type that declares the methods RType rtd = rAssembly.RModuleDef.GetType("FooBar"); //Create a RParameter object array RParameter [] paramsz = new RParameter[1]; //Set the first element of the array paramsz[0] = new RParameter(0,rAssembly.GetType("System.String")); //Get the method to replace the original RMethodDef rmdReplacer = (RMethodDef)rtd.GetMethod("wrt",rAssembly.GetType("System.Void"),paramsz); //Get the original method RMethodDef rmdOriginal = (RMethodDef)rtd.GetMethod("MyMethod",rAssembly.GetType("System.Void"),paramsz); //Create a CodeTransformer object CodeTransformer cc = new CodeTransformer(); //Set the transformation to make in the code cc.RedirectMethodCall(rmdOriginal,rmdReplacer); // Aplly the transformation to all methods and constructors // in the in the assembly rAssembly.Accept(cc); //Save the method rAssembly.SaveAssembly("Teste3.exe");
What can we really do with RAIL? Redirect field accessRedirect field access to propertyRedirect field read and write access to methods //Create the RAssemblyDef representation of the Teste3.exe assembly RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe"); //Get the RTypeDef obejct for the type where the field and property are declared RTypeDef rtd = (RTypeDef)rAssembly.RModuleDef.GetType("FooBar"); //Get tje constructor method where to apply the changes RConstructorDef rcd = (RConstructorDef)rtd.GetConstructor(new RType[0]); //Get the field RField rfld1 = rtd.GetField("Val1"); //Get the property RProperty rprop = rtd.GetProperty("Prop"); //Create the code trasnformer object CodeTransformer cc = new CodeTransformer(); //Set the transformation to make in the code cc.RedirectFieldAccess(rfld1,rprop); //Apply the changes rcd.Accept(cc); //Save the assembly rAssembly.SaveAssembly("Teste3.exe");
What can we really do with RAIL? Redirect property access //Create the RAssemblyDef representation of the Teste3.exe assembly RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe"); //Get the RTypeDef object for the type where teh properties are declared RTypeDef rtd = (RTypeDef)rAssembly.RModuleDef.GetType("FooBar"); //Get the constructor method where to apply the changes RConstructorDef rcd = (RConstructorDef)rtd.GetConstructor(new RType[0]); //Get the property to be replaced RProperty rpro1 = rtd.GetProperty("Prop"); //Get the replacement property RProperty rpro2 = rtd.GetProperty("Prop2"); //Create the code transformer object CodeTransformer cc = new CodeTransformer(); //Set the transformations to make in the code cc.RedirectPropertyAccess(rpro1,rpro2); //Aplly th changes rcd.Accept(cc); //Save the assembly rAssembly.SaveAssembly("Teste3.exe");
What can we really do with RAIL? Replace create new instructions with a static methodCreate, Run and Save assemblies //Create the RAssemblyDef representation of the Teste3.exe assembly RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe"); //Get the RTypeDef object for the type where the method is declared RTypeDef rtd = (RTypeDef)rAssembly.RModuleDef.GetType("FooBar"); //Get the RTypeDef of the object to create with the create new instruction RTypeDef rtd2 = (RTypeDef)rAssembly.RModuleDef.GetType("ReferencedClass"); //Get the constructor method where to apply the changes RConstructorDef rcd = (RConstructorDef)rtd.GetConstructor(new RType[0]); //Get to raplacement method RMethod rmGet = rtd.GetMethod("GetVal",rtd2,new RParameter[0]); //Create a code transformer object CodeTransformer cc = new CodeTransformer(); //Set the transformation to make in the code cc.ReplaceNew(rtd2,rmGet); //Aplly the changes rcd.Accept(cc); //Save the new assembly rAssembly. RunAndSaveAssembly("Teste3.exe");
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); }
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