JITHook.NET JIT Compilation
Hooking Techniqueand Its Packer / Unpacker

CyCraft Proprietary and Confidential Information

WhoamiShu-Ming Chang (@LJP-TW)
Intern at CyCraft
SQLab@NYCU
Pwn / Reverse / Cat <3
CTF Team
10sec
XxTSJxX

2

CyCraft Proprietary and Confidential Information

.NET Concepts.NET Packers

Outline

JITHook
JITPacker

JITUnpacker
Evaluation

3

CyCraft Proprietary and Confidential Information

.NET Concepts

How .NET works?
Compile source code to CIL(Common Intermediate Language),
stored in assembly
The assembly stores a lot of stuff
MethodDef
Param
ManifestResource
ModuleRef
ImplMap
5

CyCraft Proprietary and Confidential Information

Source Code(e.g. C#)

Assembly (exe, dll)

Methods

Resources

Inspect assembly with dnSpy
6

CyCraft Proprietary and Confidential Information

Stream #~How .NET works?
CLR (Common Language Runtime)
JIT compiling CIL to machine code

MemoryAssembly (exe, dll)
Method A

Method B

Managing codes
CLR
JIT compiler

Machine Codeof Method A

7

CyCraft Proprietary and Confidential Information

.NET Packers

.NET Packers
Obfuscate/Encrypt the original CIL in assembly
Restore the original CIL at runtime

9

CyCraft Proprietary and Confidential Information

.NET Packers
Categorize packers based on how they restore the CIL
There are 2 types of packers
Type 1: Restore CIL before it’s been JIT compiled
e.g. ConfuserEx

Type 2: Hook JIT compiler’s method, specifically compileMethod.
e.g. .NET Reactor
JITHook

10

CyCraft Proprietary and Confidential Information

.NET Packers

Type 1: Restore CIL before it’s been JIT compiled
e.g. ConfuserEx

11

CyCraft Proprietary and Confidential Information

Type 1 Packer: Restore CIL before it’s been JIT compiled
Assembly
UnpackMethodMethod 1
Packed IL

CLR

CompileMethod

Unpack Method
Machine Code

12

CyCraft Proprietary and Confidential Information

Method n
Pakced IL

Type 1 Packer: Restore CIL before it’s been JIT compiled
Assembly
UnpackMethodUnpack Method
restores all others
methods IL

Method 1
Origin IL

CLR

CompileMethod

Unpack Method
Machine Code13

CyCraft Proprietary and Confidential Information

Method n
Origin IL

Type 1 Packer: Restore CIL before it’s been JIT compiled
Assembly
UnpackMethodMethod 1
Origin IL

Then the program will
run normally
CLR

CompileMethod

Method 1
Machine Code

14

CyCraft Proprietary and Confidential Information

Method n
Origin IL

.NET Packers

Type 2: Hook JIT compiler’s method, specifically compileMethod.
e.g. .NET Reactor
JITHook

15

CyCraft Proprietary and Confidential Information

Type 2 Packer: JITHook
Assembly
Hook
MethodPackerCM

vtableCLR

CompileMethod

Hook Method
Machine Code16

CyCraft Proprietary and Confidential Information

Method n
Pakced IL

CMpointer

Type 2 Packer: JITHook
Assembly
Hook
MethodPacker
CM

Method n
Pakced IL

Hook CompileMethod
to Packer CM
vtableCLR

CompileMethod

Hook Method
Machine Code17

CyCraft Proprietary and Confidential InformationCM
pointer

Type 2 Packer: JITHook
Assembly
Hook
MethodvtableCLR

CompileMethod

Method n
Machine Code18

CyCraft Proprietary and Confidential Information

Method n
Pakced IL

Method n
Origin IL

Packer CM can allocate aspace to put original IL
Send it to original
CompileMethod

PackerCM

CM
pointerUnpacker
Type 1: Restore CIL before it’s been JIT compiled
Dump unpacked assembly from memory at runtime

Type 2: JITHook
That's what we're going to deal with

19

CyCraft Proprietary and Confidential Information

JITHook

JITHook
Let’s see the definition of the class that has this vtable.NET source code → Github: dotnet/runtime
ICorJitCompiler
vtableCLR
CompileMethod

Hook Method
Machine Code21

CyCraft Proprietary and Confidential InformationCM
pointer

class ICorJitCompiler{
public:virtual CorJitResult compileMethod (ICorJitInfo*comp,
struct CORINFO_METHOD_INFO *info,
unsigned /* code:CorJitFlag */flags,
uint8_t**nativeEntry,
uint32_t*nativeSizeOfCode) = 0;/* IN *//* IN *//* IN *//* OUT *//* OUT */virtual void ProcessShutdownWork(ICorStaticInfo *info) {};virtual void getVersionIdentifier(
GUID *versionIdentifier/* OUT */) = 0;
virtual unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) {return 0; }virtual void setTargetOS(CORINFO_OS os) = 0;};
22

