如何在沒(méi)有第三方.NET庫(kù)源碼的情況,調(diào)試第三庫(kù)代碼?
大家好,我是沙漠盡頭的狼。
本方首發(fā)于Dotnet9,介紹使用dnSpy調(diào)試第三方.NET庫(kù)源碼,行文目錄:
安裝dnSpy
編寫(xiě)示例程序
調(diào)試示例程序
調(diào)試.NET庫(kù)原生方法
總結(jié)
1. 安裝dnSpy
dnSpy是一款功能強(qiáng)大的.NET程序反編譯工具,可以對(duì).NET程序進(jìn)行反編譯,代替庫(kù)文檔的功能,代碼丟失或者損壞可直接恢復(fù),所以能在完全沒(méi)有源碼的情況下即時(shí)調(diào)試程序,甚至還能修改程序!
Github有二進(jìn)制可執(zhí)行程序下載地址,也有源碼可以自行編譯,本文使用前者,Github地址是:https://github.com/dnSpy/dnSpy

2. 編寫(xiě)示例程序
示例為一個(gè)桌面程序,輸入數(shù)字,右側(cè)回顯輸入的數(shù)字是奇數(shù)還是偶數(shù):

示例代碼比較簡(jiǎn)單,界面綁定和ViewModel關(guān)系截圖看完所有:

奇偶判斷由類(lèi)TestTool
的TellMeOddEven
方法返回,再回看回顯,咦,0是奇數(shù)?1是偶數(shù)?
TestTool
類(lèi)是其他庫(kù)定義,我假裝你沒(méi)有源碼哈,雖然你有:

類(lèi)具體定義如下:
namespace TestDll;public class TestTool{public string TellMeOddEven(int number){if (number % 2 == 1){return $"{number}是偶數(shù)";}return $"{number}是奇數(shù)";}}
3. 調(diào)試示例程序
打開(kāi)dnSpy,將主程序引用的TestDll
拖入:

可以看到反編譯后的代碼:

反編譯出來(lái)的方法定義會(huì)和第三方源碼可能不同,以下是一些可能導(dǎo)致不同反編譯結(jié)果的因素:
編譯器優(yōu)化:不同版本的編譯器可能會(huì)對(duì)代碼進(jìn)行不同的優(yōu)化,例如使用不同的算法、數(shù)據(jù)結(jié)構(gòu)或者代碼重排等。這些優(yōu)化可能會(huì)導(dǎo)致反編譯出來(lái)的代碼結(jié)構(gòu)和順序不同,本文示例使用 .NET 8開(kāi)發(fā),.NET Framework編譯的庫(kù)可能反編譯出來(lái)與源碼幾乎一致。
反編譯工具更新:dnSpy本身也會(huì)不斷更新,以適應(yīng)新的.NET版本和編譯器特性。這些更新可能會(huì)改變反編譯算法和策略,從而導(dǎo)致不同版本的dnSpy反編譯結(jié)果不一致。
代碼簡(jiǎn)單,對(duì)比源碼和反編譯的代碼查看,對(duì)整型入?yún)⒊?取余,如果等于1判斷為偶數(shù),否則為奇數(shù),當(dāng)然這是錯(cuò)的,假如代碼邏輯復(fù)雜,可以用dnSpy調(diào)試。
運(yùn)行測(cè)試程序,并在dnSpy中給方法打斷點(diǎn),在調(diào)試菜單附加測(cè)試程序,就和VS中操作類(lèi)似:

4. 調(diào)試.NET庫(kù)方法
上面調(diào)試示例程序的方法可用于其他第三方.NET庫(kù),那么.NET自身庫(kù)方法呢?
方法類(lèi)似,找到.NET庫(kù)對(duì)應(yīng)類(lèi)、對(duì)應(yīng)方法,運(yùn)行目標(biāo)程序,然后打斷點(diǎn)。.NET庫(kù)方法這樣找:點(diǎn)擊【文件】》【從GAC打開(kāi)】=》搜索目標(biāo)庫(kù),雙擊庫(kù),再查找目標(biāo)方法,后面調(diào)試步驟就是一樣了:

5. 總結(jié)
技術(shù)交流加群請(qǐng)?zhí)砑诱鹃L(zhǎng)微信號(hào):dotnet9com
文中示例代碼:MultiVersionLibrary
dnSpy很強(qiáng)大的,還能直接監(jiān)視第三方代碼的變量、修改值等,就和你使用VS開(kāi)發(fā)自己的程序一樣,了解更多用法還請(qǐng)查看文章開(kāi)頭給的鏈接https://github.com/dnSpy/dnSpy, 這篇大佬的文章也不錯(cuò),建議看看:《神器如 dnSpy,無(wú)需源碼也能修改 .NET 程序》。
對(duì)了,示例程序中奇偶數(shù)判斷不對(duì),我又沒(méi)代碼我想糾正怎么辦?
解決這個(gè)問(wèn)題,上面大佬的文章您可以拜讀了,下一篇站長(zhǎng)繼續(xù)講解第三方庫(kù)攔截,能實(shí)現(xiàn)不修改第三方庫(kù)達(dá)到修改方法邏輯和返回結(jié)果的效果,可以提前預(yù)習(xí)快學(xué)會(huì)這個(gè)技能-.NET API攔截技法,當(dāng)然下一篇會(huì)有新知識(shí)點(diǎn):非公有類(lèi)非公有方法攔截技法。
以原倉(cāng)庫(kù)兩張dnSpy調(diào)試第三方庫(kù)的動(dòng)圖結(jié)束本文:

