日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁編程開發(fā)其它知識 → 使用monodis工具分析pe文件結構與msil反匯編

      使用monodis工具分析pe文件結構與msil反匯編

      相關軟件相關文章發(fā)表評論 來源:西西整理時間:2011/4/24 7:47:55字體大。A-A+

      作者:西西點擊:172次評論:0次標簽: PE

      • 類型:音頻處理大小:1M語言:中文 評分:5.1
      • 標簽:
      立即下載

      monodis是mono發(fā)行包里的一個工具,作用類似與ms的ildasm,可以把dotnet pe文件反編譯為msil文件(另外有個托管代碼的實現(xiàn)Mono.Cecil)。這個工具的實現(xiàn)很簡單,就是根據(jù)PE文件的格式與規(guī)范去解析。選擇這個主題的原因有很多,首先PE文件作為進行分析mono的基礎,畢竟這里是metadata的來源;另外通過分析msil語言,可以為后續(xù)的VM執(zhí)行引擎做準備,畢竟無論是jit還是aot,都是從msil到x86代碼的轉(zhuǎn)換,msil是第一步;當然了解這個還可以為很多其他項目的分析做準備,比如最近我脫離reflector很喜歡的一個工具ilspy,是把msil做ast分析轉(zhuǎn)換為C#。好了,簡介到此為止,下面來具體分析下這個工具的源碼實現(xiàn)。

      一.文件結構及依賴
      monodis在mono/dis目錄下,通過查看makefile可見mono依賴于libmono-$(API_VER).la,這部分功能主要和mono共用metadata解析部分的代碼,除了這些monodis自身的文件包括:

      1.main.c:這個主要是提供參數(shù)解析及程序的入口,有參數(shù)可見monodis可以提供PE文件各部分信息的單獨輸出。

      2.dump.c:這個是main.c里輸出各種table直接調(diào)用的方法,比如assembly,typeref,class,method,filed,event等等我們非常關心的一些東西。

      3.get.c:主要提供一些stringfy的方法,即把MonoImage,MonoMethodSignature,MonoGenericContainer等Mono metadata相關的數(shù)據(jù)結構表示為disassemble后的字符串。

      4.dis-cil.c:這個可能是我們最關心的方法了,因為它的作用就是把MonoMethodHeader輸出為msil代碼。

      5.util.c:這個文件提供了四個工具方法:map和flags是查表方法,根據(jù)傳入的32位值得到相應的字符串標記,還有hex_dump和datadump,這兩個是把data直接輸出的。

       二.反編譯的過程

      1.加載file,解釋為assembly:

      這一塊功能主要是由libmono實現(xiàn)的,具體代碼在image.c/do_mono_image_load函數(shù)中, 這一塊是和mono共用的,我們這里所關心的就是load_metadata所調(diào)用的load_tables方法,因為MonoImage->tables是后續(xù)所有解析的來源,具體這一塊的實現(xiàn)這里不詳細的講,因為這個不是本文的重點。

      2.由上一步的工作得到了monodis反編譯過程中需要的MonoImage結構體數(shù)據(jù),下面就進行了如下一系列的工作:

      dump_header_data (img);
      dis_directive_assemblyref (img);
      dis_directive_assembly (img);
      dis_directive_file (img);
      dis_directive_mresource (img);
      dis_directive_module (img);
      dis_directive_moduleref (img);
      dis_exported_types (img);
      dis_nt_header (img);
      dis_mresource (img);
      dis_types (img, 0);
      dis_data (img);

       由函數(shù)名即可得知,這是處理各個table呢。由于其中大部分工作都類似,所有這里只選擇分析其中最具代表性的dis_directive_assemblyref方法和最重要的distypes這個方法。 

      2.1:下面來著重講一下這個通用的工作流程,也就是以上方法通用的解析步驟,以dis_directive_assemblyref為例:

      static void
      dis_directive_assemblyref (MonoImage *m)
      {
          MonoTableInfo *t = &m->tables [MONO_TABLE_ASSEMBLYREF];
          guint32 cols [MONO_ASSEMBLYREF_SIZE];
          int i;
          
          if (t->base == NULL)
              return;

          for (i = 0; i < t->rows; i++){
              char *esc, *flags;

              mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);

              esc = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME]));
              flags = assembly_flags (cols [MONO_ASSEMBLYREF_FLAGS]);
              
              fprintf (output,
                   ".assembly extern %s%s\n"
                   "{\n"
                   "  .ver %d:%d:%d:%d\n",
                   flags,
                   esc,
                   cols [MONO_ASSEMBLYREF_MAJOR_VERSION], cols [MONO_ASSEMBLYREF_MINOR_VERSION], 
                   cols [MONO_ASSEMBLYREF_BUILD_NUMBER], cols [MONO_ASSEMBLYREF_REV_NUMBER]
                  );
              dump_cattrs (m, MONO_TOKEN_ASSEMBLY_REF | (i + 1), "  ");
              if (cols [MONO_ASSEMBLYREF_CULTURE]){
                  fprintf (output, "  .locale %s\n", mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_CULTURE]));
              }
              if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]){
                  const char* b = mono_metadata_blob_heap (m, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
                  int len = mono_metadata_decode_blob_size (b, &b);
                  char *dump = data_dump (b, len, "\t\t");
                  fprintf (output, "  .publickeytoken =%s", dump);
                  g_free (dump);
              }
              fprintf (output, "}\n");
              g_free (flags);
              g_free (esc);
          }

      首先從m->tables取得相應的table得到MonoTableInfo,具體這個數(shù)據(jù)是從哪里來的,是第一步所做的工作,得到tableinfo之后,會對其進行遍歷,然后用mono_metadata_decode_row解析到定義過的col變量里。這個col的大小及每個字段的定義都在row-indexes.h定義的各種枚舉里面,至于為什么以及每個字段的含義,請直接參考PE文件格式,另外有本書寫的也非常好《加密與解密》。取得col數(shù)據(jù)之后,就是把這些數(shù)據(jù)根據(jù)msil的文件格式要求輸出,如上例以及我測試用的一個PE文件輸出為:

      .assembly extern mscorlib
      {
        .ver 2:0:0:0
        .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..

       其他的一些table輸出方式與上面一樣,只是格式不同而已。

      2.2:現(xiàn)在來分析其中最重要的也是我們最關心的distype方法。這里其實有幾個重要的部分,依次進行分析:

      (1).輸出type的基本信息,包括name,namespace以及type相關的attribute,這部分邏輯是通用的,和dis_directive_assemblyref一樣的方式。

      (2).輸出field,method,property,event等type的成員。分別對應dis_field_list,dis_method_list,dis_property_list,dis_event_list方法。這里只分析其中典型的dis_method_list方法其中的dis_code方法。

      首先由mono_image_rva_map獲取一個方法的偏移量指針,然后再由mono_metadata_parse_mh_full得到這個方法的MonoMethodHeader。以下是其定義:

      struct _MonoMethodHeader {
          const unsigned char  *code;
      #ifdef MONO_SMALL_CONFIG
          guint16      code_size;
      #else
          guint32      code_size;
      #endif
          guint16      max_stack   : 15;
          unsigned int is_transient: 1; /* mono_metadata_free_mh () will actually free this header */
          unsigned int num_clauses : 15;
          /* if num_locals != 0, then the following apply: */
          unsigned int init_locals : 1;
          guint16      num_locals;
          MonoExceptionClause *clauses;
          MonoType    *locals [MONO_ZERO_LEN_ARRAY];
      };

      如果看著這個結構體特別親切,那就對了。這個就是msil中的method的一個抽象,比如locals,exception clause,code等。

      其實對_MonoMethodHeader的輸出,就是對這個結構的一個stringfy。當然由code到msil還需要一個過程,那就是disassemble_cil方法所做的工作了。這個過程就是把code根據(jù)其對應的opcode進行翻譯,解釋為我們平常熟悉的msil了。這個翻譯的過程很簡單,具體代碼在dis-cil.c中的disassemble_cil方法,其中需要注意的一點就是會根據(jù)每個opcode的argument不同而翻譯為不同的表示。


      好了,這就是monodis的一些關鍵部分,當然還有很多沒有解釋也沒有必要去解釋,因為都是類似的操作,把這個過程搞清楚則對metadata,image,msil等一些基礎性的概念有更深的了解,也是進一步分析mono的基礎。

        相關評論

        閱讀本文后您有什么感想? 已有人給出評價!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評論

        最新評論

        發(fā)表評論 查看所有評論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)