CyCraft Proprietary and Confidential Information

virtual CorJitResult compileMethod (ICorJitInfo*comp,
struct CORINFO_METHOD_INFO *info,
unsigned /* code:CorJitFlag */flags,
uint8_t**nativeEntry,
uint32_t*nativeSizeOfCode) = 0;/* IN *//* IN *//* IN *//* OUT *//* OUT */compileMethod is the main routine to
ask the JIT Compiler to create native code for a method

23

CyCraft Proprietary and Confidential Information

CORINFO_METHOD_INFO

24

CyCraft Proprietary and Confidential Information

getJit()How do we get the ICorJitCompiler object?
Use getJit()! And it is exported by clrjit.dll
Then we can know the address of the vtable

Then we can get/set the compileMethod function pointer!
extern "C" ICorJitCompiler * getJit();25

CyCraft Proprietary and Confidential Information

JITHook
Save the original compileMethod
Overwrite it with compileMethodHook
AddDllDirectory(L"C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\");
clrjit = LoadLibraryExA("clrjit.dll", NULL, LOAD_LIBRARY_SEARCH_USER_DIRS);
getjit = (func *)GetProcAddress(clrjit, "getJit");
ICorJitCompilerPtr = getjit();
ICorJitCompilerVtable = *(void ***)CorJitCompilerPtr;
originCompileMethod = (compileMethodFunc *)ICorJitCompilerVtable[0];VirtualProtect(&ICorJitCompilerVtable[0], 0x8, PAGE_EXECUTE_READWRITE, &old);
ICorJitCompilerVtable[0] = compileMethodHook;
VirtualProtect(&ICorJitCompilerVtable[0], 0x8, old, &old);
26

CyCraft Proprietary and Confidential Information

compileMethod
Do anything before calling the original compileMethod
CorJitResult compileMethodHook(void*thisptr,
ICorJitInfo*comp,
struct CORINFO_METHOD_INFO*info,
unsigned /* code:CorJitFlag */flags,
uint8_t**nativeEntry,
uint32_t*nativeSizeOfCode) {// Do something/* IN *//* IN *//* IN *//* OUT *//* OUT */return originCompileMethod(thisptr, comp, info, flags, nativeEntry, nativeSizeOfCode);}

27

CyCraft Proprietary and Confidential Information

JITPacker

JITPacker
We implemented JITPacker using JITHook
Save the original CIL to the resource
Modify most of the original CIL code to byte 0x87

Add module initializer to the assembly to hook CM ptr to
packer CM
Restore the CIL in packer CM

29

CyCraft Proprietary and Confidential Information

JITPacker
Save the original CIL to the resource
Modify most of the original CIL code to byte 0x87

30

CyCraft Proprietary and Confidential Information

static void packMethod(TypeDef type, MethodDef method){// Get codesize// Read origin IL
byte[] originILbytes = reader.ReadBytes(codesize);// Save origin IL to resources
module.Resources.Add(new EmbeddedResource(method.MDToken.ToString().ToLower(),
originILbytes,
ManifestResourceAttributes.Private));for (int i = 0; i < method.Body.Instructions.Count - 1; i++) {// If this instruction cannot be patchedif (...) { continue; }// Patch instructions to byte 0x87
method.Body.Instructions[i] = OpCodes.Conv_Ovf_U2_Un.ToInstruction();for (int _ = 0; _ < inssize - 1; ++_) {method.Body.Instructions.Insert(i, OpCodes.Conv_Ovf_U2_Un.ToInstruction());
}
}
}
31

CyCraft Proprietary and Confidential Information

Assembly
Methods
Method 1
Pakced IL

Method 2
Pakced IL

Method n
Pakced IL

Resources
Method 1
Origin IL

32

CyCraft Proprietary and Confidential Information

Method 2
Origin IL

Method n
Origin IL

JITPacker

Add module initializer to the assembly to hook CM ptr to
packer CM

33

CyCraft Proprietary and Confidential Information

// Create module initializer
MethodDef cctor = new MethodDefUser(".cctor",
MethodSig.CreateStatic(module.CorLibTypes.Void));
cctor.Attributes = MethodAttributes.Public | MethodAttributes.SpecialName |MethodAttributes.RTSpecialName | MethodAttributes.Static;
cctor.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
moduleType.Methods.Add(cctor);// Find “entry” method of packer module
MethodDef packerEntry = packerType.FindMethod("entry");// Call “entry” method of packer module in module initializer
var cctorILbody = new CilBody();
cctor.Body = cctorILbody;
cctorILbody.Instructions.Add(OpCodes.Call.ToInstruction(packerEntry));
cctorILbody.Instructions.Add(OpCodes.Ret.ToInstruction());

34

CyCraft Proprietary and Confidential Information

public static unsafe void entry() {// Use getJit() to get ICorJITCompiler, the get original compileMethod
pCompileMethod = Marshal.ReadIntPtr(VTableAddr);
OriginalCompileMethod =(CompileMethodDel64)Marshal.GetDelegateForFunctionPointer(
Marshal.ReadIntPtr(pCompileMethod),
typeof(CompileMethodDel64));// Pre-compile some functions
RuntimeHelpers.PrepareMethod(
typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }).MethodHandle);// Overwrite compileMethod pointer in vtable of ICorJITCompiler
if (!VirtualProtect(pCompileMethod, (uint)IntPtr.Size,
Protection.PAGE_EXECUTE_READWRITE, out old))
throw new Exception("[!] Cannot change memory protection flags.");Marshal.WriteIntPtr(pCompileMethod,
Marshal.GetFunctionPointerForDelegate(packerCM));
VirtualProtect(pCompileMethod, (uint)IntPtr.Size, (Protection)old, out old);}
35

