程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 寫給自己的 程序集&msil 掃盲

寫給自己的 程序集&msil 掃盲

編輯:C#入門知識

嘴上不說 心裡卻想MD 這家伙在博客園裝了這麼久的高手 竟然連這都不會 ,我去噢。

.net 下 “程序集” 什麼東東 ,反正就是聽著挺牛x的,其實就是指“一堆程序”從我們傳統的C++封裝的dll 認知 就是一個dll文件名 然後一個lib文件裡面有對應的函數列表,把lib文件添加進去就OK了。

吶 現在我們來新建一個空白Asp.net網站
打開web.config 裡面就有一些默認引用的程序集

 
                     
     
 

看見那些唧唧歪歪的屬性沒有 System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089 這都是些啥 ,這就是程序集信息 .net下對程序集的定義已經超出我們原來對dll文件認知的那種范疇了,程序集信息指代“一堆可用程序功能”經過簽名的唯一電子標簽信息。

系統目錄的程序集稱之為GAC ,global assembly cache,就是我們平常用的console.write()啊 messageBox.show()啊啥的 。他放在C:\WINDOWS\assembly 進入那個目錄下後發現資源管理器的視圖變得很特殊。發現只可查看屬性 而不能拷走裡面的文件。要拷走也可以 在dos命令行下就可以了 他是以命名空間為目錄樹存放的。

我們自己的程序集也可放到GAC裡 需要這樣做:
放到GAC下的程序集必須使用一個私鑰進行簽名(附加強名稱)方式如下:

普通程序集在不破壞pe文件結構的情況修改後是可以運行的。而經過強名稱簽名的則不可以,有效的保證了程序完整性.。
注意在.net3.5或以上版本不論在編譯時選什麼版本加了強名稱都還是可以更改的。因為.net認為你的程序運行在一個"受信任的環境" 所以強名稱驗證是被pass的。但是加到GAC應該是加不進去的 加到GAC必定會進行強名稱驗證。要想進行強名稱驗證不被pass在app.config 裡添加這樣的配置:

 
    
       
    
 

附:
使用gacutil /i function.dll卸載
也可在C:\WINDOWS\assembly目錄 選中程序集點右鍵 卸載。
csc命令的各種使用方式:
生成dll的簽名文件:
D:\>sn -k keyfor_function.snk
附加簽名編譯為dll:
D:\>csc /keyfile:keyfor_function.snk /t:library function.cs
附加dll編譯主調程序源碼:
D:\>csc /reference:function.dll kit.cs

 

.net運行時東西大部分的人是不會去刻意學他的,啥CLR 啊 JIT  啊 我也不懂 不能裝高手 更不能拿出來吹。 入門的還是得給自己普及下。.net的exe是中間語言代碼 這不得不說ilasm 跟ildasm,一個是編譯 一個是反編譯。先來演示一下怎樣簡單“破解”一個小程序。順便我們也來玩玩ildsam

新建一個控制台程序
寫幾句代碼:

                    Main(              
              (licence() ==                   Console.WriteLine(                                
                  Console.WriteLine(                                                                  
                 }

在項目屬性上->右鍵->屬性
添加程序簽名:

項目上->右鍵->添加->新建項->應用程序配置文件
項目下多了app.config
編輯它

 
 
   
     
   
 

現在編譯並運行

運行輸出 invalid licence

很明顯驗證不通過

吶現在我們就來對他進行破解 讓他驗證通過

然後打開il dasm 工具
如果不知道在哪裡打開 就在vs命令行裡輸入ildasm
然後打開我們在debug目錄編譯後的exe文件

代表test命名空間
代表program類
咦這啥東東 咱在代碼裡沒寫這個方法啊

咱在書上學過如果沒有寫構造方法 則編譯時提供默認的構造方法
看 這裡就是這個意思 ctor可能全稱是 constructor

打開main函數 代碼如下:

      // 代碼大小          .maxstack  
   .locals init ([     
            bool .     stloc.
     ldloc.
        
     ldstr      
            void [mscorlib]System.     
            valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.     
        
     ldstr      
            void [mscorlib]System.     
            valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.     
     
     
 } // end of method :Main

打開licence函數 代碼如下:

     // 代碼大小          .maxstack  
   .locals init ([     
     ldc.i4.
     stloc.
        ldloc.
     
 } // end of method :licence

然後單擊文件菜單->轉儲
保存為il 文件
我們只需要在main函數中更改條件判斷 讓他驗證通過就可以了
用記事本打開保存的il文件
找到這一行 看到沒有
IL_0008:  brtrue.s   IL_001e

如果改成這樣呢
IL_0008:  brfalse.s   IL_001e
試下吧

改完後在vs命令行使用ilasm test.il 把il文件重新編譯成exe文件

這時我們再次運行test.exe
咦怎麼回事 不成功

 未處理的異常:  System.IO.FileLoadException: 未能加載文件或程序集“test, Version=
 ., Culture=neutral, PublicKeyToken= 強名稱驗證失敗。 (異常來自 HRESULT: 文件名:“test, Version=., Culture=neutral, PublicKeyToken= ” --->   MyComputer

因為有程序簽名,所以我們還得把強名稱去掉。
再次打開il文件
看到有這樣3處開始的地方:
.publickeytoken
.publickey
.hash

把他們刪除
然後再用ilasm編譯 並運行發現驗證成功

注意:
如果程序集加了強名稱 改了pe文件的任何內容後都是無法啟動的 就像有綁定的MD5校驗一樣。為了保護程序 都會使用混淆器進行處理 ,而混淆器正好又會更改文件內容。

另外:
說俗點高級語言也無非就
int var1=123
if(){
}
else{}

for(){}
這些之類的
看了下網上il的代碼解析 以及以前看過一些對匯編的理解 雖然不用匯編做開發。
匯編是基於堆棧的 流水線 似的操作 ,事先初始化的變量在編譯時都是確定好的 入棧出棧操作 ,每次都進行一個指令 對寄存器賦值 或者進行運算 地址跳轉 等。

仔細想想有了這些基礎特征就夠了 高級語言的那些語法基本上都可以實現只不過要麻煩些

int var1=123
這個不說了

if(){
}
else{}
在匯編裡估計是通過條件 地址跳轉啥的來實現

for(){}
其實也很簡單
看了一點il的代碼 發現也就是一個連續if的過程 條件達不到跳轉到前面的地址繼續n++
像這樣
int n=1;
loop:
n++;
console.writeline("hi");
if(n<50)
goto loop;

其實我不懂匯編語言的 有些亂說的見諒 勿噴。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved