在之前介紹Jit層脫殼原理時曾提到兩個難點,
1。方法體的局部變量簽名。
2。方法體的SEH 異常處理表。
本文主要就第一個問題進行簡單探讨,随帶也涉及到一些第二個問題。
前面提到過投機的方式擷取,不在本文讨論範圍,投機總是過于僥幸。
進入到Jit層後,局部變量簽名已經由token值轉變為了結構體 CORINFO_SIG_INFO ,可以推測,該轉變應該是在 ee 層調用 jit的預處理過程中完成了。
參考sscli的源代碼,很容易可以定位到一個關鍵函數 unsigned long __stdcall UnsafeJitFunction(class MethodDesc *, class COR_ILMETHOD_DECODER *, unsigned long) 在 .net 1.1 中好像名字叫 JitFunction 。
隻要Hook這個函數,就可以擷取到需要的東西了。
第一個參數,前面提到過了,可以轉換為dotNet中的方法對象。第二個參數,是本文要提到的關鍵東西。關于它的定義可以參考sscli或者dotNet的sdk。
從名字就能看出它是幹什麼用的。如果你好彩,得到它就得到了整個方法體(如:.Net reactor, maxtocode 2007之前版本以及2007個人版,dnguard v1.0)。
如果殼在Jit層有挂鈎,那麼基本上可以判斷這裡無法取得IL位元組碼(如果殼采用分段解密,在這裡不會解密IL位元組碼,它會把IL位元組碼的解密放到Jit層中)。
基本上可以确定這裡能夠擷取到LocalVarSig 的 token值。
同時順帶一般也能擷取到SEH Table。
這裡需要注意,如果殼在附近也有挂鈎,需要判斷它是否挂了這個函數,然後需要調整一下hook位置。
還有一個不錯的hook位置是 getMethodInfoHelper(MethodDesc *,CORINFO_METHOD_STRUCT_ *,COR_ILMETHOD_DECODER *,CORINFO_METHOD_INFO *)。
這個方法再配合 jit層的hook,加在一起基本上就完成了一個方法體的完整還原。
使用這個方法對 CliProtector,DNGuard HVM 加密保護的程式集無效。
這兩個是純Jit層的殼,在ee層沒有挂鈎服務提供解密,是以在這個方法hook不到所需的東西。
它們實際上是把預處理的工作全部放到了殼裡面。
也許有人會有疑惑,既然這樣加密殼為什麼還要在ee層挂鈎提供解密服務呢?這是幾個技術問題,
加密殼需要在ee層挂接解密服務,一般是沒有解決如何在殼中實作全部預處理的工作。
在Jit層實作預處理工作與在Jit層中直接實作脫殼是一個互逆的操作。
前面介紹Jit層脫殼時提到過兩個難點,在jit層實作預處理同樣也是這兩個難點。