CyCraft Proprietary and Confidential Information

Assembly
Methods

Module initializer

Hook
MethodPacker
CM

Method n
Pakced IL

Resources
Method 1
Origin IL

36

CyCraft Proprietary and Confidential Information

Method 2
Origin IL

Method n
Origin IL

JITPacker

Restore the CIL in packer CM

37

CyCraft Proprietary and Confidential Information

private static unsafe int packerCM(IntPtr thisPtr, [In] IntPtr corJitInfo,[In] CorMethodInfo64* methodInfo, CorJitFlag flags,[Out] IntPtr nativeEntry, [Out] IntPtr nativeSizeOfCode) {// Calculate methodToken
string methodToken = (0x06000000 + *(ushort*)methodInfo->ftn).ToString("x8");// Try to get original CIL from resource
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream stream = assembly.GetManifestResourceStream(methodToken);if (stream == null) {return OriginalCompileMethod(...);}// Patchbyte[] newil = new byte[stream.Length];
stream.Read(newil, 0, newil.Length);
IntPtr ilCodeHandle = Marshal.AllocHGlobal(newil.Length);
Marshal.Copy(newil, 0, ilCodeHandle, newil.Length);methodInfo->ilCode = (byte*)ilCodeHandle.ToPointer();
methodInfo->ilCodeSize = (uint)newil.Length;
return OriginalCompileMethod(thisPtr, corJitInfo, methodInfo,flags, nativeEntry, nativeSizeOfCode); }38

CyCraft Proprietary and Confidential Information

JITUnpacker

