嘴上不說 心裡卻想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;
其實我不懂匯編語言的 有些亂說的見諒 勿噴。