MS.Net CLR 擴充PE結構分析2

來源:互聯網
上載者:User
Flier Lu <flier_lu@sina.com.cn>
  
注意:本系列文章在水木清華BBS(smth.org)之.Net版首發,
     轉載請保留以上資訊,發表請與作者聯絡
  
Metadata 篇
  
第一章 Metadata 概述
  
1.1 什麼是 Metadata
  
    Metadata翻譯成中文是“中繼資料”,可以理解為Type of Type,
說白了就是描述類型的類型資料。從最初級的語言層面支援的RTTI
(“近代”的程式設計語言基本上都提供了足夠的支援,如C++,Delphi等,
部分較“落伍”的語言也通過不同形式如擴充庫提供了類比支援,
“現代”的程式設計語言則提供了強力的支援,如Java和C#<本質是CLR>),
到後來二進位級的COM的IDL和類型庫(類型庫是IDL編譯後的二進位形式),
到現在的Metadata,其實是遵循著相同的設計思路。只是出於不同的需求
設計、實現,有這各自的優點缺點罷了。但隨著語言的發展,更多的需求集中在
靈活性方面,因而語言發展的趨勢是中繼資料的使用越來越多、支援越來越強。
    舉個最簡單的例子,在IDE中,動態顯示當前對象的方法、屬性名稱列表的功能
(MS叫IntelliSense,Borland叫CodeInsight),就得宜於類型資訊
以前在VC裡實現,比較麻煩,得產生專門的符號庫;在VB裡強一點,可以通過
COM的IDispatch,ITypeInfo,ITypeLib等介面動態擷取,但編程麻煩要死;
到CLR,庫一級直接提供支援,可以通過System.Reflection完全控制
甚至比COM類型庫更高一級地支援動態建立。
   對使用者來說,可以完全瞭解當前程式介面,有哪些Module,哪些Class,
哪些Method等等,這給開發人員提供了巨大的創造空間。如DUnit(DotNet下
的XUnit單元測試平台)就大量使用Reflection機制,我們等會談使用時再說。
  
1.2 Metadata在CLR中的作用
  
    對於CLR架構來說,Metadata可以算是核心操作對象,幾乎絕大多數功能
都需要參考其資料。從靜態IL代碼構成(二進位編碼中直接使用Metadata裡的Token)
到動態JIT編譯器(使用Metadata定位IL代碼及其關係);從簡單的代碼載入執行
(Class Loader通過Metadata定位代碼入口、編譯執行)到複雜的不同語言互操作
(如VB.Net繼承C#的類,實際上是直接繼承CLR中Metadata中的類);等等……
幾乎所有地方都能看到Metadata的身影。
  
    因為本文的主要目的是介紹底層結構,這裡就不再羅嗦Metadata的好處了,
反正以後文章中大家會次次看到他,各種優點自己慢慢體會吧 :)
  
1.3 如何訪問和使用 Metadata
  
   做了一通廣告,大家一定很關心如何使用Metadata,聽我慢慢道來
   在CLR裡使用Metadata,可以在三個層面進行操作。
   最簡單的方法是直接通過類庫提供的System.Reflection命名空間中的
若干類進行訪問,例如
  
using System.Reflection;
using System;
  
public class Simple
{
    public static void Main ()
    {
         Module mod = Assembly.GetExecutingAssembly().GetModules () [0];
         Console.WriteLine ("Module Name is " + mod.Name);
         Console.WriteLine ("Module FullyQualifiedName is " +
mod.FullyQualifiedName);
         Console.WriteLine ("Module ScopeName is " + mod.ScopeName);
    }
}
  
   這種訪問方式使用起來最簡單,功能也足夠強大,能夠完成我們絕大多數的需要,
特別是在System.Reflection.Emit命名空間中,更提供了動態產生、修改的支援
功能強大得我都想不出能有什麼改進了 :) (寫.Net病毒就靠他了,hoho)
   不過這種方式必須有CLR環境的支援,受到庫功能的限制(後面我們會看到很多
在Reflection一級裡不提供的資訊:),因此MS為工具軟體開發商提供了另一套
較底層的開發庫,Metadata Unmanaged API。這套庫通過一系列COM介面,
提供了直接存取Metadata的強大支援,System.Reflection應該就是使用它實現的。
有興趣的朋友可以參看FrameworkSDK\Tool Developers Guide\docs
目錄下的Metadata Unmanaged API.doc文檔,裡面有詳細的說明。
如同其名字所示,它必須用Unmanaged代碼來使用,如傳統的VC,Delphi等。
   可以說99%的工作,都可以通過上面兩套庫來完成,不過總有些象我這樣的人,