Unpack JITHook .NET assembly
Hook CompileMethod before it’s been hooked
Get the unpacked CIL from Packer CM
Rebuild the unpacked assembly

40

CyCraft Proprietary and Confidential Information

JITUnpacker

Prepare CLR with
CLR Hosting
CLR

vtableCompileMethod

41

CyCraft Proprietary and Confidential InformationCM
pointer

JITUnpacker

Hook CompileMethod
to Unpacker CM

Unpacker CM
CLR

vtableCompileMethod

42

CyCraft Proprietary and Confidential InformationCM
pointer

JITUnpacker
Assembly
Hook
MethodLoad packed assembly

PackerCM

Unpacker CM
CLR

vtableCompileMethod

43

CyCraft Proprietary and Confidential Information

Method n
Pakced IL

CMpointer

JITUnpacker
Assembly
Hook
MethodAssembly hooks
CompileMethod
to Packer CM

PackerCM

Unpacker CM
CLR

vtableCompileMethod

Hook Method
Machine Code44

CyCraft Proprietary and Confidential Information

Method n
Pakced IL

CMpointer

JITUnpacker
Assembly
Hook
MethodPacker
CM

Method n
Pakced IL

Method n Origin IL
Intercept unpacked IL
Save it
Pass it to original CM

Use Unpack Info to rebuild
unpacked assembly after
the process is terminatedUnpacker CM
CLR

vtableCompileMethod

Method n
Machine Code45

CyCraft Proprietary and Confidential Information

UnpackInfo

CMpointerUnpack JITHook .NET assembly
There are 2 type of method headers
If
IL code size >= (1<<6)Or the method has local variables
Or the method has EH (Exception Handler)

Then the method header is fat format

Otherwise, the header is tiny format

46

CyCraft Proprietary and Confidential Information

Unpack JITHook .NET assembly
CorILMethod_TinyFormat
Only need the unpacked CIL code and size to rebuild

CorILMethod_FatFormat
Not only need the unpacked CIL code and size to rebuild, but also
EH (Exception Handler) table
LocalVarSigTok

47

CyCraft Proprietary and Confidential Information

EH Table
How to get EH table?
There is a member function getEHinfo() in class ICorJitInfo

48

CyCraft Proprietary and Confidential Information

EH Table// src/coreclr/inc/corjit.hclass ICorJitCompiler{
virtual CorJitResult compileMethod (ICorJitInfo*comp,
struct CORINFO_METHOD_INFO *info,
unsigned /* code:CorJitFlag */flags,
uint8_t**nativeEntry,
uint32_t*nativeSizeOfCode) = 0;...
}

class ICorJitInfo : public ICorDynamicInfo
{
...
}

49

CyCraft Proprietary and Confidential Information// src/coreclr/inc/corinfo.hclass ICorDynamicInfo : public ICorStaticInfo{...
// get individual exception handler
virtual void getEHinfo(
CORINFO_METHOD_HANDLE ftn,
unsigned
EHnumber,
CORINFO_EH_CLAUSE* clause) = 0;...
}

EH Table
What is the index of getEHinfo() in the vtable?
Let’s find a callsite of getEHinfo() and reverse it

50

CyCraft Proprietary and Confidential Information

CORINFO_EH_CLAUSE clause;
info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
51

CyCraft Proprietary and Confidential Information

Info.compCompHnd is a ICorJitInfo pointer

CORINFO_EH_CLAUSE clause;
info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
52

CyCraft Proprietary and Confidential Information

*
*
*
*
*
*
*
*
*
*

mov
mov
mov
mov
call
mov
lea
mov
mov
call

rdi, [rsi+1AB8h]; this->info.compCompHnd (ICorJitInfo *)rax, [rdi]; vtable (clr!CEEJitInfo::’vftable’)rbx, [rax+40h] ; vtable[8] (clr!CEEJitInfo::getEHinfo)
rcx, rbx
cs:__guard_check_icall_fptr ;rdx, [rsi+1AD0h]r9, [rbp+clause]
r8d, r12d
rcx, rdirbx; (clr!CEEJitInfo::getEHinfo)

