反射、反射加殼、反射脫殼、反射註冊機

來源:互聯網
上載者:User
 程式集包含模組,而模組包含類型,類型又包含成員。反射則提供了封裝程式集、模組和類型的對象。您可以使用反射動態地建立類型的執行個體,將類型綁定到現有對象,或從現有對象中擷取類型。然後,可以調用類型的方法或訪問其欄位和屬性。
      反射的用途很大,在上節文章中的“晚期綁定”就是利用了反射的性質,在外掛程式的編寫上更是需要反射。我們常用的反編譯工具Refiector 也是用了反射的性質。
     我們今天就來寫一個簡單的類似於Refiector的東西,通過反射來獲得程式集的多種資訊。
1、獲得程式集所有的namespace


        public static ArrayList GetAllNameSpace(Assembly assembly)
        {
           ArrayList namePaceArry = new ArrayList();
           foreach(Type type in assembly.GetTypes())
           {
              if (!namePaceArry.Contains(type.Namespace) && type.Namespace != null)
              {
                   namePaceArry.Add(type.Namespace);
              }
           }
           return namePaceArry;
        }


2、獲得程式集的所有類
 

       public static ArrayList GetClassNames(Assembly assembly, string nameSpace)
        {
            Type[] types = assembly.GetTypes();
            ArrayList classArray = new ArrayList();
            foreach (Type type in types)
            {
                if (type.FullName == nameSpace + "." + type.Name && type.BaseType.Name != "Enum")
                {
                    classArray.Add(type.Name);
                }
            }
            return classArray;
        }


3、獲得程式集的某一類中的所有方法


        public static MethodInfo [] GetMethod(Assembly assembly, string fullName)
        {
            Type type = assembly.GetType(fullName);
            return type.GetMethods();
        }


這裡的fullName是包含namespace和類名合在一起的。

4、獲得程式集中的某一類中的所有屬性

        public static PropertyInfo[] GetPropertys(Assembly assembly, string fullName)
        {
            Type type = assembly.GetType(fullName);
            return type.GetProperties();
        }


5、獲得程式集的枚舉類型

        public static ArrayList GetEnums(Assembly assembly, string nameSpace)
        {
            Type[] types = assembly.GetTypes();
            ArrayList classArray = new ArrayList();
            foreach (Type type in types)
            {
                if (type.FullName == nameSpace + "." + type.Name && type.BaseType.Name == "Enum")
                {
                    classArray.Add(type.Name);
                }
            }
            return classArray;
        }



6、獲得程式集中枚舉的內容,以及每項的值

        public static FieldInfo [] GetSubEnums(Assembly assembly, string fullName)
        {
            return assembly.GetType(fullName).GetFields();
        }

        public static string GetSubEnumsData(Assembly assembly, string fullName,string name)
        {
            FieldInfo info = assembly.GetType(fullName).GetField(name);
            return info.GetRawConstantValue().ToString();
        }


7、獲得程式集中某一類的所有屬性

        public static PropertyInfo[] GetPropertys(Assembly assembly, string fullName)
        {
            Type type = assembly.GetType(fullName);
            return type.GetProperties();
        }


8、獲得程式集中某一具體方法的IL代碼

        public static string GetMethodData(Assembly assembly, string fullName,string name, Type [] types)
        

{
            Type type = assembly.GetType(fullName);
            MethodInfo info = type.GetMethod(name, types);
            string data = String.Empty;
            if (info.GetMethodBody() != null)
            {
                byte[] il = info.GetMethodBody().GetILAsByteArray();
                if (il != null)
                {
                    int inslength;
                    for (int currentpos = 0;currentpos < il.Length;currentpos += inslength)
                    {
                        inslength = 0;
                        data += String.Format("{0:X8}: {1}", currentpos,Disassembler.Decode(il, currentpos, out inslength)) + "\r\n";
                    }
                }
                return data;
            }
            return "此函數不做反編譯處理";
        }



1、反射加殼
       我曾經在06年的《駭客防線》上發表過一篇名為《C# 實現從自身資源提取EXE檔案》的文章,主要講的就是如何將EXE檔案以資源的形式儲存在PE檔案中,然後自我釋放出來(模仿木馬的自我釋放功能),當時就用了反射技術。時隔2年,當年的熬夜奮鬥的情景我還依稀記得,通過該文章得指引,釋放出來後將會得到一個獨立的EXE檔案。而在反射殼中僅僅將託管程式釋放到記憶體中,並找到其進入點,然後執行入口函數(不釋放真實檔案),這便是DONET反射殼的原理了。怎麼樣。貌似很簡單吧。
       我們今天就拿一個CrackMe來加一層簡單的反射殼。
       首先建立一個CMD項目,將CrackME拷貝到這個專案檔中,並在解決方案中設定成為這個項目的“嵌入式資源”。
       然後我們在代碼中將這個資源轉換為的位元組數組:

Stream sr = Assembly.GetExecutingAssembly().GetManifestResourceStream("CiCiPackDemo.CrackMe1.exe");
byte[] fileBytes = new byte[sr.Length];
sr.Read(fileBytes, 0, (int)sr.Length -1);
Assembly assembly = Assembly.Load(fileBytes);
MethodInfo mi = assembly.EntryPoint;
mi.Invoke(null, null);

註:這裡的“CiCiPackDemo”為該項目的命名空間,而“CrackMe1.exe”為嵌入式資源名。
然後我們再找到CrackME1.exe的函數進入點並運行就可以了。

       最後我們再把這個項目的編譯類型強制設定為Windows程式,編譯一次,這個最簡單的反射殼就完成了。我們可以看到其流程是:讀取自身資源->轉換資源為Assembly->找到進入點->執行入口函數。
我們用Reflector分別開啟加殼和未加殼的程式查看:
未加殼程式如下:


已經加殼程式如下:

      經過對比我們發現,加殼後的程式把CrackMe1.exe作為資源檔儲存了,而我們的Refletor也不能查看其代碼了。起到了簡單的加密保護作用。
這就是反射加殼,很簡單吧^_^!

2、反射脫殼
       能加殼就能脫殼,這當然是天經地義的事情。在Win32時代OllyDbg似乎成了該平台下的寵兒,然而對於反射類的DONET平台殼,這款軟體一載入就會將程式跑飛。有一身本領卻施展不出來……..。
       那麼如何對付DONET平台下的反射殼呢。再回顧一下加殼原理,我們仔細看看這句代碼:Assembly assembly = Assembly.Load(fileBytes); 這說明不管怎樣系統都會將加殼的程式在記憶體中還原成一個Assembly的對象。那麼我們只要獲得了這個對象,也就可以獲得這個程式相關的資訊,結合上一篇文章我們甚至可以獲得IL代碼。那麼如何獲得這個對象呢。在程式域中有這樣的方法   AppDomain.CurrentDomain.GetAssemblies(),可惜只有在本程式集中才能這樣調用,一番思考後,我們發現可以將Managed 程式碼注射進入程式中,再利用該方法就可以獲得其對象了。
       通過上一片文章中我寫的這個工具:“通用Managed 程式碼注射器”。就可以將託管程式注入到任意進程中。根據上篇文章注入cicireflection到上面的加殼的CiCiPackDemo中可以得到Crackme1.exe的完整資訊。
       那麼我們如何把這個Crackme1.exe程式集完整的Dump下來呢。在介紹原理前先告訴大家一件失望的事情,這種反射脫殼在目前的DONET解密中並不實用了,更多的則是基於JIT層的脫殼,而不是基於軟體本身,但是作為一種脫殼思路還是有必要和大家分享的。
       其一:分享一下RICK大牛的方法,這是我拜讀了RICK大牛的一些文章後自己理解的。(因為牛人寫的文章經常只有代碼並且點到為止,我等菜鳥可是要消化很久的)。用第三方的Dump軟體把這個程式集先DUMP下來,然後根據Assembly對象獲得一些資料來修複Dump後的檔案,就相當於Win32程式脫殼後需要修複輸入輸出表的道理是一樣的。而DONET反射脫殼則是來修複“方法體、標頭檔、中繼資料”之類的。為了不誤導大家或者故意標榜自己的嫌疑,我還是請大家來看看Rick大牛的代碼:http://bbs.pediy.com/showthread.php?t=47330
      其二:說完了RICK大牛的原理,再看看我直接注入進去反射獲得資料的辦法。當然我們要用到我的通用Managed 程式碼注射器,自己寫一個外掛程式代碼如下:

if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                    bool isUnpack = false;
                    foreach (Assembly assembly in assemblies)
                    {
                        if (Path.GetFileName(assembly.Location).ToLower() == "cicipackdemo.exe")
                        {
                            using (Stream sr =assembly.GetManifestResourceStream("CiCiPackDemo.CrackMe1.exe"))
                            {
                 &nb

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.