喜歡對技術追根究底,想把隱藏在美好面紗下的底層架構糾出來暴露一把,呵呵
因此有了第三個層面,二進位層面的逆向工程分析。
   好在MS為了讓其CLI(CLR的子集)標準化,公開了大量文檔,總算沒要我用上
SoftIce之類的牛刀,Partition II Metadata.doc文檔中對Metadata的
二進位格式實現給出了比較詳盡的說明,加上GNOME的mono項目已經做了很多工作
因而對Metadata的二進位層面分析不是那麼困難。
   接下去的文章中,我會逐漸將Metadata在PE中的組織圖逐漸剝離開來,
讓大家能夠瞭解這個神秘的CLR核心到底是什麼,裡面隱藏了些什麼,我們能夠通過
他做什麼,為什麼要這樣設計,等等……
  
1.4 Metadata在PE中的組織圖
  
   說了一通廢話後,回到正體上來,談談Metadata在PE中的組織圖。
  
注意:這一章裡面我只把Metadata結構的大概情況介紹一下,下一章會專門
針對二進位模式分析進行詳細講解。如果你只想瞭解底層結構,可以跳過
下一章。以後的文章也會遵循這種方式組織,講一些結構、原理,跟著講
一些實際資料分析方法。
  
   上次我們提到CLR的頭資訊裡面專門有一個欄位指向Metadata資料區塊,
實際上這個資料區塊只是Metadata的一個頭結構,儲存有Metadata的資訊,
而Metadata的實際資料,是通過若干不同的Heap或者說Stream儲存的。
這裡我統一使用Stream“流“作為他的名字,但很多文檔中以Heap”堆“作為
其稱呼,我們可以理解他是一個二進位流,其中資料以堆的結構進行組織。
   Metadata裡最常見的有五種流,#String, #Blob, #Guid,
#US(User String)和#~流("#"是流名字的首碼)
   String流就是一個字串堆,Metadata內部用到的所有字串如類或方法
的名字等等都以UTF8編碼儲存在此堆內。而使用者的字串如字串常量,
則以Unicode編碼儲存在US(User String)堆內。值得注意的是,
US流和String流在二進位結構組織上不同,我們後面將分析時會詳細提及。
Guid流是儲存程式中使用到的Guid的數組,如Assembly中Module的MVID。
Blob流是一個通用儲存空間,除了Guid和字串以外基本上所有
亂七八糟的東西都放在裡面,呵呵,如PublicKey,常量的值等等。
   最重要的是#~流,這是Metadata實際資訊存放的地方。#~流結構上以
若干張表(Table)的形式組織,每張表格儲存體某一方面的Metadata資訊,
如MethodDef表格儲存體所有方法的資訊。每張表又由若干的行(Row)組成
每行有n個列(Column),每列代表一種資訊,如MethodDef表中每一行
都有一個方法的RVA,類型標誌,名字,Signature等等資訊。在其中通過
各種索引來相互關聯,整個組織圖和關聯式資料庫很相似。
   比較特殊的是,這裡所有的表通過一個64bit的有效位元影像來表示其存在與否
每種類型的表有一個編號,如MethodDef表的編號是6,則第(1<<(6-1))位置1
因而每個表的每一行,可以使用一個唯一的Token表示。此Token是一個32bit
無符號整型數,最高一個位元組表示表的編號,低三個位元組表示表中的索引號。
如0x06000003表示0x06表(MethodDef)中第3行(如MyApp::Add)
這個Token概念在CLR中頻繁使用,如IL代碼調用函數、使用變數都是使用Token。
   與之類似的還有Coded Index,下次講二進位實現時再說。 

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。