Reverse Engineering a Dotnet Monitor
von Felix Mößbauer
For my master thesis I had to reverse engineer a Dotnet monitor to intercept certain function calls. While this is not scientific enought to put in in the thesis, it might help someone facing similar problems.
The general strategy to locate the synchronisation related symbols is to use a tiny C# program with a synchronized loop (see below).
This issues many calls to the monitor. Our goal is to find the unknown Monitor.Exit
symbol.
Thereto we set a breakpoint on the known Monitor.Enter
symbol and inspect the assembly at the breakpoint location.
We know, that each entry to the monitor must be followed by an exit statement. So the number of entry and exit calls must match.
Using this information, we simply count the number of calls to functions near the Monitor.Enter
breakpoint.
This finally points us to JIT_MonExit
.
The WinDbg console output of the sampel C# program is shown below. Breakpoints are set on:
System.Private.CoreLib!System.Threading.Monitor.Enter*
coreclr!JIT_MonExit
To trace the objects the monitor is bound to, we further inspect the function arguments. For the Monitor.Enter
function, we know that it takes two arguments. Furthermore the calling convention is cdecl
.
Hence, the first argument is 0x20d'3835b9d8
and the second 0x0
(read in right-to-left order).
For tracing, we must be able to distinct between monitors on different objects.
From the Monitor.Enter
function we are able to derive that the first argument is a reference to the object.
Hence, a distinction between different monitors is trivially possible by checking the first argument of the Enter
and Exit
function calls.
Sample Program The shown function is executed in parallel by multiple threads.
public static void IncByOne(param p)
{
lock (p)
{
Inc(p);
int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Value on {0} is {1}", threadId, p.acc);
}
}
}
WinDbg Output
Breakpoint 2 hit
System_Private_CoreLib!System.Threading.Monitor.Enter(System.Object, Boolean ByRef)$##6001EDB:
00007ff9`c11bdb40 4883ec28 sub rsp,28h
0:006> kv
# Child-SP RetAddr : Args to Child : Call Site
00 000000e8`c25ff4b8 00007ff9`fe1fed8f : 0000020d`38359eb0 0000020d`38359ec8 00000000`00000000 0000020d`3835b9d8 : System_Private_CoreLib!System.Threading.Monitor.Enter(System.Object, Boolean ByRef)$##6001EDB
01 000000e8`c25ff4c0 00007ff9`e7da5ac7 : 0000020d`38358fc8 00007ff9`d1b4552f 0000020d`38359920 0000020d`38359938 : System_Console!System.IO.SyncTextWriter.WriteLine(System.String)$##60001B6+0x2f
02 000000e8`c25ff510 00007ff9`fe1f570e : 00000000`00000003 000000e8`c25ff600 0000020d`38359078 00000000`00000007 : System_Runtime_Extensions!System.IO.TextWriter.WriteLine(System.String, System.Object, System.Object)$##6000458+0x47
[...]
13 000000e8`c25ffe60 00007ffa`0f6c0c31 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
14 000000e8`c25ffe90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
0:006> g
Breakpoint 1 hit
coreclr!JIT_MonExit:
00007ff9`d1b94650 33d2 xor edx,edx
0:006> kv
# Child-SP RetAddr : Args to Child : Call Site
00 000000e8`c25ff4b8 00007ff9`fe1fedc0 : 0000020d`38359eb0 0000020d`38359ec8 00000000`00000000 0000020d`3835b9d8 : coreclr!JIT_MonExit [E:\A\_work\2188\s\src\vm\amd64\JitHelpers_InlineGetThread.asm @ 673]
01 000000e8`c25ff4c0 00007ff9`e7da5ac7 : 0000020d`38358fc8 00007ff9`d1b4552f 0000020d`38359920 0000020d`38359938 : System_Console!System.IO.SyncTextWriter.WriteLine(System.String)$##60001B6+0x60
02 000000e8`c25ff510 00007ff9`fe1f570e : 00000000`00000003 000000e8`c25ff600 0000020d`38359078 00000000`00000007 : System_Runtime_Extensions!System.IO.TextWriter.WriteLine(System.String, System.Object, System.Object)$##6000458+0x47
[...]
13 000000e8`c25ffe60 00007ffa`0f6c0c31 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
14 000000e8`c25ffe90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
Ähnliche Beiträge
von Felix Mößbauer
Kommentare
Einen Kommentar schreiben