Info.compCompHnd is a ICorJitInfo pointer

CORINFO_EH_CLAUSE clause;
info.compCompHnd->getEHinfo(info.compMethodHnd, XTnum, &clause);
53

CyCraft Proprietary and Confidential Information

EH Table
We can get getEHinfo() address from ICorJitInfo pointerpassed to compileMethod()Then use it to get EH table
CorJitResult compileMethodHook(void*thisptr,
ICorJitInfo*comp,
struct CORINFO_METHOD_INFO*info,
unsigned /* code:CorJitFlag */flags,
uint8_t**nativeEntry,
uint32_t*nativeSizeOfCode){...
vtable = *((void ***)comp);
getEHinfo = (getEHinfoFunc *)vtable[8];
...
}
54

CyCraft Proprietary and Confidential Information/* IN *//* IN *//* IN *//* OUT *//* OUT */LocalVarSigTokinfo->locals.pSig points to the LocalVarSig in #Blob stream
struct CORINFO_METHOD_INFO{CorJitResult compileMethodHook(struct CORINFO_METHOD_INFO*info,)CORINFO_SIG_INFO};
55

CyCraft Proprietary and Confidential Information

locals;LocalVarSigTokinfo->locals.pSig points to the LocalVarSig in #Blob stream+ 0:007 > dt clrjit!CORINFO_SIG_INFO

struct CORINFO_METHOD_INFO{+ 0x048 pSig
CORINFO_SIG_INFO};

56

CyCraft Proprietary and Confidential Information

locals;: Ptr64 UChar

LocalVarSigTok
LocalVarSigTok of StandAlongSig.row[n] is 0x11000000 | (n + 1)

+0x00
+signature#~ Stream
57

CyCraft Proprietary and Confidential Information

Rows of StandAlongSig

LocalVarSig#Blob Stream

LocalVarSigTok
Compare pSig and StandAlongSig.row[n] to find LocalVarSigTok
LocalVarSigTok = 0x11000003

Rows of StandAlongSig

58

CyCraft Proprietary and Confidential Information+0x308

LocalVarSig 1+0x30cLocalVarSig 2+0x311

LocalVarSig 3+0x326

LocalVarSig 4#Blob Stream

pSig

info->locals.pSig

Unpack JITHook .NET assembly
CorILMethod_TinyFormat
Only need the unpacked CIL code and size to rebuild

CorILMethod_FatFormat
Not only need the unpacked CIL code and size to rebuild, but also
EH (Exception Handler) table
LocalVarSigTok

Now we have gathered all the information we need
So we can rebuild the unpacked assembly!
59

CyCraft Proprietary and Confidential Information

Evaluation

SampleSample 1:
Use .NET Reactor packer to pack test assembly
Only enable NecroBit option, focus on testing type 2 packer

61

CyCraft Proprietary and Confidential Information

62

CyCraft Proprietary and Confidential Information

SampleSample 2:
Use JITPacker to pack test assembly

63

CyCraft Proprietary and Confidential Information

64

CyCraft Proprietary and Confidential Information

Unpacker
Try unpacking the samples using the following unpackers
De4dot.NETReactorSlayer
mandiant/jitm
JITUnpacker

65

CyCraft Proprietary and Confidential Information

Result

66

CyCraft Proprietary and Confidential Information

Sample 1 (.NET Reactor)

Sample 2 (JITPacker)

De4dot❌

❌

.NETReactorSlayer⭕

❌

mandiant/JITM🔺

🔺

JITUnpacker⭕

⭕

mandiant/jitm
A github repository, last updated 2 years ago (Dec, 2020)
The mechanism of JITM is very similar with JITUnpacker
Problems of JITM:
JITM doesn’t handle EH table
JITM can’t process assemblies that require user interaction
JITM can’t process assemblies which’s machine field of PE fileheader isn’t 0x14c (Intel 386)
JITM only collects unpacked CIL which the name of the assembly
which the method belongs to is equal to file name67

CyCraft Proprietary and Confidential Information

