再探.NET的PE檔案結構(安全篇)

BattleHeart發表於2019-05-11

再探.NET的PE檔案結構(安全篇)

一、開篇

首先寫在前面,這篇文章源於個人的研究和探索,由於.NET有自己的反射機制,可以清楚的將原始碼反射出來,這樣你的軟體就很容易被破解,當然這篇文章不會說怎麼樣保護你的軟體不被破解,相反是借用一個軟體來講述是怎麼被攻破的,也會有人說這是一篇破文,我其實這篇文章已經寫了很長時間了,不知道以什麼形式發出來,因為畢竟是有些破解類的東西。但是我覺得從這篇文章相反的是能夠帶來一些啟發。大家應該都知道Reflector這個反編譯軟體還有一個外掛是專門用來改IL的外掛叫Reflexil,這裡我們也要用到前面那個工具Reflector,後面的外掛我們這裡我們不用,接下來分析的東西可以讓大家能夠更深入.NET的PE,深入內幕來看看,好,閒話少說….直接上分析。


二、詳細分析過程

如果不懂.NET的PE檔案結構的帥哥美女,可以看一下上一篇文章http://www.80iter.com/blog/1414333757520474,這裡要用到PE的知識,首先我們來看一下這個程式的限制,這個程式有顯示限制也就是顯示的列表只能顯示三行。如下圖所示:



    我們現在要用Reflector工具將我們要破解的程式反編譯一下看一下哪裡沒有跳轉到MessagBox彈出對話方塊了!反編譯成C#程式碼後我們可以看到這個程式就一個主介面,看到了Form名字就說明這個是一個Windows的窗體:


    點開之後,就發現ProgressChanged方法裡面有內容,裡面包含了彈出訊息框的全部程式碼,好的我們這裡就確定了是這個方法讓這個訊息框彈出來的!的確他就是罪魁禍首,先記錄備案。

    現在已經知道是哪個方法彈出訊息框來了,那麼我們就可以再後設資料表中進行查詢該方法所在的RVA,這裡我要講一個後設資料表中的表這個表就是MethodDef表,這個表很重要也很好玩,這個表裡不但指出了該方法的IL程式碼的位置,還限定了方法的屬性。下面來看一下表結構:


看到上面這個表不禁讓我開心,因為我能找到這個方法存放的位置,也就是我需要的是這個RVA的地址,那麼這個方法的RVA是多少呢?帶著疑問思考,我們會想到用到一個工具來幫助我們查詢這個方法到底在Method的第幾個,這裡不講直接開啟CFF也可以看到這個方法。我要曲折的找一下。開啟ILDASM,既然.NET裡面有後設資料這個一號人物,我們就來小窺一下後設資料表,該方法的後設資料肯定在裡面。

    果然不出我們所料,確實在後設資料裡面有描述,因為後設資料是描述資料的資料,那麼我們就拿到了這個Token標示:0600001F,可以翻回到上一篇文章找一下這個對應的表是MethodDef正還是我們想要的,在這個表下的第31的位置就是我們要找的內容,懷著疑問開啟CFF軟體,來證實一下我們找的沒有錯!!!

    經過證實是我要找的ProgressChanged方法在後設資料表中的描述,現在就可以取出關鍵資訊ProgressChanged方法的RVA:0x3184

    通過CFF檢視一下區塊的內容:


可以正確的觀察到該方法的RVA存放在.text區塊中,因為該區塊的範圍是:2000~14A00,而3184正好落在了這段地址當中,好,接下來就可以算出該程式碼在實體地址了:3184-2000+200=1384,好的,0x1384就是我們要在檔案中查詢的的實體地址。這時候開啟16進位制編輯器,將程式載入到16進位制編輯器中。CTRL+G搜尋0x1384這個地址,下面是我們搜到的地址:

你們會疑問我怎麼知道這麼一段就是這個方法的程式碼呢?讓我來揭曉這個謎底。OKRVA我們算的肯定沒錯,也就是開始位置1384這個肯定是沒錯的,但是程式碼的長度不是很確定對吧?好,開啟ILDASM找到這個方法就知道這個方法的長度,或者是在這個方法的頭部我們就可以確定這個方法的長度。


驗證結果的時候到了通過ILDASM來驗證下:


      通過上述結論我們可以證實確實是存放的IL的程式碼,我們可以看到上面有一個開始指令,是我標記的這個開始指令的IL程式碼是ldarg.2載入方法引數2到堆疊上。這裡不看他的個什麼東東!我們只要知道他的Opcode是多少就好了這個指令的Opcode04,那麼我們就在上面的16進位制編輯器中進行搜尋:



       意思就是04這個指令的前面都是在做初始化堆疊和初始化引數的操作,而從04開始才是真正執行程式碼。好的開始的指令已經找好了,我們就要看一下我們要修改那段程式碼了,先觀察這段比較num--==0這裡,注意這裡修改程式碼的時候不能破壞程式碼的長度和程式碼的堆疊平衡原理。我們想如何能讓這個條件永遠不成立,OK,我想到了一個方法就是不讓這個引數進行減法操作,讓他一直進行加法操作!首先先小窺一下的他的IL程式碼我們開講一下整體IL的實現,這裡只講num--==0處的程式碼:



程式碼詳細講解如下:

IL_002f:  ldloc.3           //載入3到堆疊上。

IL_0030:  dup               //複製棧頂資料

IL_0031:  ldc.i4.1          //載入1到堆疊上

IL_0032:  sub               //3-1的操作。

IL_0033:  stloc.3           //儲存到區域性變數3中這是由原來的3變成了2

IL_0034:  ldc.i4.0          //載入變數0到堆疊

     IL_0035:  ceq               //於O比較後的結果放在堆疊上(返回01    IL_0037:  ldc.i4.0           //因為我們比較後的結果為01所以在壓入一個0後面進行比較falseceq從堆疊彈出兩個引數)

IL_0038:  ceq

IL_003a:  brfalse    IL_0113//條件成立跳到訊息框

 OK分析到這裡,這段指令的sub指令是我們的關鍵,我們要將這個指令改為Add就可以實現了,對應的SubOpcode59,而對應AddOpcode58這樣我們把59變成58再把16進位制另存一份就可以實現所有功能了。


    改好後我們來看一下效果如何吧!!!



三、結束語

這東西雖然看著沒有Reflexil來得快但是能讓你更深入的瞭解.NET的PE結構,小弟再次宣告本文章只是為了研究技術,沒有用做商業用途,為了支援正版我已經將標題遮擋住了,通過上述的文章,我有點小小的想法,就是我們可以講我們需要加密的方法體抽出來,當jit呼叫時再進行還原這樣就會對程式的安全性有一個提升。這裡只是我自己的個人看法,還請各位大牛指點小弟,小弟在此謝過了。

龐順龍最後編輯於:4年前

內容均為作者獨立觀點,不代表八零IT人立場,如涉及侵權,請及時告知。

相關文章