標籤:round 啟示 進位 局部變數 原始碼 oat height sof 取出
一、開篇
首先寫在前面,這篇文章源於個人的研究和探索,由於.NET有自己的反射機制。可以清楚的將原始碼反射出來。這樣你的軟體就非常easy被破解。當然這篇文章不會說怎麼樣保護你的軟體不被破解。相反是借用一個軟體來講述是怎麼被攻破的。也會有人說這是一篇破文,我事實上這篇文章已經寫了非常長時間了。不知道以什麼形式發出來,由於畢竟是有些破解類的東西。可是我認為從這篇文章相反的是可以帶來一些啟示。大家應該都知道Reflector這個反編譯軟體另一個外掛程式是專門用來改IL的外掛程式叫Reflexil。這裡我們也要用到前面那個工具Reflector。後面的外掛程式我們這裡我們不用,接下來分析的東西可以讓大家可以更深入.NET的PE,深入內幕來看看。好,閑話少說….直接上分析。
二、具體分析過程
假設不懂.NET的PE檔案結構的帥哥美女,能夠看一下上一篇文章http://www.cnblogs.com/dwlsxj/p/4052871.html,這裡要用到PE的知識。首先我們來看一下這個程式的限制。這個程式有顯示限制也就是顯示的列表僅僅能顯示三行。
例如以所看到的:
我們如今要用Reflector工具將我們要破解的程式反編譯一下看一下哪裡沒有跳轉到MessagBox彈出對話方塊了!反編譯成C#代碼後我們能夠看到這個程式就一個主介面,看到了Form名字就說明這個是一個Windows的視窗:
點開之後。就發現ProgressChanged方法裡面有內容,裡麵包括了彈出訊息框的所有代碼。好的我們這裡就確定了是這種方法讓這個訊息框彈出來的!
的確他就是罪魁禍首。先記錄備案。
如今已經知道是哪個方法彈出訊息框來了,那麼我們就能夠再中繼資料表中進行尋找該方法所在的RVA。這裡我要講一個中繼資料表中的表這個表就是MethodDef表,這個表非常重要也非常好玩,這個表裡不但指出了該方法的IL代碼的位置,還限定了方法的屬性。以下來看一下表結構:
位移 |
大小 |
名稱 |
說明 |
0 |
4 |
RVA |
該方法體的RVA(方法體包含:方法頭、IL代碼、異常處理定義) |
4 |
2 |
ImplFlags |
限定了方法的運行方法(如abstract、P/Invoke) |
6 |
2 |
Flags |
先頂了方法的調用屬性和其它的一些性質 |
8 |
2(4) |
Name |
指向#String的位移,表示該方法的名稱 |
|
2(4) |
Signature |
指向#Blob的位移,Signature定義了方法的調用方式(如傳回值類型等) |
|
2 |
ParamList |
指向Param表的索引,指出了方法的參數 |
看到上面這個表不禁讓我開心,由於我能找到這種方法存放的位置,也就是我須要的是這個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這個地址。以下是我們搜到的地址:
你們會疑問我怎麼知道這麼一段就是這種方法的代碼呢?讓我來揭曉這個謎底。
OK。RVA我們算的肯定沒錯,也就是開始位置1384這個肯定是沒錯的,可是代碼的長度不是非常確定對吧?好,開啟ILDASM找到這種方法就知道這種方法的長度。或者是在這種方法的頭部我們就能夠確定這種方法的長度。
驗證結果的時候到了通過ILDASM來驗證下:
通過上述結論我們能夠證實確實是存放的IL的代碼,我們能夠看到上面有一個開始指令,是我標記的這個開始指令的IL代碼是ldarg.2載入方法參數2到堆棧上。這裡不看他的個什麼東東!我們僅僅要知道他的Opcode是多少就好了這個指令的Opcode是04,那麼我們就在上面的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比較後的結果放在堆棧上(返回0或1) IL_0037: ldc.i4.0 //由於我們比較後的結果為0或1所以在壓入一個0後面進行比較false(ceq從堆棧彈出兩個參數)
IL_0038: ceq
IL_003a: brfalse IL_0113//條件成立跳到訊息框
OK分析到這裡,這段指令的sub指令是我們的關鍵,我們要將這個指令改為Add就能夠實現了,相應的Sub的Opcode是59,而相應AddOpcode是58這樣我們把59變成58再把16進位另存一份就能夠實現全部功能了。
改好後我們來看一下效果怎樣吧!!!
Xamarin.Android之下拉重新整理