Notes
Slide Show
Outline
1
http://rail.dei.uc.pt
  • Bruno Cabral
2
Summary
  • Vision Statement
  • Process and Methodology
  • Key Features
  • Application scenarios
  • What can we really do with RAIL?
  • Conclusion


3
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.
4
Process and Methodology
5
Process and Methodology
6
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
7
Application scenarios
  •  Runtime analysis tools
  •  Security verification
  •  MSIL optimization
  •  Application invisible proxy substitution
  •  Software fault injection
  •  Aspect Oriented Programming
  •  Others!
8
What can we really do with RAIL?
  • //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");
9
What can we really do with RAIL?
  • //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");
10
What can we really do with RAIL?
  • //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");
11
What can we really do with RAIL?
    • //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");
12
What can we really do with RAIL?
  • //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");
13
What can we really do with RAIL?
  • //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");
14
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);
  • }
15
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