WriteHeader(sw, mbd);
WriteILCode(sw, mbd);
WriteSEH(sw, mbd);
}
从上可以看出,dump一个method需要知道4个东西,token,方法头,ILCode,SEH。jit层脱壳,这个怎么实现呢?DumpMethod函数只需要 invoke方法,让其进入jit处理过程即可。这里需要注意一点:方法是private的,外界无法访问,怎么办?这里我需要用到 net 2.0的又一个新特性:DynamicMethod 。看msdn的介绍:"可以使用 DynamicMethod 类在运行时生成和执行方法,而不必生成动态程序集和动态类型来包含该方法。动态方法是生成和执行少量代码的最有效方式。动态方法在逻辑上与模块或类型关联。如果与模块关联,动态方法对于该模块在全局范围内有效。如果有足够的权限,动态方法可以跳过实时 (JIT) 可见性检查,访问在该模块中所声明类型的私有数据。可以将动态方法与任何模块关联,无论该模块是否由您创建。
如果动态方法与类型关联,动态方法可以访问该类型的私有成员。除非动态方法需要访问在同一模块中声明的其他类型的私有数据,否则无需跳过 JIT 可见性检查。可以将动态方法与任何类型关联。
"动态方法可以跳过 jit 可见性检查。这是我们最关心的。通过它我们解决的private方法的问题。和反射脱壳相比,jit层脱壳真正的DumpMethod 应该是在 hook处理函数中。即在 hook 到一个jit请求后,回调真正的 DumpMethod 实现来完成 一个方法体的脱壳。问题:怎么知道当前jit处理的是哪个方法体呢?"
MethodBase.GetMethodFromHandle (RuntimeMethodHandle) | 通过使用方法的内部元数据表示形式(句柄)获取方法信息。 |
"
这个函数可以解决这个问题。传入的参数,就是我们在 jit hook中截获的 MethodDesc* 的指针变量。这个结构体在sscli里面是没有其明确资料的。但是它可以通过这个函数转换为 。Net中的 Method对象。这样前面提到的dump一个方法体需要的 4个东西,这里就知道了两个了, token 和 ILCode(jit hook直接取得的)。如果是tiny method。方法体也可以重构出来了。之前介绍反射重构的帖子中又详细介绍。如果是fat method呢?有两个难点:1。方法头 中的localsig 的token。 2。SeH 的重构。完全从jit hook到的结构体中重构需要费一番周折,有可能会和壳的实现相关。对于有些加密壳,可以通过投机的方式取得这两个东西。(因目前国内某壳也受此影响,在其新版改进之前,暂不公开这个方式)单纯jit层的加密壳可以从这两点,增加脱壳的难度。
DNGuard 标准版对这两部分做了特许处理。标准版预计在一个星期内完成。演示版RC1已经基本完成,近两天就会发布。DNGuard 专业版,除了对这两个的处理,对ILCode也进行了处理,标准版发布后,需要再花时间对 专业版 IL模拟部分 进行一次全面的检测。