Conclusion
JITHook: Overwrite the vtable of JIT compiler.
The current unpacker only supports unpacking assemblies
packed with specific packers

JITUnpacker does not target to certain packers
but JITHook
In theory, JITUnpacker can handle any assembly thatpacked by a packer that uses JITHook technique

68

CyCraft Proprietary and Confidential Information

Source code
https://github.com/LJP-TW/JITHook

69

CyCraft Proprietary and Confidential Information

ReferencesReferences
Hijacking .NET to Defend PowerShell
Unpack Your Troubles: .NET Packer Tricks And Countermeasures
Jerry Wang - .NET CLR Injection: Modify IL Code during Run-time

浅谈.Net.NET JIT

71

CyCraft Proprietary and Confidential Information签 还码Thank You!
Q&A

72

CyCraft Proprietary and Confidential Information

CyCraft Proprietary and Confidential Information

Method in PE

MetaData+0x00

PE\0\0
+0x08

+0xF8

MetaData (RVA)

CLI Header+0x00

Signature (0x424A5342)+0x0c

Version Length x+0x10

VersionPadding (Align 4-byte)+0x12+x

Number of streams n+0x14+x

Stream Header 1…

Stream Header n
PE Header(AMD64)74

CyCraft Proprietary and Confidential Information

CLI Header

MetaData Root

MetaData+0x00

PE\0\0
+0x08

+0xF8

MetaData (RVA)

CLI Header+0x00

Signature (0x424A5342)+0x0c

Version Length x+0x10

VersionPadding (Align 4-byte)+0x12+x

Number of streams n+0x14+x

Stream Header 1…

Stream Header n
PE Header

75

CyCraft Proprietary and Confidential Information

dnSpy

CLI Header

MetaData RootStream Header+0x00

Signature (0x424A5342)+0x0c

Version Length x+0x10

Version+0x00

Offset (from Metadata Root)

Padding (Align to 4-byte)

+0x04

Size

+0x08

Name

+0x12+x

Number of streams n+0x14+x

Stream Header 1

Padding (Align 4-byte)…

Stream Header nMetaData Root76

CyCraft Proprietary and Confidential Information

Stream Header

#~ Stream
+0x08

Valid

+0x00

Offset (from Metadata Root)

+0x04

Size

+0x18

Rows[0]

+0x08

#~\0

+0x1c

Rows[1]…

Padding (Align 4-byte)Rows[n]+0x18+4xn#~ Stream Header

77

CyCraft Proprietary and Confidential Information

Tables#~ Stream

Metadata Tables
There are various metadata
tables+0x00
Offset (from Metadata Root)
MethodDef

+0x08

Valid

+0x04

Size

+0x18

Rows[0]

+0x08

#~\0

+0x1c

Rows[1]

Param

ManifestResource
Padding (Align 4-byte)
ModuleRef

ImplMap…

78

CyCraft Proprietary and Confidential Information…
Rows[n]+0x18+4xn

Tables#~ Stream

Metadata Tables
Metadata tables are stored in
the column Tables in #~stream+0x00 Offset (from Metadata Root)

+0x08

Valid

+0x04

+0x18

Rows[0]+0x1c

Rows[1]Size

Tablesare in a#~\0
certain order+0x08
Padding (Align 4-byte)
0x00 Module

0x01 TypeRef…
0x06 MethodDef
79

CyCraft Proprietary and Confidential Information…
Rows[n]+0x18+4xn

Tables#~ Stream

Metadata Tables
If n-th bit of Valid is 0
The n-th table has no rows.

+0x08

Valid

Size

+0x18

Rows[0]+0x08
The n-th table#~\0
has Rows[i] rows

+0x1c

Rows[1]+0x00

Offset (from Metadata Root)

Otherwise
+0x04
i++

…

Padding (Align 4-byte)Rows[n]+0x18+4xn

Tables#~ Stream

80

CyCraft Proprietary and Confidential Information

Example
+0x08

Valid

0x….57+0x18

Rows[0]0x01

0th-bit of Valid: 1+0x1c

Rows[1]0x2cModule table
has Rows[0] rows

+0x20

Rows[2]

