bruno cabral . summary vision statement process and methodology key features application scenarios...
TRANSCRIPT
Bruno Cabral
http://rail.dei.uc.pt
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
Operating SystemOperating SystemOperating SystemOperating System
programprogramprogramprogram
program.exe/dllprogram.exe/dllprogram.exe/dllprogram.exe/dll
PE HeaderPE Header
MetadataMetadata
ILIL
PE HeaderPE Header
MetadataMetadata
ILIL
ILIL x86x86
Source CodeSource Code
CompileCompile
AssemblyAssembly
JIT-compileJIT-compile
RAILRAIL
Process and Methodology
Collect metadata andMSIL code into a set
of objects
Assembly Load assembly
Manipulate the assemblyby modifying the objects structure
Create AssemblyBuilder
Run new assembly
Save new assembly
RAIL
Programmer
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?
//Create the RAssemblyDef objects of the two assembliesRAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste.exe");RAssemblyDef rAssembly2 = RAssemblyDef.LoadAssembly("Teste2.dll");//Get the type to copy from assembly Teste2.dll to assembly Teste.exeRType typeToCopy = rAssembly2.RModuleDef.GetType("Bar");//Copies the type Bar to Teste.exe assemblyrAssembly.RModuleDef.CopyType(typeToCopy,typeToCopy.Name);//Creates the RType instances of the to typesRType oldType = rAssembly.RModuleDef.GetType("Foo");RType newType = rAssembly.RModuleDef.GetType("Bar");//Creates the ReferenceReplacer visitor objectReferenceReplacer rr = new ReferenceReplacer(oldType,newType);//Aplly the change to the assembly an its membersrAssembly.Accept(rr);//Remove the previous used type FoorAssembly.RModuleDef.RemoveType("Foo");//Save the new assemblyrAssembly.SaveAssembly("Teste.exe");
Replace References
What can we really do with RAIL?
//Create the RAssemblyDef instance for the Teste3.exe assemblyRAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe");//Get the RType object of the FooBar typeRType rtd = rAssembly.RModuleDef.GetType("FooBar");//Create an array of RParameter objectsRParameter [] paramsz = new RParameter[1];//Set the first element of the arrayparamsz[0] = new RParameter(0,rAssembly.GetType("System.String"));//Get the method which code is to be inserted at the start of the methodRMethodDef rmd0 =
(RMethodDef)rtd.GetMethod("WriteToScreenBefore",rAssembly.GetType("System.Void"),paramsz);//Get the method which code is to be inserted at the end of the methodRMethodDef rmd1 =
(RMethodDef)rtd.GetMethod("WriteToScreenAfter",rAssembly.GetType("System.Void"),paramsz);//Get the method to instrumentRMethodDef rmd2 = (RMethodDef)rtd.GetMethod("MyMethod",rAssembly.GetType("System.Void"),paramsz);//Create the CodeTransformer objectCodeTransformer cc = new CodeTransformer();//Set the transformations to make in the codecc.InsertAtMethodStart(rmd0);cc.InsertAtMethodEnd(rmd1);//Apply the change to the codermd2.Accept(cc);//Save the new assemblyrAssembly.SaveAssembly("Teste3.exe");
Add epilogues and prologues to methods
What can we really do with RAIL?
//Create the RAssemblyDef instance for the Teste3.exe assemblyRAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe");//Get the RType object for the type that declares the methodsRType rtd = rAssembly.RModuleDef.GetType("FooBar");//Create a RParameter object arrayRParameter [] paramsz = new RParameter[1];//Set the first element of the arrayparamsz[0] = new RParameter(0,rAssembly.GetType("System.String"));//Get the method to replace the originalRMethodDef rmdReplacer =
(RMethodDef)rtd.GetMethod("wrt",rAssembly.GetType("System.Void"),paramsz);//Get the original methodRMethodDef rmdOriginal =
(RMethodDef)rtd.GetMethod("MyMethod",rAssembly.GetType("System.Void"),paramsz);//Create a CodeTransformer objectCodeTransformer cc = new CodeTransformer();//Set the transformation to make in the codecc.RedirectMethodCall(rmdOriginal,rmdReplacer);// Aplly the transformation to all methods and constructors // in the in the assemblyrAssembly.Accept(cc);//Save the methodrAssembly.SaveAssembly("Teste3.exe");
Redirect methods access/call
What can we really do with RAIL?
//Create the RAssemblyDef representation of the Teste3.exe assemblyRAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe");//Get the RTypeDef obejct for the type where the field and property are
declaredRTypeDef rtd = (RTypeDef)rAssembly.RModuleDef.GetType("FooBar");//Get tje constructor method where to apply the changesRConstructorDef rcd = (RConstructorDef)rtd.GetConstructor(new RType[0]);//Get the fieldRField rfld1 = rtd.GetField("Val1");//Get the propertyRProperty rprop = rtd.GetProperty("Prop");//Create the code trasnformer objectCodeTransformer cc = new CodeTransformer();//Set the transformation to make in the codecc.RedirectFieldAccess(rfld1,rprop);//Apply the changesrcd.Accept(cc);//Save the assemblyrAssembly.SaveAssembly("Teste3.exe");
Redirect field accessRedirect field access to propertyRedirect field read and write access to methods
What can we really do with RAIL?
//Create the RAssemblyDef representation of the Teste3.exe assemblyRAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe");//Get the RTypeDef object for the type where teh properties are declaredRTypeDef rtd = (RTypeDef)rAssembly.RModuleDef.GetType("FooBar");//Get the constructor method where to apply the changesRConstructorDef rcd = (RConstructorDef)rtd.GetConstructor(new RType[0]);//Get the property to be replacedRProperty rpro1 = rtd.GetProperty("Prop");//Get the replacement propertyRProperty rpro2 = rtd.GetProperty("Prop2");//Create the code transformer objectCodeTransformer cc = new CodeTransformer();//Set the transformations to make in the codecc.RedirectPropertyAccess(rpro1,rpro2);//Aplly th changesrcd.Accept(cc);//Save the assemblyrAssembly.SaveAssembly("Teste3.exe");
Redirect property access
What can we really do with RAIL?
//Create the RAssemblyDef representation of the Teste3.exe assemblyRAssemblyDef rAssembly = RAssemblyDef.LoadAssembly("Teste3.exe");//Get the RTypeDef object for the type where the method is declaredRTypeDef rtd = (RTypeDef)rAssembly.RModuleDef.GetType("FooBar");//Get the RTypeDef of the object to create with the create new instructionRTypeDef rtd2 = (RTypeDef)rAssembly.RModuleDef.GetType("ReferencedClass");//Get the constructor method where to apply the changesRConstructorDef rcd = (RConstructorDef)rtd.GetConstructor(new RType[0]);//Get to raplacement methodRMethod rmGet = rtd.GetMethod("GetVal",rtd2,new RParameter[0]);//Create a code transformer objectCodeTransformer cc = new CodeTransformer();//Set the transformation to make in the codecc.ReplaceNew(rtd2,rmGet); //Aplly the changesrcd.Accept(cc);//Save the new assemblyrAssembly. RunAndSaveAssembly("Teste3.exe");
Replace create new instructions with a static methodCreate, Run and Save assemblies
What can we really do with RAIL?
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);
}
Play with MSIL code!!
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