最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

攔截|篡改|偽造.NET類庫中不限于public的類和方法

2023-09-23 21:24 作者:沙漠盡頭的狼  | 我要投稿

大家好,我是沙漠盡頭的狼。

本文首發(fā)于Dotnet9,介紹使用Lib.Harmony庫攔截第三方.NET庫方法,達到不修改其源碼并能實現(xiàn)修改方法邏輯、預期行為的效果,并且不限于只攔截public訪問修飾的類及方法,行文目錄:

  1. 什么是方法攔截?

  2. 示例程序攔截

  3. 非public方法怎么攔截?

  4. 總結

1. 什么是方法攔截?

方法攔截是指在方法被調用之前或之后,通過插入自定義的代碼來修改方法的行為。通過方法攔截,開發(fā)人員可以在不修改原始代碼的情況下,對方法的輸入?yún)?shù)進行驗證、修改方法的返回值、記錄方法的調用日志等操作。

本文使用Lib.Harmony庫實現(xiàn)第三方庫方法的攔截,關于該庫站長寫過[快學會這個技能-.NET API攔截技法](快學會這個技能-.NET API攔截技法 - Dotnet9)一文,大家可以再看看,但該篇文章未介紹非public類及方法如何攔截,本文會有所補充反過來 。

2. 示例程序攔截

2.1. 編寫取數(shù)字段落的程序

創(chuàng)建一個.NET類庫工程,比如叫TestDll,添加工具類TestTool

上面的方法GetNumberSentence邏輯:傳入一個整型number參數(shù),除10(集合_sentences項數(shù))取模,返回10以內的數(shù)字美文段落,其中如果模為6會取數(shù)字1的段落(這是為了驗證攔截邏輯設計添加的)。

下面是寫的一個AvaloniaUI程序測試界面,UI不是本文重點,這里就直接貼動圖和代碼截圖了,文末也有源碼鏈接:

2.2. 為什么個位數(shù)字為6時,總是顯示數(shù)字1的段落呢?

分析上面的代碼,我們想把mo == 6時讓mo = 1邏輯去掉,除了使用dnSpy這些反編譯工具修改代碼,我們還可以使用Lib.Harmony(快學會這個技能-.NET API攔截技法 - Dotnet9)攔截GetNumberSentence方法。

  1. 安裝Lib.Harmony

<PackageReference Include="Lib.Harmony" Version="2.3.0-prerelease.2" />

  1. 編寫攔截替換類

參考快學會這個技能-.NET API攔截技法 - Dotnet9添加如下攔截替換類:

  • 在攔截類上注冊需要攔截的原類類型、原方法名和參數(shù)數(shù)據(jù)類型

  • 可以先將原方法內代碼復制到攔截替換方法Prefix內,對于原類中的屬性、字段可通過反射獲取(比如_sentences集合)

  • mo == 6的代碼注釋

別忘了在ProgramApp.xaml初始方法內注冊自動攔截類方法:

重新運行主程序,輸入數(shù)字6時正常顯示數(shù)字6對應的段落了:

這樣就達到不修改第三庫源碼的情況實現(xiàn)結果篡改了,站長使用.NET 8攔截會有異常,后改為?.NET 6?得以正常運行,異常信息如下,可能是Lib.Harmony還不支持.NET 8吧:

HarmonyLib.HarmonyException:“Patching exception in method System.String TestDll.TestTool::GetNumberSentence(System.Int32 number)”

TypeInitializationException: The type initializer for 'MonoMod.Utils.DMDEmitDynamicMethodGenerator' threw an exception.

InvalidOperationException: Cannot find returnType fieeld on DynamicMethod

3. 非public方法怎么攔截?

3.1. 修改數(shù)字段落獲取方法

還是修改TestTool類,另外增加GetNumberSentence2方法,在方法中添加一個數(shù)字驗證操作mo = new CalNumber().GetValidNumber(mo);,方法定義如下:

驗證方法定義如下:

  • CalNumber類和GetValidNumber方法用internal聲明,意為類或方法只能在當前工程內使用

并在主工程調用數(shù)字獲取段落方法處改為:

輸入6時又返回1的段落了:

問題來了:internal方法怎么攔截?

我們不直接注釋代碼mo = new CalNumber().GetValidNumber(mo);,萬一驗證方法非常重要,我們只是需要修改其中部分邏輯,總體原邏輯不應該改變。

3.2. internal方法怎么攔截?

新增攔截類HookGetValidNumber,現(xiàn)在不能再在類上添加特性了([HarmonyPatch(typeof(CalNumber))]),因為CalNumber不是public訪問修飾,跨工程無法直接使用,語法不支持:

特性用不上,那就手工注冊需要攔截的方法,這是本文的重點,代碼在下面,簡單提一下:

  • 手工注冊代碼和自動注冊聲明特性類似,只是換個寫法;

  • 攔截替換方法需要使用HarmonyMethod方法包裝;

  • harmony.Patch(hookMethod, replaceHarmonyMethod);用于關聯(lián)被攔截方法與替換方法

替換方法定義如下:

  • Prefix方法命名這里不加限制,只要和上面手工注冊(var replaceMethod = typeof(HookGetValidNumber).GetMethod(nameof(Prefix));)相同即可:

  • 數(shù)字等于6,修改偽造結果為8

最后在原自動注冊代碼下,再加一行手工注冊代碼就OK,打完收工:

運行效果如下,輸入6顯示數(shù)字8段落:

4. 總結

  • 技術交流加群請?zhí)砑诱鹃L微信號:dotnet9com

  • 文中示例代碼:MultiVersionLibrary

使用Lib.Harmony庫攔截注冊有兩種方式的用處如下:

  1. 自動注冊:

    • 通過在攔截類上使用特性關聯(lián)被攔截類和方法定義,可以實現(xiàn)自動注冊攔截邏輯。這種方式適用于需要攔截的類和方法比較多的情況,可以減少手動注冊的工作量,提高開發(fā)效率。

    • 自動注冊通常只能關聯(lián)public類或方法,因為IDE會根據(jù)代碼的可見性進行過濾和提示。

  2. 手工注冊:

    • 通過代碼構造被攔截類和方法定義進行手工注冊,可以更加靈活地控制攔截邏輯。這種方式適用于需要對攔截邏輯進行定制化處理的情況,可以根據(jù)具體需求選擇需要攔截的類和方法,并對攔截邏輯進行精細化配置。

    • 手工注冊更加靈活,可以攔截包括internal在內的各種類和方法。手工注冊可以通過編寫代碼來實現(xiàn)對非public類和方法的關聯(lián),但需要注意的是,這樣做可能會增加代碼的復雜性和維護成本。

時間如流水,只能流去不流回。


攔截|篡改|偽造.NET類庫中不限于public的類和方法的評論 (共 條)

分享到微博請遵守國家法律
汉阴县| 德昌县| 河间市| 会宁县| 鄢陵县| 革吉县| 石嘴山市| 阿合奇县| 牟定县| 平塘县| 合水县| 海兴县| 吉隆县| 富锦市| 凤阳县| 永城市| 凤庆县| 孝感市| 江门市| 龙南县| 锡林郭勒盟| 呼和浩特市| 桂东县| 舞钢市| 汉中市| 鞍山市| 双鸭山市| 祁阳县| 崇文区| 老河口市| 北京市| 卫辉市| 长沙县| 兴化市| 清新县| 永修县| 凤翔县| 旬邑县| 文成县| 锦屏县| 益阳市|