0x0e

+0x24

Rows[3]0x79…

Module81

CyCraft Proprietary and Confidential Information

Module.row[0]Example
+0x08

Valid

0x….57+0x18

Rows[0]0x01

1st-bit of Valid: 1+0x1c

Rows[1]

0x2c

TypeRef table
has Rows[1] rows

+0x20

Rows[2]

0x0e

+0x24

Rows[3]0x79…

ModuleModule.row[0]TypeRef

TypeRef.row[0]…
TypeRef.row[0x2b]82

CyCraft Proprietary and Confidential Information

Example
+0x08

Valid

0x….57+0x18

Rows[0]0x01

2nd-bit of Valid: 1+0x1c

Rows[1]

0x2c

TypeDef table
has Rows[2] rows

+0x20

Rows[2]

0x0e

+0x24

Rows[3]0x79…

TypeRef

TypeRef.row[0x2b]

TypeDef

TypeDef.row[0]…
TypeDef.row[0xd]83

CyCraft Proprietary and Confidential Information

Example
+0x08

Valid

0x….57+0x18

Rows[0]

0x01

3rd-bit of Valid: 0+0x1c

Rows[1]

0x2c

FieldPtr table
has no rows

+0x20

Rows[2]

0x0e

+0x24

Rows[3]0x79…

TypeDef

84

CyCraft Proprietary and Confidential Information

TypeDef.row[0xd]Example
+0x08

Valid

0x….57+0x18

Rows[0]0x01

4th-bit of Valid: 1+0x1c

Rows[1]

0x2c

Field table
has Rows[3] rows

+0x20

Rows[2]

0x0e

+0x24

Rows[3]0x79…

TypeDef
Field

TypeDef.row[0xd]Field.row[0]…
Field.row[0x78]85

CyCraft Proprietary and Confidential Information

MethodDef

+0x08

Valid

+0x18

Rows
…

MethodDef

+0x00

RVA

+0x08

Name Index+0x00+Name Index

Method Name

MethodDef.row[n]…
#~ Stream

86

CyCraft Proprietary and Confidential Information

Row of MethodDef#Strings Stream

Method

+0x08

Valid

+0x18

Rows
…

MethodDef

+0x00

RVA

Method Header
Method Body (CIL)+0x08

Name Index

Extra Sections

Row of MethodDef

MethodMethodDef.row[n]…
#~ Stream

87

CyCraft Proprietary and Confidential Information

Method
MethodToken of MethodDef.row[n] is
0x06000000 | (n + 1)
+0x08

Valid

+0x18

Rows
…

MethodDef

+0x00

RVA

Method Header
Method Body (CIL)+0x08

Name Index

Extra Sections

Row of MethodDef

MethodMethodDef.row[n]…
#~ Stream

88

CyCraft Proprietary and Confidential Information

Method
There are 2 type of method headers
CorILMethod_TinyFormat
+0x08

Valid
CorILMethod_FatFormat
+0x00

+0x18

Rows
…

MethodDef

RVA

Method Header
Method Body (CIL)+0x08

Name Index

Extra Sections

MethodDef.row[n]…
Method89

CyCraft Proprietary and Confidential Information

Method
If
IL code size >= (1<<6)+0x08

MethodValidhas local variables
+0x00

RVA

has EH (Exception Handler)+0x18 MethodRows+0x08 Name Index…

Then the method header is fat format

MethodDef

Method Header
Method Body (CIL)
Extra Sections

MethodDef.row[n]Otherwise,… the header is tiny format
Method90

CyCraft Proprietary and Confidential Information

CorILMethod_TinyFormat

4A 00 7E 01 00 00 04 7E 02 00 00 04 58 80 01 00
00 04 2A

91

CyCraft Proprietary and Confidential Information

CorILMethod_TinyFormat

4A
Bit[0:2] (0x02)
Flags (Must be 0x2)

Bit[2:8] (0x48 >> 2 = 0x12)
Size of method body (CIL)92

CyCraft Proprietary and Confidential Information

CorILMethod_TinyFormat

