Title: Windows Security Internals
1Advanced.Net Programming
Jan eda Monster Technologies
2Agenda of workshop
3Windos PE file format
Native PE file format
MS-DOS Stub
PE
COFF Header
Section Tables
Code and data
4Executing assembly
- What happens when assembly is started?
- How does an system recognizes .NET environment?
- Is it secure?
- What would you recommend to your client regarding
Windows environment? (when no flameware is
involved ? )
5Starting CLR
- When starting a managed application this triggers
mscoree.dll - _CorExeMain or _Cor
- Mscoree.dll loads CLR
- Native support just from Win XP and Win 2003 and
higher - Open to attacks
- Configuration
ltconfigurationgt ltstartupgt ltsupportedRuntime
version"v2.0.40607"gtlt/supportedRuntimegt
lt/startupgt lt/configurationgt
6Assembly in .NET
MS-DOS Stub
MS-DOS Stub
PE Header
PE Header
CLR Header
CLR Header
Metadata
Manifest
Metadata
IL Code
IL Code
7Executing assembly cont.
Windows environment
CLR
Sample.exe
CLR loads Manifest Metadata
Windows loads PE header
Is it safe for all Windows versions?
Application domain is created and IL code loaded
Gets entry point to start Mscoree.dll
Loads CLR
8How assembly is compiled?
- If C compiler is used then its open to hacking
throw stub attack - C compiler generates own umanaged entry point
to start mscoree.dll gt this opens space for
trojan horses - This is true just for older Windows versions
before Windows XP (WinXP provide new system
loader that automaticaly recognizes .NET
assemblies) - For Windows XP is Code Access Security active
since assembly is started (and CLR loaded).
9Private Assemblies (PA)
- Placed in the root, or sub directory structure of
the application - Will not be shared by multiple applications
- Enables XCopy deployment and Delete uninstall
10Shared Assemblies (SA)
- Designed for use by multiple applications
- Ex Mscorlib.dll
- Each SA is assigned a strong name based on the
public key and the originator name - Shared assemblies have version numbers
11Global Assembly Cache (GAC)
- Central Repository of shared assemblies
- Currently stored in c\winnt\assembly
- gacutil.exe, MSI, or Explorer can be used to
install assemblies in the GAC - Use gacutil l to explore the GAC
12Exploring GAC
- Regsvr32 u shfusion.dll
- Regsvr32 shfusion.dll
- Not recommended for Windows 2003 environment
- There are new versions of this library gt
connected to iexplore process gt system GUI may
not be accessible
13Strong Names Code Signing
- Build Shared Assembly using Public / Private key
pair - Contents of each related file are hashed as their
name is added to the metadata tables. - PE file contents hashed with Private key, hash
value is stored in the file. - Public key value is stored in the file.
- Combination of filename and Public Key become the
shared name. Guaranteed unique. - Created within IDE or with Sn.exe
14Strong Names Benefits
- Guarantee name uniqueness by relying on unique
key-pairs. - Prevent others from "taking over your
namespace." - Protect the version lineage of an assembly
- Guaranteed that the contents of the assembly have
not been changed since it was built - Integrity checking is done on all shared
assemblies using strong / shared names
15Versioning
- Version Policies are applied by the Runtime to
Shared Assemblies only - Version number bindings are captured at compile
time - Version policies are set administratively using
the assemblys .config files ltBinding Policygt
section
16IL Virtual Machine
Memory Generally Available
Memory local to current method
Static Fields
Method Argument Table
Evaluation Stack
Dynamic Memory Pool
Managed Heap
Local Variable Table
17A Threads Stack
Windows Process
void M1() String name Joe M2(name)
... return
name (String)
return address
void M2(String s) Int32 length s.Length
Int32 tally ... return
CLR (Thread Pool Managed Heap)
18Lets do some testing
- using System
- class Program
-
- static int a 1
- static int b 2
- static int Test()
-
- a b
- return 3
-
- static void Main(string args)
-
- a0 Test()
- Console.WriteLine(a0)
-
19Simple Class Hierarchy
class Employee public Int32
GetYearsEmployed() ... public virtual
String GenProgressReport() ... public
static Employee Lookup(String name) ...
class Manager Employee public override
String GenProgressReport() ...
20Instance Method Mapping Using this
public Int32 GetYearsEmployed() public
(static) Int32 GetYearsEmployed(Employee
this) public virtual String GenProgressReport()
public (static) String GenProgressReport(Emplo
yee this) public static Employee
Lookup(String name) public static Employee
Lookup(String name)
Employee e new Employee() e.GetYearsEmployed()
e.GenProgressReport()
Employee e new Employee() Employee.GetYearsEmpl
oyed(e) Employee.GenProgressReport(e)
- this is what makes instance data available to
instance methods
21IL Instructions ToCall A Method
- Call
- Is usable for static, instance, and virtual
instance methods - No null check for the this pointer (for instance
methods) - Used to call virtual methods non-polymorphically
- base.OnPaint()
- Callvirt
- Usable for instance and virtual methods only
- Slower perf
- Null check for all instance methods
- Polymorphs for virtual methods
- No polymorphic behavior for non-virtual methods
- C and VB use callvirt to perform a null check
when calling instance methods
22class App static void Main() Object
o new Object() o.GetHashCode() //
Virtual o.GetType() // Non-virtual
instance Console.WriteLine(1) // Static
.method private hidebysig static void Main() cil
managed .entrypoint // Code size 27
(0x1b) .maxstack 1 .locals init (object
V_0) IL_0000 newobj instance void
System.Object.ctor() IL_0005 stloc.0
IL_0006 ldloc.0 IL_0007 callvirt instance
int32 System.ObjectGetHashCode() IL_000c
pop IL_000d ldloc.0 IL_000e callvirt
instance class System.Type System.ObjectGetType(
) IL_0013 pop IL_0014 ldc.i4.1 IL_0015
call void System.ConsoleWriteLine(int32)
IL_001a ret // end of method AppMain
23Memory Code, Types, Objects
Windows Process
Stack
null
Jitted Code
5
0
Jitted Code
void M3() Employee e Int32 year e new
Manager() e Employee.Lookup(Joe) year
e.GetYearsEmployed() e.GenProgressReport()
Jitted Code
Jitted Code
CLR (Thread Pool Managed Heap)
24Garbage Collection
- Garbage Collection is the process of recovering
managed memory that is no longer being used - Garbage Collection is automatically handled by
the runtime - Garbage Collection can be forced programmatically
(but should not be)
25Traditional Heaps
- Heap Manager keeps list of free and used blocks
- On an Memory Allocation, manager searches lists
for a space big enough for requested block - On a Deallocation, manager must check if newly
freed block should be merged with an adjacent
free block - Result gt Work on Allocs Deallocs
- Doesnt scale well on multi-threaded or
multi-proc systems
26What techniques were used?
- Reference counting
- Typical for COM environment based on C/C
pointer style - Some automatic techniques as
- Smart pointers (ATL)
- Auto-reference counting (VB6)
- Suitable only for client-server pattern
- Open to deadlocks by cycle references
B
X
A
C
27The Managed Heap
- How many managed heaps are there? Important!!!!
- All reference types are allocated on the managed
heap - Your code never frees an object
- The GC frees objects when they are no longer
reachable - Each process gets its own managed heap
- Virtual address space region, sparsely allocated
- The new operator always allocates objects at the
end - If heap is full, a GC occurs
- Reality GC occurs when generation 0 is full
NextObjPtr
28How GC controls application?
- Hijacking
- GC overwrites return address from a method with
address of one of its methods. After method is
executed gt control is traversed to GC. - Safe Points
- Points where JIT decides that are safe to suspend
a thread and start GC. JIT compiler inserts code
here. - Interruptible code
- The simplest technique available only in .NET
1.0. GC suspends all threads and inspects memory
by method table produced by JIT to find variables
that are in scope.
29Roots and GC Preparation
- Every application has a set of Roots
- A Root is a memory location that can refer to an
object - Or, the memory location can contain null
- Roots can be any of the following
- Global static fields, local parameters, local
variables, CPU registers - When a method is JIT compiled, the JIT compiler
creates a table indicating the methods roots - The GC uses this table
- The table looks something like this...
Start Offset End Offset Roots________________ 0x00
000000 0x00000020 this, arg1, arg2, ECX,
EDX 0x00000021 0x00000122 this, arg2, fs,
EBX 0x00000123 0x00000145 fs
30When a GC Starts...
- All objects in heap are considered garbage
- The GC assumes that no roots refer to objects
- GC examines roots and marks each reachable object
- If a GC starts and the CPUs IP is at 0x00000100,
the objects pointed to by the this parameter,
arg2 parameter, fs local variable, and the EBX
register are roots these objects are marked as
in use - As reachable objects are found, GC uses metadata
to check each objects fields for references to
other objects - These objects are marked in use too, and so on
- GC walks up the threads call stack determining
roots for the calling methods by accessing each
methods table - For objects already in use, fields arent
checked - Improves performance
- Prevents infinite loops due to circular
references - The GC uses other means to obtain the set of
roots stored in global and static variables
31Generations in GC
Heap begins with one and new generation
References to objects are kept alive
GC defragments and compacts references
Objects are joined into newer generation
New objects are allocated in new generation
32Allocation on Managed Heap
O1
Cursor
33Allocation on Managed Heap
O1
O2
Cursor
34Allocation on Managed Heap
O1
O2
O4
O5
O6
O3
O7
Cursor
35Garbage Collection
- At some point the Garbage Collection algorithm
decides that memory has grown too much - A Collection is triggered
- All Unreferenced (garbage) objects deleted from
the heap - What are Unreferenced Objects
- Determined through the creation of a reference
tree
36Garbage Collection
- Attempt to create object at end of heap triggers
garbage collection - Builds reference tree starting with roots
- Global and static object pointers, CPU registers
containing heap pointers, etc. - Begins building the tree with the first root,
recursively moving on to all objects that object
referenced etc. - Then on to the next root until finished
37Garbage Collection Triggered
O1
O2
O4
O5
O6
O3
O7
GC ROOTS(References) Globals Statics Locals
CPU Registers
38Garbage Collection
- When finished deletes garbage
- Moves all code down filling GCd areas in the
heap - Cursor reset to beginning of free memory
39Garbage Collection Triggered
O1
O2
O4
O5
O6
O3
O7
GC ROOTS(References) Globals Statics Locals
CPU Registers
40Garbage Collected
O1
O2
O4
O5
O6
GC ROOTS(References) Globals Statics Locals
CPU Registers
41Garbage Collection
- Pointers adjusted appropriately including objects
containing pointers to other objects - Operation that triggered the garbage collection
is retried
42Compacting the Heap
- After all roots have been checked and all objects
have been marked in use... - The GC walks linearly through heap for free gaps
and shifts reachable objects down (simple memory
copy) - As objects are shifted down in memory, roots are
updated to point to the objects new memory
address - After all objects have been shifted...
- The NextObjPtr pointer is positioned after last
object - The new operation that caused the GC is retried
- This time, there should be available memory in
the heap and the object construction should
succeed - If not, an OutOfMemoryException is thrown
43How does GC work here?
- using System
- namespace ConsoleApplication1
-
- class Program
-
- static void Main(string args)
-
- // allocate and forget the objects
immediately - // AllocForget()
- // allocate array and overwrite
random objects with new ones - AllocOver()
-
- public static void AllocForget()
-
- for ( )
-
- new object()
44How does GC work here?
45How does GC work here?
46Server vs. Workstation
- Mscoree chooses workstation or server mode
- Workstation optimized for front-end, interactive
apps - Server optimized for throughput
- Server optimized for multi-CPUs computers
ltconfigurationgt ltruntimegt ltgcServer
enabledtrue" /gt lt/ runtimegt lt/configurationgt
47Server vs. Workstation
- There are three modes of GC available
- Can be checked programmatically by
System.Environment.IsServerGC
48Garbage Collector - CPUs
- When working on multiple CPUs garbage collector
can have different behavior - This is for server mode
- CLR allocates separate heaps for each physical
CPU - Called arenas
- Allows lock-free allocation
- GC is done in parallel
- Each CPU cleans up its own heap
49GC isnt perfect!
- How much memory does GC thinks this occupies?
- GC doesnt see the image
Gen0 heap
Bitmap object (40 bytes)
Bitmap buffer (20MB)
50How to educate GC?
- AddMemoryPressure
- Be VERY careful when using it
- class Bitmap IDisposable
-
- FileInfo file
- public Bitmap(string path)
-
- file new FileInfo(path)
- GC.AddMemoryPressure(file.Length)
- ...
-
- override void Dispose()
-
- GC.RemoveMemoryPressure(file.Length)
-
-
51Limited resouces and GC
- Some resources have a hard upper limit
- Database connections, GDI handles etc.
- Forcing GC can help free them up
- In .NET2.0 HandleCollector attemtps to help
- Monitors a count of add/remove calls
- Calls GC.Collect when count gt threshold
- Must have rights to run interop
static readonly HandleCollector conns new
HandleCollector(DB, 4, 10) public class
MyConnection IDisposable public
MyConnection() conns.Add() public override
void Dispose() conns.Remove()
52GC Dos and Donts
- Dont call GC.Collect
- Dont use finalizers unless you are absolutely
sure what you are doing - Do call Debug.Assert(false) in finalizers
- Do call GC.SupressFinalize from
IDisposable.Dispose - Do use performance counters to measure changes
53Cleaning Up
- Traditional Languages (C COM based languages
like VB) provide Deterministic Finalization - When an object goes out of scope, the objects
Destructor is executed - The CLRs Garbage Collected environment does not
provide this - The replacement
- Finalization and the Dispose pattern
54Why Do I Care?
- Who cares about destructors in a Garbage
Collected environment? - Not all resources are managed
- Database connections
- Windows Handles
- Etc
- The Finalize method allows you to clean up
these resources, but - If you wait for objects to Finalize, you may end
up in a resource starved situation
55Finalization
- After an object is marked for collection (but
before it is collected), it may be finalized - Finalization happens eventually
- Only objects with Finalize methods get treated
this way - Finalization is expensive
- Objects get shuffled around on lists at GC time
- Since the Finalization happens after the object
is marked, it cant be collected until the next
GC operation - Delaying the GC for that object
56Finalization queue
Application threads
Garbage Collection
Objects placed on freachable
Calling finalizers
Finished garbage Collection
57Update info on finalization queue!
- Finalization queue is used for Finalize methods
- According to further testing finally blocks are
not included in finalization queue as was
presented - Correct definition is that finalization queue is
related ONLY to finalizers and it doesnt affect
finally
58The Dispose Pattern
- The Frameworks answer to Determistic
Finalization - Allows aggressive disposal of objects that use
unmanaged resources - Not needed for objects that only have managed
data members - Objects that use unmanaged resources should
implement the IDisposable interface - IDisposableDispose()
- Well documented
- Example Create a Windows.Forms application
59Using Disposable Objects
Dim X as New DisposableTypeTry do something
with X Finally X.Dispose()End Try using
(DisposableType x new DisposableType)
//do something with X
60Equivalence vs. Identity
- Different instances of objects with same values,
but different memory addresses gt not the same
objects! - This is equivalence
- To check objects equivalence System.Object.Equal
virtual method should be implemented for specific
reference type - When references of objects point to the same
address space gt this is one and the same object - Can be checked by the method System.Object.Referen
ceEquals, GC.ReferenceEquals
61A
x 0
B
y 0
C
D
x 5
x 3
y 0
y 2
62Object equals
63Cloning
- Implementation of System.ICloneable interface gt
Clone method - Shallow copy vs. Deep copy
64Shallow copy
x 0
y 0
Class Data
A
Just Reference
B
x 0
y 0
65Shallow copy
66Deep copy
x 0
y 0
Class Data
A
Class Data
B
x 0
y 0
67Memory referencesConsider design
68Memory referencesConsider design
69Multithreading
- What is a multithreading and how does it work in
Windows and CLR? - How many threads are in this app?
using System namespace ConsoleApplication1
class Program static void
Main(string args)
Console.Read()
70Native threads in .NET
- Lets enumerate native threads in .NET application
71Threads in CLR
- Managed threads are different from native ones
- There are two types of managed threads
- Thread-pool threads (System.Threading.ThreadPool)
- Background threads
- Limited number of threads in pool (OS dependant)
- Can be changed by hacking into CLR
- Non-thread pool threads
- All new Thread() instances
72Max. of threads in pool
73How to use thread pool?
- Thread pool has background threads gt process is
not alive when there are just background threads - Why does a thread pool exists?
- Number of thread in pool is changing depending on
number of CPU and OS - ThreadPool is suitable for background
asynchronous operations
74ThreadPool
75Synchronization in CLR
- CLR provides several thread synchronization
techniques - Monitor
- Most common
- Integrated
- Other techniques
- Mutex class for deadlock-free multiple lock
acquisition - Events
- Multi-reader/single-writer support
- WaitHandles
- ReadWriteLocks very strong feature
- Semaphores
76Monitor
- Used to work with protected code sections
- Thread sychronization primitives control access
of threads to objects - Lock statements are finally compiled
lock (x) // some code goes here
object temp x Monitor.Enter(temp) // some
code goes here // using temp finally
Monitor.Exit(temp)
lock (typeof(x)) // some code goes here
77Deadlocks
- Deadlocks gt2 threads are waiting cyclically for
each other - Mutexes can be used to protect from deadlocks
First thread lock(x) // do something with
x lock(y) // work with x and y Second
thread lock(y) lock(x) // work with x and
y
WaitHandle mutexes new WaitHandle2 mutexes
0 mutexY mutexes1 mutexX WaitHandle.WaitA
ll(mutexes) // do something with x and
y mutexX.ReleaseMutex() mutexY.ReleaseMutex()
78Races
- Races conditions occur when result of some code
depends on unpredictable timing factors
lock(x) // do something with x lock(y)
lock(x) // work with x and y