共两篇,第一篇和壳本身的过程关系不大,主要是涉及了虚方法的内容,第二篇则详细调试了CLISecure的保护原理。在我的blog上名为CLR内核调试随记,因为是随记,所以文章中可能有不全面甚至错误的地方。找到错误的朋友请与偶联系。性急的兄弟请直接看第二篇。
本文章所调试壳为CLISecure,下载地址为http://www.secureteam.net/,最新版本为3.0,而我所调试的版本为2.5,所以可能与最新的壳有所不同。
CLR内核随记(1)
把平时看到的一些东西记下来,没准以后用的上。
本文利用调试跟踪CLR中接口virtual方法的定位。为什么呢?好玩儿而已。
这是在某壳挂钩JIT的代码,有些东西还是很有意思(总是觉得这些壳作者知道很多CLR的内部结构,估计微软对他们部分开源了):
.text:10002A4C mov eax, [ebp+ICorJitInfo]
.text:10002A4F mov ecx, [eax+4]
//此时ecx==.text:79E97C14 const CEEJitInfo::`vbtable’{for `ICorJitInfo’},第一个双字是什么?第一个双字指向
.text:79E97B14 dd offset [thunk]:CEEInfo::getHelperName`vtordisp{4294967292,52}’ (CorInfoHelpFunc)
到这里,来看看CEEJitInfo::’vbtable’在内存中的表示:
79E97C14 >FC FF FF FF 34 00 00 00 3C 00 00 00 44 00 00 00
79E97C24 4C 00 00 00 54 00 00 00 5C 00 00 00 64 00 00 00
79E97C34 6C 00 00 00 74 00 00 00 80 00 00 00 FC FF FF FF
其实这些值是在编译时确定的,因为CLR本身部分用C++写成,也就是C++中的vtable在编译时确定,mscorwks.dll中的代码如下:
.text:79E97C14 const CEEJitInfo::`vbtable’{for `ICorJitInfo’} dd 0FFFFFFFCh, 34h, 3Ch, 44h, 4Ch, 54h, 5Ch, 64h, 6Ch
.text:79E97C14 dd 74h, 80h
FCFFFFFF是what?谁知道,也许是一个vtable的开始标志,因为在第三行最后又见到一个同样的双字。计算两个FCFFFFFF之间的双字值,可以先猜测这个vtable含有10个方法。不过sscli中对应的代码却多出了一两个方法,这里暂且不管,下面主要看怎么定位这些vtable的。
.text:10002A52 mov edx, [ecx+4]
.text:10002A55 mov eax, [ebp+ICorJitInfo]
.text:10002A58 mov ecx, [eax+4]
.text:10002A5B mov eax, [ecx+4]
.text:10002A5E mov ecx, [ebp+ICorJitInfo]
.text:10002A61 lea eax, [ecx+eax+4]
.text:10002A65 mov ecx, [ebp+ICorJitInfo]
.text:10002A68 mov edx, [ecx+edx+4]
在lea eax这句执行完后,eax指向内存如下
0013EA18 78 7B E9 79 00 00 00 00 4C 7B E9 79 00 00 00 00
0013EA28 A8 7A E9 79 00 00 00 00 84 7A E9 79 00 00 00 00
总觉得后面那句mov edx,[ecx+edx+4]重复了,直接mov edx,[eax]不就可以了吗?这时[eax]的值是79E97B78指向什么?它指向了下面一个方法:
.text:79E97B78 const CEEJitInfo::`vftable’{for `ICorMethodInfo’} dd offset [thunk]:CEEInfo::getMethodName`vtordisp{4294967292,52}’ (CORINFO_METHOD_STRUCT_ *,char const * *)