Paulo Marques, Bruno Cabral {pmarques,bcabral}@dei.uc.pt Dependable Systems Group University of...

Preview:

Citation preview

Paulo Marques, Bruno Cabral{pmarques,bcabral}@dei.uc.pt

Dependable Systems Group University of Coimbra, Portugal

RAIL: Code Instrumentation for .NET

Code Instrumentation The ability to modify an application

after it has been compiled but before (or during) its execution

Application Scenarios: Security Verifications, Dynamic Code

Optimizers, Profiling, Fault Injection, AOP, among others

RAIL Runtime Assembly Instrumentation

Library http://rail.dei.uc.pt

“An API that allows CLR assemblies to be manipulated and instrumented before they are loaded and executed”

Currently, one of the main high-level code instrumentation libraries for .NET

But what’s this RAIL API anyway? Simple example:

How can you be sure that the application that you’ve downloaded from the Internet is not searching through your files??

RAIL Suppose that you can open the

application executable and substitute all class references from “File” to “SecureFileAccess”!!!

......

FileFile theSecret; theSecret;

theSecret = newtheSecret = new FileFile(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

......

FileFile theSecret; theSecret;

theSecret = newtheSecret = new FileFile(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

Original File (but in binary code!) RAIL......

SecureFileAccessSecureFileAccess theSecret; theSecret;

theSecret = newtheSecret = new SecureFileAccessSecureFileAccess(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

......

SecureFileAccessSecureFileAccess theSecret; theSecret;

theSecret = newtheSecret = new SecureFileAccessSecureFileAccess(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

New File (also in binary code...)

class class SecureFileAccessSecureFileAccess { {

File theRealFile;File theRealFile; boolean accessPermited; boolean accessPermited;

SecureFileAccess(String filename) {SecureFileAccess(String filename) { logfile.write(“The foo is accessing {0}”, name); logfile.write(“The foo is accessing {0}”, name); ... ... accessPermited = User.readPermitAccess(); accessPermited = User.readPermitAccess(); theRealFile = new File(filename); theRealFile = new File(filename); } }

read() {read() { if (accessPermited) {if (accessPermited) { theRealFile.read(); theRealFile.read(); } } } }

}}

class class SecureFileAccessSecureFileAccess { {

File theRealFile;File theRealFile; boolean accessPermited; boolean accessPermited;

SecureFileAccess(String filename) {SecureFileAccess(String filename) { logfile.write(“The foo is accessing {0}”, name); logfile.write(“The foo is accessing {0}”, name); ... ... accessPermited = User.readPermitAccess(); accessPermited = User.readPermitAccess(); theRealFile = new File(filename); theRealFile = new File(filename); } }

read() {read() { if (accessPermited) {if (accessPermited) { theRealFile.read(); theRealFile.read(); } } } }

}}

theSecrettheSecrettheSecrettheSecret

Proxy class

RealFile

Real reference to the file

RAIL Suppose that you can open the

application executable and substitute all class references from “File” to “SecureFileAccess”!!!

......

FileFile theSecret; theSecret;

theSecret = newtheSecret = new FileFile(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

......

FileFile theSecret; theSecret;

theSecret = newtheSecret = new FileFile(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

Original File (but in binary code!) RAIL......

SecureFileAccessSecureFileAccess theSecret; theSecret;

theSecret = newtheSecret = new SecureFileAccessSecureFileAccess(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

......

SecureFileAccessSecureFileAccess theSecret; theSecret;

theSecret = newtheSecret = new SecureFileAccessSecureFileAccess(“secret.doc”);(“secret.doc”);

......

data = theSecret.read();data = theSecret.read();

internet.send(...);internet.send(...);

New File (also in binary code...)

// Load assembly into memory RAssemblyDef myAssembly = RAssemblyDef.LoadAssembly("Download.exe");

// Creates references for the old and new types to be usedRType oldType = myAssembly.RModuleDef.GetType("File");RType newType = myAssembly.RModuleDef.GetType("SecureFileAccess");

// Creates a reference replacer and apply the substitutionReferenceReplacer replacer = new ReferenceReplacer(oldType, newType);myAssembly.Accept(replacer);

Development Model

What can be done with RAIL? Iterate over code, injecting and removing code Replace Type references Add epilogues and prologues to methods Redirect method accesses and calls Redirect field and property accesses Redirect field access to properties Redirect field read and write access to methods Manipulate custom attributes Copy-Paste Types and Methods and

IL code across assemblies Manipulate Exception Blocks Integration with CODEDOM

Operating SystemOperating SystemOperating SystemOperating System

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-compilerJIT-compiler

RAILRAIL

.cs

Structure of an Assembly

PE/COFF headers

CLR Header

CLR Data

Metadata IL code

Native Image Sections

.data, .rdata, .rsrc, .text

Managed Module

Metadata

IL code

Source Code

Managed Compiler

Common Language Runtime

Loader JIT Compiler

Internal DataStructures

Native Code

Execution engine

Object-OrientedRepresentation

(diagram not complete)

Assembly

RAIL

Mono.PEToolkit

RAIL.Reflect RAIL.MSIL

Rail High Level Instrumentation classes

System.Reflection

System.Reflection.Emit

AssemblyBuilder object

Assembly

Save

AppDomain

Load

Load

RAIL’s InternalStructure

Fully-configurable:Can use third-partylibraries

Source CodeCODEDOM

// Source code to usestring myProxy = @" using system;

class SecureFileAccess { File theRealFile; boolean accessPermited; (...) }";

// Define the code in an assembly RAssemblyDef dynamicAssembly = RAssemblyDef.CreateRAssemblyFromCode(myProxy, false);

(...)

// Creates references for the old and new types to be usedRType oldType = myAssembly.RModuleDef.GetType("File");RType newType = dynamicAssembly.RModuleDef.GetType("SecureFileAccess");

// Creates a reference replacer and apply the substitutionReferenceReplacer replacer = new ReferenceReplacer(oldType, newType);myAssembly.Accept(replacer);

Example Using

CodeDom

Conclusion High Level of Abstraction

No need for handling all the internal details of PEs

At the same time, has the ability to manipulate IL code directly

Object-oriented Model for representation of all assembly modules

Flexible MSIL instruction handling Use of Design Patterns One of the main high-level code

instrumentation libraries for .NET

Questions?

http://rail.dei.uc.pt

Recommended