00 7E 01 00 00 04 7E 02 00 00 04 58 80 01 00
00 04 2A
Method body (CIL)

93

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
1B 30 01 00 12 00 00 00 01 00 00 11 00 00 28 03
00 00 06 00 02 0A DE 04 26 00 FE 1A 06 2A 00 00
01 10 00 00 00 00 01 00 0B 0C 00 04 01 00 00 01

94

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
1B 30 01 00 12 00 00 00 01 00 00 11

Method Header

95

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
1B 30 01 00 12 00 00 00 01 00 00 11

Method Header
Flags

96

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
1B 30 01 00 12 00 00 00 01 00 00 11

Method Header
Flags

MaxStack

97

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
1B 30 01 00 12 00 00 00 01 00 00 11

Method Header
Flags

MaxStack
CodeSize

98

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
1B 30 01 00 12 00 00 00 01 00 00 11

Method Header
Flags

MaxStack
CodeSize
LocalVarSigTok

99

CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
00 00 28 03
00 00 06 00 02 0A DE 04 26 00 FE 1A 06 2A 00 00
Method body (CIL)

100 CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat
00 00 28 03
00 00 06 00 02 0A DE 04 26 00 FE 1A 06 2A 00 00
Method body (CIL)
Pad with 0x00 to align to 4-byte boundary

101 CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat

01 10 00 00 00 00 01 00 0B 0C 00 04 01 00 00 01
Extra method data section (Optional)
Currently, this section is only used forEH (Exception Handler) table

102 CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat

01 10 00 00 00 00 01 00 0B 0C 00 04 01 00 00 01
Extra method data section (Optional)
Flag (0x01 means this section is EH Table)

103 CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat

01 10 00 00 00 00 01 00 0B 0C 00 04 01 00 00 01
Extra method data section (Optional)
Flag

DataSize (size of this section)

104 CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat

01 10 00 00 00 00 01 00 0B 0C 00 04 01 00 00 01
Extra method data section (Optional)
Flag

DataSize
Reserved

105 CyCraft Proprietary and Confidential Information

CorILMethod_FatFormat

01 10 00 00 00 00 01 00 0B 0C 00 04 01 00 00 01
Extra method data section (Optional)
Flag

DataSize
Reserved
EH Clauses (Records the offset and length of try blocks and handlers)

106 CyCraft Proprietary and Confidential Information

StandAlongSig
LocalVarSigToken of StandAlongSig.row[n] is 0x11000000 | (n + 1)

+0x08

Valid

+0x18

Rows

Offset+0x00+Offset…

LocalVarSig

StandAlongSig.row[n]…
#~ Stream

Row ofStandAlongSig

107 CyCraft Proprietary and Confidential Information#Blob Stream

CLR HostingCLR Hosting

MemoryUse unmanaged code to host CLR
Let native process has the ability toload assemblies and run managed
code

Unmanaged code

CLR Hosting
CLR

JIT compiler

109 CyCraft Proprietary and Confidential Information

Get ICLRMetaHost interface

110 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Get ICLRRuntimeInfo interface

111 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Check whether the
CLR is loadable

112 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Load the CLR and Return
ICorRuntimeHost interface
pointer

113 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Start the CLR

114 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Memory

Unmanaged Code

CLR Hosting

CLR
JIT compiler

115 CyCraft Proprietary and Confidential Information

Gets an interface pointer oftype System._AppDomain

116 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Prepare SAFEARRAY
Copy entire assembly to array

117 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Load the assembly to CLR

118 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Memory
Assembly (exe, dll)
Entry
Point

Unmanaged CodeLoad assembly

Method B

CLR
JIT compiler

119 CyCraft Proprietary and Confidential Information

Get MethodInfoPtr
of entry point

120 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Prepare parameter forthe assembly

121 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Invoke entry point!

122 CyCraft
CyCraft Proprietary
Proprietary andand Confidential
Confidential Information
Information

Memory
Assembly (exe, dll)
Entry
Point

Unmanaged CodeInvoke entry point

Method B

CLR
JIT compiler

Machine Codeof Entry Point

123 CyCraft Proprietary and Confidential Information