如何從dump文件中提取出C#源代碼
一:背景
相信有很多朋友在遇到應(yīng)用程序各種奇葩問題后,拿下來一個(gè)dump文件,辛辛苦苦分析了大半天,終于在某一個(gè)線程的調(diào)用棧上找到了一個(gè)可疑的方法,但 windbg 常常是以 匯編 的方式顯示方法代碼的,可惜的是,現(xiàn)如今的匯編,有多少像我們這些速成系碼農(nóng)還看的懂呢?😂😂😂
接下來尖銳的問題就來了,如何將這些匯編代碼轉(zhuǎn)成 C# 源代碼,如果轉(zhuǎn)不成源代碼轉(zhuǎn)成 IL代碼也好呀,起碼我努努力還是能試著看的懂的。。。
本篇我就來分享下如何把 dump 中的方法源碼提取出來。
二:從 dump 文件中提取源代碼
1. 案例演示
為了能夠演示方便,我用 .netcore 3.1 寫了一個(gè)簡單的demo,代碼如下:
namespace ConsoleApp6 { class Program { static void Main(string[] args) { Run(); } static void Run() { Console.WriteLine("hello world!"); Console.ReadLine(); } } }
將程序跑起來后,使用 任務(wù)管理器, adplus, procdump 隨便哪一個(gè)抓取 dump 都可以。
2. 使用 lm + savemodule 命令提取
如果你的程序足夠簡單,可以直接用 lm 獲取程序中所有的模塊,然后使用 savemodule 將模塊導(dǎo)出為 exe/dll 物理文件,如下所示:
- 使用 lm 提取出所有模塊
0:000> lm start end module name 000002c2`264b0000 000002c2`264b8000 ConsoleApp6_2c2264b0000 (deferred) 00007ff7`e4a50000 00007ff7`e4a7f000 ConsoleApp6 (deferred) 00007ffa`a4b50000 00007ffa`a546d000 System_Private_CoreLib (deferred) 00007ffa`a5470000 00007ffa`a59df000 coreclr (deferred) 00007ffa`df070000 00007ffa`df1b2000 clrjit (deferred) ...
可以隱約的看到,我有一個(gè)名為 ConsoleApp6_2c2264b0000 的模塊,這就是我要提取的 ConsoleApp6.exe,順便提一下,那個(gè)很礙眼的 ConsoleApp6 (deferred) 是 PE 文件,要問我怎么知道的?試一下就好啦😁
- 使用 savemodule 提取
從上面第一行 start 列中可以看到 ConsoleApp6_2c2264b0000 的開始地址為 000002c2264b0000,接下來用 savemodule 導(dǎo)出到 E:\dump。
0:000> !savemodule 000002c2`264b0000 E:\dump\ConsoleApp6.exe 3 sections in file section 0 - VA=2000, VASize=6c4, FileAddr=200, FileSize=800 section 1 - VA=4000, VASize=564, FileAddr=a00, FileSize=600 section 2 - VA=6000, VASize=c, FileAddr=1000, FileSize=200
然后就可以看到 E:\dump 里面多了一個(gè) ConsoleApp6.exe 🐂,有了這玩意看源碼就簡單多了,直接用 ILSpy 對(duì)其進(jìn)行反編譯即可。
3. 使用 dumpdomain/module + savemodule 提取
實(shí)際開發(fā)中有可能你的程序非常復(fù)雜,使用 lm 直接提取模塊是找不到的,最好的辦法就是 按圖索驥 的方式尋找你要的 module,還記得 CLR Via C# 上說過的 AppDomain,Assembly,Module 之間的關(guān)系嗎?如果要詳細(xì)了解,建議翻看一下,這里我大概簡述一下, Assembly 一般包含若干個(gè) Module + 資源文件, Assembly 就是一個(gè) dll/exe 文件,程序跑起來后,Assembly是被妥善安置在 AppDomain 中的。
有了上面這個(gè)思想,是不是就可以通過這個(gè)流程 AppDomain -> Assembly -> Module 找到 module 啦?接下來看看如何去實(shí)現(xiàn)。
- 使用 !dumpdomain 找到 ConsoleApp6 所在的程序域
0:000> !dumpdomain -------------------------------------- System Domain: 00007ffaa59996f0 LowFrequencyHeap: 00007FFAA5999C58 HighFrequencyHeap: 00007FFAA5999CE8 StubHeap: 00007FFAA5999D78 Stage: OPEN Name: None -------------------------------------- Domain 1: 000002c224b6ca80 LowFrequencyHeap: 00007FFAA5999C58 HighFrequencyHeap: 00007FFAA5999CE8 StubHeap: 00007FFAA5999D78 Stage: OPEN Name: clrhost Assembly: 000002c224bf1c00 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.12\System.Private.CoreLib.dll] ClassLoader: 000002C224B61820 Module 00007ffa45984020 C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.12\System.Private.CoreLib.dll Assembly: 000002c224bf1980 [E:\net5\ConsoleApp3\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.dll] ClassLoader: 000002C224BE3F80 Module 00007ffa45b5f7d0 E:\net5\ConsoleApp3\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.dll
尷尬,記得不錯(cuò)的話,在 .NET Framework 中默認(rèn)會(huì)有三個(gè)應(yīng)用程序域。
- System Domain
- Shared Domain
- Domain 1
咋到 .NET Core 上就丟了一個(gè) Shard Domain 呢 😄😄😄,先不管啦,從圖中可以清楚的看到 Domian 1 上有我的dll E:\net5\ConsoleApp3\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.dll,同時(shí)還有一個(gè) module 的地址 00007ffa45b5f7d0。
- 使用 !dumpmodule 獲取 module 詳細(xì)信息
0:000> !DumpModule /d 00007ffa45b5f7d0 Name: E:\net5\ConsoleApp3\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.dll Attributes: PEFile SupportsUpdateableMethods Assembly: 000002c224bf1980 BaseAddress: 000002C2264B0000 PEFile: 000002C224BF2300 ModuleId: 00007FFA45B5FB98 ModuleIndex: 0000000000000001 LoaderHeap: 0000000000000000 TypeDefToMethodTableMap: 00007FFA45B3C8D0 TypeRefToMethodTableMap: 00007FFA45B3C8E8 MethodDefToDescMap: 00007FFA45B3C958 FieldDefToDescMap: 00007FFA45B3C978 MemberRefToDescMap: 0000000000000000 FileReferencesMap: 00007FFA45B3C988 AssemblyReferencesMap: 00007FFA45B3C990 MetaData start address: 000002C2264B2078 (1304 bytes)
從上面的 BaseAddress: 000002C2264B0000 可以看出,module 的start 地址為 000002C2264B0000,是不是和剛才我用 lm 提取出來的地址一致哈,最后用 savemodule 導(dǎo)出一下就可以啦,為了做區(qū)分,我取名為 ConsoleApp7.exe, 如下所示:
哈哈,剩下來的就是用 ILSpy 反編譯 CosoleApp7 啦。
以上就是如何從dump文件中提取出C#源代碼的詳細(xì)內(nèi)容,更多關(guān)于dump 文件中提取出 C# 源代碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c#讀取excel數(shù)據(jù)的兩種方法實(shí)現(xiàn)
這篇文章主要介紹了c#讀取excel數(shù)據(jù)的兩種方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12C#實(shí)現(xiàn)控制電腦注銷,關(guān)機(jī)和重啟
這篇文章主要為大家介紹了C#如何實(shí)現(xiàn)控制電腦注銷,關(guān)機(jī)和重啟功能,本案例涉及的知識(shí)點(diǎn)包含:Process、Shell32.dll、User32.dll、Struct數(shù)據(jù)結(jié)構(gòu),感興趣的可以了解一下2022-09-09C#使用Jquery zTree實(shí)現(xiàn)樹狀結(jié)構(gòu)顯示 異步數(shù)據(jù)加載
這篇文章主要為大家詳細(xì)介紹了C#使用Jquery zTree實(shí)現(xiàn)樹狀結(jié)構(gòu)顯示和異步數(shù)據(jù)加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12詳解C#的設(shè)計(jì)模式編程之抽象工廠模式的應(yīng)用
這篇文章主要介紹了C#的設(shè)計(jì)模式編程之抽象工廠模式的應(yīng)用,注意區(qū)分一下簡單工廠模式、工廠方法模式和抽象工廠模式概念之間的區(qū)別,需要的朋友可以參考下2016-02-02C# WinForm捕獲全局變量異常 SamWang解決方法
本文將介紹C# WinForm捕獲全局變量異常 SamWang解決方法,需要的朋友可以參考2012-11-11