Title: Bruno Cabral
1http//rail.dei.uc.pt
2Summary
- Vision Statement
- Process and Methodology
- Key Features
- Application scenarios
- What can we really do with RAIL?
- Conclusion
3Vision 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.
4Process and Methodology
program
Source Code
Compile
program.exe/dll
PE Header Metadata IL
Assembly
JIT-compile
RAIL
IL
x86
Operating System
5Process and Methodology
6Key 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
7Application scenarios
- Runtime analysis tools
- Security verification
- MSIL optimization
- Application invisible proxy substitution
- Software fault injection
- Aspect Oriented Programming
- Others!
8What 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.LoadAssembl
y("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,typeToCop
y.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(oldTy
pe,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")
9What 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 RParameter1
- //Set the first element of the array
- paramsz0 new RParameter(0,rAssembly.GetType("S
ystem.String")) - //Get the method which code is to be inserted at
the start of the method - RMethodDef rmd0 (RMethodDef)rtd.GetMethod("Write
ToScreenBefore",rAssembly.GetType("System.Void"),p
aramsz) - //Get the method which code is to be inserted at
the end of the method - RMethodDef rmd1 (RMethodDef)rtd.GetMethod("Write
ToScreenAfter",rAssembly.GetType("System.Void"),pa
ramsz) - //Get the method to instrument
- RMethodDef rmd2 (RMethodDef)rtd.GetMethod("MyMet
hod",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)
10What 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 RParameter1
- //Set the first element of the array
- paramsz0 new RParameter(0,rAssembly.GetType("S
ystem.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"),param
sz) - //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)
11What 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.GetT
ype("FooBar") - //Get tje constructor method where to apply the
changes - RConstructorDef rcd (RConstructorDef)rtd.GetCons
tructor(new RType0) - //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")
12What 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.GetT
ype("FooBar") - //Get the constructor method where to apply the
changes - RConstructorDef rcd (RConstructorDef)rtd.GetCons
tructor(new RType0) - //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")
13What 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.GetT
ype("FooBar") - //Get the RTypeDef of the object to create with
the create new instruction - RTypeDef rtd2 (RTypeDef)rAssembly.RModuleDef.Get
Type("ReferencedClass") - //Get the constructor method where to apply the
changes - RConstructorDef rcd (RConstructorDef)rtd.GetCons
tructor(new RType0) - //Get to raplacement method
- RMethod rmGet rtd.GetMethod("GetVal",rtd2,new
RParameter0) - //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")
14What 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.Cal
l, this.newMethod) - code.Remove(pos)
- code.Insert(pos,ilm)
-
15Conclusion
- Code instrumentation is not a simple task
- With RAIL its easy to develop high level
functionalities - Assembly creation mechanisms can be very slow
- The design patterns are very useful