某殼對.Net程式加密的原理及解密探討二

來源:互聯網
上載者:User

自上次寫第一篇文章到現在不知不覺兩個月過去了,這篇文章我們將介紹怎麼擷取解密後的IL位元組代碼。
我們先回顧一下前文,在上一回我們提到“InFaceMaxtoCode.Startup 正常啟動後,在整個程式集中只會運行一次。”。
當時這種說法是很武斷的,如果 “InFaceMaxtoCode.C______(num2, num3)” 的傳回值總是 false的話,該函數就會被執行多次,
不過根據後來動態調試的結果,我們證實了“InFaceMaxtoCode.C______(num2, num3)” 的傳回值為 true,因此上次的說法是正確的。

現在言歸正傳,怎麼取得解密後的代碼呢?大概兩個方向,
1.正面交鋒,直接攻破maxtocode的運行庫。
這就將問題直接回到了傳統的win32層面,不過這個東西是業內人士寫的在這方面的保護工作做得很好,像我這樣的菜鳥就很難直接攻破了。
我曾有一個設想,就是通過分析運行庫找到解密函數的入口,然後弄一個stub dll,hook這個地方,把解密後的il代碼dump出來。
實際跟蹤幾次後我就放棄了。從跟蹤到的資訊來看,我猜測,運行庫是通過 mscorwks.dll 掛接到 jit,在jit的前面即時解密代碼。
理論上我們也可以掛一個到jit前面,在那裡dump解密的il代碼,不過這個實現的方式,還不清楚,如果弄明白了,也就能寫一個同樣原理的加密軟體了。
這個難度比較大,所以我最終放棄了這個方案。

2.避開運行庫,我們直接利用dotNet 2.0的特性擷取IL代碼。
如是我就試著用2.0寫了一個winform程式,加密,運行,發現報錯。
maxtocode3.1不支援2.0的winform程式,這就使我的這個方案實驗夭折了。
兩個月過去了,發現maxtocode升級到3.11了修正了這個bug,今天終於可以繼續實驗了。

我們來建一個簡單的winform程式。一個表單,然後一個按鈕。
代碼如下:


 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Text;
 7 using System.Windows.Forms;
 8 using System.Reflection;
 9 using Spaces;
10 namespace Test5
11 {
12     public partial class Form1 : Form
13     {
14         public Form1()
15         {
16             InitializeComponent();
17         }
18    
19         private void TestMethod()
20         {
21             //  [7/17/2006]
22             int i = 0;
23             i = 1;
24             i++;
25             if(i>0)
26             {
27                 MessageBox.Show("OK");
28             }
29         }
30 
31         private void button1_Click(object sender, EventArgs e)
32         {
33             Type tp = this.GetType();
34 
35             MethodInfo mi = tp.GetMethod("TestMethod",
36                 BindingFlags.NonPublic|BindingFlags.DeclaredOnly|
37                 BindingFlags.Public|BindingFlags.Static
38                 |BindingFlags.Instance);
39             if(mi == null)
40             {
41                 MessageBox.Show("err");
42                 return;
43             }
44             MethodBody mb = mi.GetMethodBody();
45             byte[] bt= mb.GetILAsByteArray();
46             StringBuilder sb = new StringBuilder();
47             for (int i = 0; i < bt.Length; i++)
48             {
49                 sb.Append(bt[i].ToString("X2"));
50                 sb.Append(" ");
51             }
52             string stxt = sb.ToString();
53             MessageBox.Show(stxt);
54                        
55         } 
56      
57     }
58 }

編譯運行,我們點擊按鈕就能看到 TestMethod 的IL位元組碼。
然後用maxtocode加密在運行,同樣能看到 TestMethod 的IL位元組碼。
兩次看到的結果一樣的,這個是當然了,如果不一樣,maxtocode就破壞了程式的正確性了。

好了,我們的實驗成功了。

看到這裡大家應該知道怎麼擷取解密後的IL代碼了吧。

這種方式比在記憶體裡面找代碼或者hook到maxtocode解密後dump代碼的方式要優越很多,
因為記憶體dump的方式你還要擔心運行時的函數覆蓋率,沒有運行到的就dump不到。

這種方式我們利用 DotNet的反射機制,可以枚舉出程式集中的所有類型,以及每個類型的所有方法,成員,欄位,建構函式等。

初步實驗了一下,對於加了密的dll檔案還是比較好弄的,2.0的、1.1的都能弄出IL代碼來。
對於exe檔案還有一關需要解決,那就是如何將我們的DotNet dll程式集插入到exe的Runspace中去。

今回就先到這裡了,下回再實際寫程式演練擷取解密後的IL位元組代碼。

ps:不知道大家手上是否有破解到的 Reflector 的原始碼,如果有丟一份給我,感激不盡。

相關文章

聯繫我們

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

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

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.