主頁 > .NET開發 > .NET 7 的 AOT 到底能不能扛反編譯?

.NET 7 的 AOT 到底能不能扛反編譯?

2022-11-24 06:19:34 .NET開發

一:背景

1.講故事

在B站,公眾號上發了一篇 AOT 的文章后,沒想到反響還是挺大的,都稱贊這個東西能抗反編譯,可以讓破解難度極大提高,可能有很多朋友對逆向不了解,以為用 ILSpy,Reflector,DnSpy 這些工具打不開就覺得很安全,其實不然,在 OllyDbg,IDA,WinDBG 這些逆向工具面前一樣是裸奔,

既然大家都很感興趣,那這篇就和大家聊一聊,

二:幾個例子

1. 動態修改程式資料

修改程式資料在逆向中再正常不過了,由于目前的 AOT 只能發布成 x64 ,這里就用 WinDbg 做下演示,首先看下例子,


    internal class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.WriteLine("hello world!");
                Thread.Sleep(1000);
            }
        }
    }

程式在不斷的輸出,接下來我們將 hello world 中的 world 給去掉,操作手法非常簡單,先記憶體搜索找到 hello world,然后修改 length=5 即可,


0:005> lm
start             end                 module name
00007ff7`95b70000 00007ff7`95e5d000   ConsoleApp1 C (private pdb symbols)  

0:005> s-u 00007ff7`95b70000 L?0x00007ff7`95e5d000 hello
00007ff7`95e1c41c  0068 0065 006c 006c 006f 0020 0077 006f  h.e.l.l.o. .w.o.

0:000> dp 00007ff795e1c41c-0x4 L1
00007ff7`95e1c418  00650068`0000000c

0:000> eq 00007ff7`95e1c418 00650068`00000005
0:000> g

2. 獲取程式托管堆

AOT 再怎么牛,它侄訓是個托管程式,既然是托管程式自然就有托管堆,托管堆中就有所有的托管資料,玩過 SOS.dll 朋友應該知道,用 !eeheap -gc 就能把托管堆給顯示出來,比如下面這樣,


0:022> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x000002414D891030
generation 1 starts at 0x000002414D891018
generation 2 starts at 0x000002414D891000
ephemeral segment allocation context: none
         segment             begin         allocated         committed    allocated size    committed size
000002414D890000  000002414D891000  000002414D8D1FE8  000002414D8D2000  0x40fe8(266216)  0x41000(266240)
Large object heap starts at 0x000002415D891000
         segment             begin         allocated         committed    allocated size    committed size
000002415D890000  000002415D891000  000002415D891018  000002415D892000  0x18(24)  0x1000(4096)
Pinned object heap starts at 0x0000024165891000
0000024165890000  0000024165891000  0000024165899C10  00000241658A2000  0x8c10(35856)  0x11000(69632)
Total Allocated Size:              Size: 0x49c10 (302096) bytes.
Total Committed Size:              Size: 0x42000 (270336) bytes.
------------------------------
GC Allocated Heap Size:    Size: 0x49c10 (302096) bytes.
GC Committed Heap Size:    Size: 0x42000 (270336) bytes.

雖然目前的 AOT 不支持 SOS 擴展,無法顯示出托管堆,但一點關系都沒有,SOS 是通過 DataAccess 去挖的,大不來我手工挖一下就好了哈,接下來就是怎么挖的問題了,熟悉 CLR 的朋友應該知道所謂的托管堆在內部用的是 generation_table[] 一維資料來維護的,以 的方式來劃分,代的落地是用 heap_segment 來表示的, 參考代碼如下:


generation gc_heap::generation_table [total_generation_count];

enum gc_generation_num
{
    // small object heap includes generations [0-2], which are "generations" in the general sense.
    soh_gen0 = 0,
    soh_gen1 = 1,
    soh_gen2 = 2,
    max_generation = soh_gen2,

    // large object heap, technically not a generation, but it is convenient to represent it as such
    loh_generation = 3,

    // pinned heap, a separate generation for the same reasons as loh
    poh_generation = 4,

    uoh_start_generation = loh_generation,

    // number of ephemeral generations
    ephemeral_generation_count = max_generation,

    // number of all generations
    total_generation_count = poh_generation + 1
};

接下來用 x 命令看下陣列內容,代碼如下:


0:000> x ConsoleApp1!WKS::gc_heap::generation_table
00007ff7`95e25010 ConsoleApp1!WKS::gc_heap::generation_table = class WKS::generation [5]

