當前位置:
首頁 > 新聞 > 使用公共語言運行時獲取持久性(上)

使用公共語言運行時獲取持久性(上)

本文我們會介紹如何通過使用公共語言運行時應用程序域管理器執行任意代碼並維護對Microsoft Windows系統的訪問。

工具、安全性評估和測試

在安全性評估中,獲得對組織內部網路的初始訪問是一項非常具有挑戰性的任務,需要花費很多的時間和精力。

為了解決這個問題,可以使用多種持久性技術。這些技術可以確保失去訪問權只是暫時的,這意味著你可以在特定的時間或執行特定的操作之後恢復訪問許可權。本文解釋了如何通過使用公共語言運行時應用程序域管理器執行任意代碼並維護對Microsoft Windows系統的訪問。

在這篇文章中,我們將具體介紹:

1.基本.Net知識(例如公共語言運行時,全局程序集緩存);

2.PowerShell腳本的基礎知識;

3.C#編程的基礎知識

.Net概述

.Net是Microsoft於2002年2月發布的開發平台,支持三種語言:C#,F#和Visual Basic .Net(VB.NET)。

C#1.0於2002年1月首次發布,現在是最流行和最常用的.Net語言之一。這是一種高級的面向對象編程語言,主要用於開發胖客戶端應用程序,Web應用程序和移動應用程序(Xamarin)。

F#1.x於2005年5月發布,是一種用於科學和數據分析的強函數式語言。

最後說說VB.NET,其第一個版本於2002年發布,基於Visual Basic 7.0,用於開發桌面應用程序。

.Net之所以變得如此受歡迎的原因是因為它提供了許多有趣的功能,例如:

1.自動內存管理功能:垃圾收集(GC)自動解除分配.Net應用程序使用的已分配內存,另外GC還確保只能訪問分配的內存,從而確保內存安全。

2.使用非託管資源功能:不由.Net維護的資源稱為非託管資源,.Net應用程序可以通過託管類型(例如MemoryStream、CryptoStream、UnmanagedMemoryStream等)使用這些非託管資源。

3.類型安全功能:類型的每個對象都定義了具有不同可訪問級別的方法和屬性,例如private、public、protected、internal、protected internal、private internal。.Net在嘗試訪問未定義或不可訪問的方法或屬性時,通過拋出運行時或編譯時異常來確保類型安全。

4. delegate函數和「Lambda 表達式」:委託(delegate)是一種類型安全的函數指針,用於通用語言運行庫(CLI)。在C#中,delegate是一種class,包裝了一個或多個函數指針及綁定的類實例。「Lambda 表達式」(lambda expression)是一個匿名函數,Lambda表達式基於數學中的λ演算得名,直接對應於其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數,Lambda表達式可以表示閉包(注意和數學傳統意義上的不同)。

5. Java泛型(Generics): 泛型是Java SE 1.5的新特性,泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。Generics有「類的,屬性的」之意,在Java中代表泛型,泛型作為一種安全機制而產生。

類可以利用泛型來允許程序員在構造類時指定類型,例如,實現泛型數據結構的類型是List,它可用於構造字元串List或整數列表的強類型List。

6.非同步編程:通過C#中的async和await關鍵字,編寫I / O綁定和CPU綁定的非同步代碼相當容易,這有助於改善應用程序的執行時間和性能。

