天天看點

淺談.Net脫殼中方法體的局部變量簽名還原

在之前介紹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層實作預處理同樣也是這兩個難點。