0:000> dx -r1 (*((ConsoleApp1!WKS::generation (*)[5])0x7ff795e25010))
(*((ConsoleApp1!WKS::generation (*)[5])0x7ff795e25010))                 [Type: WKS::generation [5]]
    [0]              [Type: WKS::generation]
    ...
    [4]              [Type: WKS::generation]

0:000> dx -r1 (*((ConsoleApp1!WKS::generation *)0x7ff795e25010))
(*((ConsoleApp1!WKS::generation *)0x7ff795e25010))                 [Type: WKS::generation]
    [+0x038] start_segment    : 0x25100000000 [Type: WKS::heap_segment *]
    [+0x040] allocation_start : 0x25100001030 : 0x38 [Type: unsigned char *]
    [+0x048] allocation_segment : 0x25100000000 [Type: WKS::heap_segment *]
    [+0x0d0] allocation_size  : 0x0 [Type: unsigned __int64]
    [+0x100] gen_num          : 0 [Type: int]
    ...

0:000> dx -r1 ((ConsoleApp1!WKS::heap_segment *)0x25100000000)
((ConsoleApp1!WKS::heap_segment *)0x25100000000)                 : 0x25100000000 [Type: WKS::heap_segment *]
    [+0x000] allocated        : 0x25100001048 : 0x90 [Type: unsigned char *]
    [+0x008] committed        : 0x25100012000 : Unable to read memory at Address 0x25100012000 [Type: unsigned char *]
    [+0x010] reserved         : 0x25110000000 : 0x18 [Type: unsigned char *]
    [+0x018] used             : 0x25100009fe0 : 0x0 [Type: unsigned char *]
    [+0x020] mem              : 0x25100001000 : 0x38 [Type: unsigned char *]
    [+0x028] flags            : 0x0 [Type: unsigned __int64]
    [+0x030] next             : 0x0 [Type: WKS::heap_segment *]
    ...

上面的這些欄位就描述出了 !eeheap -gc 的結果,接下來想挖什么,提取什么我就不過多介紹了,

3. 提取托管執行緒串列

提取 托管執行緒 串列也是非常重要的, 它能指示出很多資訊,一般用 !t 命令就能顯示,輸出如下:


0:022> !t
ThreadCount:      17
UnstartedThread:  0
BackgroundThread: 6
PendingThread:    0
DeadThread:       0
Hosted Runtime:   no
                                                                                                            Lock  
 DBG   ID     OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
   0    1     4128 000002414BDB8C70    2a020 Preemptive  000002414D8C6108:000002414D8C8000 000002414bdaf8f0 -00001 MTA 
   6    2     4458 000002414BDE5EB0    2b220 Preemptive  0000000000000000:0000000000000000 000002414bdaf8f0 -00001 MTA (Finalizer) 
   7    4     23e8 000002416DDB15C0  102b220 Preemptive  000002414D8C9250:000002414D8CA000 000002414bdaf8f0 -00001 MTA (Threadpool Worker) 
   ...
  20   17     50a8 000002416DE43DD0  102b220 Preemptive  000002414D8BC2D0:000002414D8BDFD0 000002414bdaf8f0 -00001 MTA (Threadpool Worker) 
  21   18     57d4 000002416DE628E0  8029220 Preemptive  000002414D8CC2A8:000002414D8CE000 000002414bdaf8f0 -00001 MTA (Threadpool Completion Port) 

既然目前的 SOS 不支持,同樣可以手工到 CLR 中去挖,熟悉的朋友應該知道 !t 的資料源來自于 ThreadStore::s_pThreadStore 下的 m_ThreadList 集合,它以鏈表的形式串聯了每個執行緒的 LinkPtr 欄位,但可惜的是,在 AOT 中,這一塊已經重寫了,由 g_pTheRuntimeInstance 全域變數下的 m_ThreadList 來維護了,

為了方便觀察,多生成幾個 Thread,


        static void Main(string[] args)
        {
            Debugger.Break();

            var tasks = Enumerable.Range(0, 10).Select(m => new Thread(() =>
            {
                Console.WriteLine($"tid={Thread.CurrentThread.ManagedThreadId} 已執行!");
                Console.ReadLine();
            }));

            foreach (var item in tasks)
            {
                item.Start();
            }

            Console.ReadLine();
        }

程式跑起來后,深挖 g_pTheRuntimeInstance 全域變數即可,


