上篇文章介紹了 Visual Studio 的兩項祕密武器 - Source Link 及 Decompile Source Code 功能,能幫助我們針對開源 NuGet 程式庫,甚至對沒有源碼的第三方程式庫逐行偵錯。今天再補充一件無源碼偵錯的神兵利器 - dnSpy

在 Visual Studio 2019 整合 Decompile 偵錯功能前,dnSpy 也是無源碼偵錯領域的一方霸主,現在雖然被 Visual Studio 搶去一些光采,但 dnSpy 有些特異功能仍值得一看。

dnSpy 的執行程式可從 Github 下載,有幾個選項:依賴 .NET 4.7.2 的版本、自帶 .NET Core 執行所需組件的版本(再區分 32/64),還有 Unity 專用版本。我選擇使用 .NET 4.7.2 版:

免安裝,解壓縮即可執行,平常主要是用 dnSpy.exe、dnSpy-x86.exe,視要偵錯的對象是 64bit 還是 32bit 而定(注意:Visual Studio 新增 .NET Console Application 專案,預設目標平台雖為 AnyCPU,但因啟用 Prefer 32bit,其實是跑 32 位元模式),dnSpy.console.exe 則可能來反組譯產生 .cs 檔:

dnSpy 沒有寫成 Visual Studio 擴充套件形式,而是以獨立軟體方式執行,提供了跟 Visual Studio 非常相似的操作環境。

用一個模擬情境來展示 dnSpy 的黑魔法。

假設你的公司有一支流傳多年的神奇 .NET 程式,作者早已浪跡天涯不知去向,原始碼已不可考,手上只有一個 exe 跟兩個 dll 三個檔案,程式不知去哪裡抓來台北跟高雄的現在天氣跟氣溫並顯示:

老闆:你不是很行?研究一下怎麼修改程式,給我把台中市的天氣也加進去。

你:沒問題,老闆。這交給我,小事。(內心 OS:媽惹發可,不給原始碼叫工程師改程式,這什麼鬼公司?)

開啟 dnSpy,將 ShowWeatherStatus.exe 拖到左側 Assembly Explorer,展開找到 Program.Main(),dnSpy 會自動帶入引用到的組件,包含 Foo.dll:

設好中斷點,按下 Start,確認 exe 位置、啟動參數、工作目錄等,即可按 OK 開始偵錯。

程式開始執行,並在中斷點停下來,按 F10 Step Over,F11 Step Into,操作跟 Visual Studio 幾乎一模一樣,也一樣有 Locals、Exception Settings、Call Stack、Watch 等視窗,Visual Studio 老手不需學習即可立刻上手:

dnSpy 的 UI 操作設計不如 Visual Studio 豪華,例如沒法做到滑鼠停在程式碼上即時顯示變數內容、沒有 Immediate Windows 可供動態執行指令... 等。但 dnSpy 能完成一些 Visual Studio 做不到的事,有其不可取代性。

按 F11 深入 Foo.WeatherService.GetWeatherStatuses(),原來裡面是用 WebClient.DownloadString() 去下載中央氣象局網站的 JS 取出 JSON 解析抓出天氣狀況及高低溫(謎之聲:流傳多年的程式哪可能長這樣?穿幫了啦),地區則豬頭地寫死台北跟高雄而非抓設定檔,想擴充都沒得擴充:

地區清單寫死又沒原始碼,要怎麼改?很好,輪到 dnSpy 大展身手了。在 Assembly Explorer 對方法按右鍵選單,有兩個選擇:

Edit Method(C#) 可直接改 C# 程式碼重新編譯:

Edit Method Body 則可修改 IL Code 儲存。IL Code 可讀性不如 C#,但如果遇到反組譯出來的 C# 無法編譯時,直接改 IL Code 是最快的解決辦法。

修改完畢記得用 Save Module 儲存 DLL 或 EXE:

接下來到了見證奇蹟的時刻。重新執行程式,台中市出現惹!
(老闆:看吧,改個程式是能有多難?以後別跟我靠北程式沒原始碼不能改。 你: ... (捏碎滑鼠))

雖然借助反組譯工具,我們本來就能在沒有原始碼的情況下修改程式,但 dnSpy 讓整個修改過程簡單到不可思議,連阿媽都會操作。不過,這類技巧偏向應急救險,不是軟體開發的正統做法,原始碼一定要妥善管理交接,不要搞死開發人員呀。

dnSpy 還有許多其他功能,但光無源碼偵錯跟直接修改程式這兩項就值得讓人起立鼓掌了,不呼口號對不起這麼強大的工具:

dnSpy 好威呀!

Example of using dnSpy to trace and modify .NET progrrame without source code.


Comments

# by Dxball

推薦一個 Visual Studio extension: GoToDnSpy https://marketplace.visualstudio.com/items?itemName=VladimirChirikov.GoToDnSpy 可以直接從 vs 裡面快速用 dnSpy 打開 assembly 並跳至指定的 member

# by Jeffrey

to Dxball, 好物! 感謝分享。

Post a comment


54 - 13 =