7.語言集成查詢(LINQ):語言集成查詢是微軟公司提供的一項新技術。它能夠將查詢功能直接引入到.NET Framework 3.5所支持的編程語言(如C#、Visual Basic等)中,使開發人員能夠在應用程序代碼中形成基於集合的查詢,而不必使用單獨的查詢語言。查詢操作可以通過編程語言自身來傳達,而不是以字元串嵌入到應用程序代碼中。LINQ的語法和語義和SQL很像,具有許多相同的優勢。要查詢的數據的內部結構發送改變後,不必修改查詢代碼。注意,雖然LINQ和SQL看起來很像,但LINQ更加靈活,而且能處理範圍更大的邏輯數據結構。例如,LINQ能處理以層次化的方式組織的數據,例如XML文檔中的數據。

8.互操作性:操作系統提供了應用程序編程介面(API),可以用來訪問操作系統管理的函數和信息的硬體。.Net提供了多種方法來調用系統的API。此外,在Windows上,互操作性允許使用組件對象模型(COM)組件。

7.不安全的代碼:為了操作內存塊(如API調用、指針、演算法),訪問本機內存是必要的,可以在c#中使用不安全的關鍵字來執行不安全的代碼。

雖然多年來,.Net誕生了不同的實現方式,但就本質來講,.Net只有四種主要的實現方式:

·1..Net框架:這是.Net在2002年的最初實現方式,此實現僅適用於Windows系統,用於開發Web,Windows,Windows Phone,Windows Server和Azure的應用程序;

·2..Net內核:這是.Net的開源和跨平台實現,主要用於構建設備、雲和物聯網(IoT)應用程序;

·3. Mono:Mono是基於.Net Framework的.Net的開源和跨平台實現,該框架最初是為在Unix系統上使用.Net Framework應用程序而開發的。現在,Mono主要由Xamarin用於Android,iOS,tvOS和watchOS應用程序。Xamarin作為一個跨平台開發框架始創於2011年,旨在使移動開發變得難以置信地迅捷和簡單。Xamarin的產品簡化了針對多種平台的應用開發,包括iOS、Android、Windows Phone和Mac App。Xamarin由許多著名的開源社區開發者創立和參與,而且也是Mono項目的主導者——C#與?NET框架的開源、跨平台實現。

·4.通用Windows平台(UWP):最後一種實現通常用於開發現代物聯網、移動設備、平板電腦、平板手機或Xbox應用程序。

所有的實現都有兩個共同點:.Net標準,以及一個或多個運行時。.Net標準是每個.Net基類庫實現的一組API。此API可確保任何.Net實現的一致性,從而允許跨實現庫。這個API確保了任何.Net實現的一致性,因此允許跨實現庫。不同的運行時(託管應用程序的執行環境)包括:.Net Framework的公共語言運行時(CLR); .Net Core的內核CLR;用於UWP的.Net Native和用於基於Mono的應用程序的Mono運行時。

公共語言運行時

公共語言運行時(Common Language Runtime,CLR)是Microsoft的公共語中言基礎結構(CLI)的一個商業實現,CLI是一種國際標準,用於創建語言和庫在其中無縫協同工作的執行和開發環境基礎。.NET Framework 提供了一個稱為公共語言運行時的運行環境,它運行代碼並提供使開發過程更輕鬆的服務。有了公共語言運行時,就可以很容易的設計出對象能夠跨語言交互的組件和應用程序。也就是說,用不同語言編寫的對象可以互相通信,並且它們的行為可以緊密集成。

元數據描述應用程序使用的類型、成員和引用,CLR在運行時使用元數據來確保應用程序擁有所需的一切(例如載入程序集、分配內存、生成本機代碼),並設置運行時上下文邊界。

公共語言運行時遵循公共語言架構的標準,能夠使C 、C#、Visual Basic、以及JScript等多種語言深度集成。CLR從某種意義上理解相當於Java中的Java虛擬機(JVM),而MSIL相當於Java中的位元組碼(.class文件)。MSIL總是及時編譯(稱為JIT編譯)為相應平台的機器代碼,這一點與Java也很相似。

編譯將源代碼翻譯為Micrisoft 中間語言(MSIL)並生成所需的元數據。MSIL是一組可以有效地轉換為本機代碼且獨立於CPU的指令。它包括用於載入、存儲和初始化對象以及對對象調用方法的指令,還包括用於算術和邏輯運算、控制流、直接內存存取、異常處理和其他操作的指令。元數據描述代碼中的類型,包括每種類型的定義、每種類型的成員的簽名、代碼引用的成員和運行時在執行時使用的其他數據。

在執行時,實時(JIT)編譯器將MSIL翻譯為本機代碼。在此編譯過程中,代碼必須通過驗證過程,該過程檢查MSIL和元數據以查看是否可以將代碼確定為類型安全。

以上所述可用下圖形象地表示:

通過使用中間語言反彙編程序(ILDASM)二進位文件,可以獲取.exe,.dll,.obj,.lib和.winmd文件的MSIL代碼。請注意,此二進位文件可從Windows軟體開發工具包(SDK)獲得。

例如,可以將以下C#編譯到名為Tool.exe的文件中,然後使用Ildasm.exe進行分析:

using System;

namespace Tools {

class Program {

static void Main(string[] args) {

Console.WriteLine("Hook my Common Language Runtime");

}

}

}

下面的屏幕截圖顯示了通過Ildasm.exe從上面的C#編譯代碼中提取的Main方法的MSIL代碼。

應該注意的是,任何使用CLR的. net應用程序都被認為是託管應用程序。CLR可以使用的代碼也被認為是託管代碼。託管應用程序的主要優點是它們可以從CLR的服務和功能中獲益,例如:

1.跨語言集成;

2.跨語言異常處理;

3.增強的安全性;

4.版本控制和部署支持

5.組件交互的簡化模型

6.調試和分析服務

在上面的功能列表中,最有趣的功能之一是跨語言集成。實際上,任何託管應用程序都可以載入和使用任何託管庫,而不管用於開發庫的語言是什麼。

除了上述問題,還有一個關鍵的問題,就是Windows如何使用CLR執行應用程序?事實上,Windows使用運行時主機,如Microsoft Internet Explorer、APS.Net或Windows shell來執行託管應用程序,這些運行時主機是將CLR的DLL載入到它們的進程空間的進程。

CLR使用的主要DLL是"mscorlib.dll",它代表多語言標準公共對象運行時庫(MS COR LIB)。但是,CLR使用了許多其他DLL,它們都以"mscor"為前綴。因此,可以通過列出以「mscor」開頭的所有DLL名稱來列出CLR在系統上使用的所有DLL。

以下PowerShell cmdlet將通過『C:\Windows\Microsoft.Net\Framework』 文件夾,該文件夾包含.Net Framework DLL並使用『mscor*』過濾名稱。

請注意; .Net Framework 4.0及更高版本中的主要DLL是"clr.dll"。

此外,運行時主機不僅載入CLR的DLL。啟動運行時主機時,將創建一個默認應用程序域,然後在默認應用程序域中載入並執行託管代碼。

以上所述可用下圖形象地表示:

如上圖所示,運行時主機創建一個應用程序域,載入託管代碼,然後在應用程序域中執行JIT編譯器編譯的託管代碼。

應用程序域和應用程序域管理器

應用程序域是安全邊界,執行託管應用程序時,運行時主機將自動創建一個默認的應用程序域。多個應用程序域可以駐留在同一運行時主機中,此安全邊界提供了應用程序域之間的隔離,這意味著應用程序域A無法直接訪問應用程序域B的代碼或資源。

同一運行時主機中的應用程序域之間的隔離提供了以下幾個好處:

1.如果一個應用程序出現故障,則不會影響其他應用程序域;

2.應用程序域可以單獨停止/重新啟動,而無需停止/重新啟動運行時主機;

3.每個應用程序域的代碼都有一組獨特授予的許可權,這些許可權可能與其他應用程序域不同;

4.每個應用程序域都有自己的與域無關的程序集列表,可以根據需要載入或卸載程序集;

應該注意,從一個應用程序域訪問代碼或資源是可能的。但是,需要一個代理。

每個應用程序域都有一種類型的應用程序域管理器,而一個應用程序域管理器可以有X個應用程序域。應用程序域管理器是System.AppDomainManager類,負責創建和自定義新創建的應用程序域。總的來說,這個類公開了4個屬性和6個方法,可以覆蓋這些屬性和方法來修改默認的CLR行為。

以下屏幕截圖顯示了System.AppDomainManager類的屬性和方法。

可以重寫標記為virtual的屬性和方法,並因此在自定義程序集中實現,以便在執行任何託管代碼之前修改新的應用程序域。

下表描述了可以根據Microsoft文檔重寫的屬性和方法:

1.ApplicationActivator:屬性,獲取處理域的外接程序和基於清單的應用程序的激活的應用程序激活器;

2.HostSecurityManager:屬性,獲取參與應用程序域安全性決策的主機安全性管理器;

3.HostExecutionContextManager:屬性,獲取管理執行上下文流程的主機執行上下文管理器;

4.EntryAssembly:屬性,獲取應用程序的項目程序集;

5.CreateDomainHelper:方法,提供用於創建應用程序域的幫助程序方法;

6.CheckSecuritySettings:方法,指示應用程序域中是否允許指定的操作;

7. CreateDomain:方法,返回新的或現有的應用程序域;

8.InitializeNewDomain:方法,初始化新的應用程序域。

此外,因為System.AppDomainManager類繼承自System.MarshalByRefObject,也可以重寫以下方法:

1.ApplicationActivator:屬性,獲取處理域的外接程序和基於清單的應用程序的激活的應用程序激活器。

2.CreateObjRef:方法,創建一個對象,該對象包含生成用於與遠程對象通信的代理所需的所有相關信息;

3.InitializeLifetimeService:方法,獲取生命周期服務對象以控制此實例的生存期策略;

現在,雖然我們已經知道可以重寫的方法和屬性,但是,目前尚不清楚如何更改CLR使用的默認應用程序域管理器。

要解決此問題,必須設置「APPDOMAIN_MANAGER_ASM」和「APPDOMAIN_MANAGER_TYPE」環境變數。它們分別表示從System.AppDomainManager繼承並覆蓋方法和屬性的自定義程序集的全名,以及自定義程序集用於實現System.AppDomainManager類的類型名稱。

最後,由於應用程序域管理器可以修改CLR的安全性決策,因此自定義程序集需要完全受信任,這就要求必須是強名稱程序集,並且必須安裝到全局程序集緩存(GAC)中。

本篇文章,我們已經知道可以重寫的方法和屬性,以及如何更改CLR使用的默認應用程序域管理器。下一篇,我們就來繼續說說如何將實現System.AppDomainManager的強名稱程序集安裝到GAC中,並最終實現使用公共語言運行時獲取持久性。

註:本文參考自contextis.com

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

美國實施DotGov項目確保.GOV域名DNS安全
「專註」是對解謎最好的褒獎