自上次寫第一篇文章到現在不知不覺兩個月過去了,這篇文章我們將介紹怎麼擷取解密後的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 的原始碼,如果有丟一份給我,感激不盡。