0:015> x ConsoleApp1!g_pTheRuntimeInstance
00007ff7`0155ee20 ConsoleApp1!g_pTheRuntimeInstance = 0x00000291`cb5b9300
0:015> dx -r1 ((ConsoleApp1!RuntimeInstance *)0x291cb5b9300)
((ConsoleApp1!RuntimeInstance *)0x291cb5b9300)                 : 0x291cb5b9300 [Type: RuntimeInstance *]
    [+0x000] m_pThreadStore   : 0x291cb5b9390 [Type: ThreadStore *]
    ...
0:015> dx -r1 ((ConsoleApp1!ThreadStore *)0x291cb5b9390)
((ConsoleApp1!ThreadStore *)0x291cb5b9390)                 : 0x291cb5b9390 [Type: ThreadStore *]
    [+0x000] m_ThreadList     [Type: SList<Thread,DefaultSListTraits<Thread,DoNothingFailFastPolicy> >]
    [+0x008] m_pRuntimeInstance : 0x291cb5b9300 [Type: RuntimeInstance *]
    [+0x010] m_Lock           [Type: ReaderWriterLock]
0:015> dx -r1 (*((ConsoleApp1!SList<Thread,DefaultSListTraits<Thread,DoNothingFailFastPolicy> > *)0x291cb5b9390))
(*((ConsoleApp1!SList<Thread,DefaultSListTraits<Thread,DoNothingFailFastPolicy> > *)0x291cb5b9390))                 [Type: SList<Thread,DefaultSListTraits<Thread,DoNothingFailFastPolicy> >]
    [+0x000] m_pHead          : 0x291ed366240 [Type: Thread *]
0:015> dx -r1 ((ConsoleApp1!Thread *)0x291ed366240)
((ConsoleApp1!Thread *)0x291ed366240)                 : 0x291ed366240 [Type: Thread *]
    ...
    [+0x058] m_pNext          : 0x291cb6aeb60 [Type: Thread *]
    [+0x060] m_hPalThread     : 0x204 [Type: void *]
    [+0x068] m_ppvHijackedReturnAddressLocation : 0x0 [Type: void * *]
    [+0x070] m_pvHijackedReturnAddress : 0x0 [Type: void *]
    [+0x078] m_uHijackedReturnValueFlags : 0x0 [Type: unsigned __int64]
    [+0x080] m_pExInfoStackHead : 0x0 [Type: ExInfo *]
    [+0x088] m_threadAbortException : 0x0 [Type: Object *]
    [+0x090] m_pThreadLocalModuleStatics : 0x291cb6aee90 [Type: void * *]
    [+0x098] m_numThreadLocalModuleStatics : 0x1 [Type: unsigned int]
    [+0x0a0] m_pGCFrameRegistrations : 0x0 [Type: GCFrameRegistration *]
    [+0x0a8] m_pStackLow      : 0xf754100000 [Type: void *]
    [+0x0b0] m_pStackHigh     : 0xf754200000 [Type: void *]
    [+0x0b8] m_pTEB           : 0xf7533ba000 : 0x0 [Type: unsigned char *]
    [+0x0c0] m_uPalThreadIdForLogging : 0x2044 [Type: unsigned __int64]
    [+0x0c8] m_threadId       [Type: EEThreadId]
    [+0x0d0] m_pThreadStressLog : 0x0 [Type: void *]
    [+0x0d8] m_interruptedContext : 0x0 [Type: _CONTEXT *]
    [+0x0e0] m_redirectionContextBuffer : 0x0 [Type: unsigned char *]
0:015> dx -r1 (*((ConsoleApp1!EEThreadId *)0x291ed366308))
(*((ConsoleApp1!EEThreadId *)0x291ed366308))                 [Type: EEThreadId]
    [+0x000] m_uiId           : 0x2044 [Type: unsigned __int64]

從CLR 的 Thread 維護的資訊來看,這個結構體已經很小了,也說明 AOT 在Thread資訊維護上做了很多的精簡,

三:總結

總的來說,AOT 確實能加速程式的初始啟動,一體化的打包機制也非常方便部署,但怎么變終究還是一個托管程式,需要底層的 C++ 托著它,扛 反編譯 無從談起,所以防小人的話,該加殼的加殼,該混淆的混淆,

圖片名稱

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/538092.html

標籤:.NET技术

上一篇:SQL Server(解決問題)已成功與服務器建立連接,但是在登錄程序中發生錯誤。provider:SSL Provider,error:0 - 證書鏈是由不受信任的頒發機構頒發的

下一篇:ASP.NET Core 簡介

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more