日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

输入法注入源码_将注入进行到底:利用Mono注入C#游戏脚本

發(fā)布時(shí)間:2024/10/6 C# 287 豆豆
生活随笔 收集整理的這篇文章主要介紹了 输入法注入源码_将注入进行到底:利用Mono注入C#游戏脚本 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文作者01dTan9,首發(fā)于三葉草小組博客:http://blog.sycsec.com/?? 致力于引領(lǐng)每一位對windows安全感興趣的萌新,希望讓萌新能夠?qū)indows有初步的了解。筆者的文章涉獵廣泛,從Windows基礎(chǔ)編程,加密與解密,跨平臺腳本語言,硬件安全,到游戲引擎逆向,涵蓋多方面,多領(lǐng)域的理論與技術(shù),幫助萌新更快地從入門到入獄。

?1. 游戲腳本是什么?

腳本語言(英語:Scripting language)是為了縮短傳統(tǒng)的“編寫、編譯、鏈接、運(yùn)行”(edit-compile-link-run)過程而創(chuàng)建的計(jì)算機(jī)編程語言。早期的腳本語言經(jīng)常被稱為批處理語言或工作控制語言。一個(gè)腳本通常是解釋運(yùn)行而非編譯。


游戲腳本由于腳本語言的開發(fā)成本低,許多游戲引擎不約而同地使用了腳本語言作為主要編程語言,比如大名鼎鼎的《魔獸世界》,就是使用的Lua進(jìn)行開發(fā)的。本文所描述的游戲腳本是Unity(游戲引擎)中使用的主要編程語言——C#,并且Unity提供C#中的主要腳本API ,其腳本具有簡單、易學(xué)、易用的特性,目的就是希望能讓開發(fā)人員快速完成游戲開發(fā)。

2.為什么要注入游戲腳本?

1.?傳統(tǒng)注入方式

對于傳統(tǒng)的第三方游戲插件開發(fā)而言,由于沒有游戲廠商提供的官方接口,只能通過非常規(guī)的方式將插件的功能安裝在游戲中。

通常來說,這些安裝的方式與病毒的行為十分類似,更偏向于系統(tǒng)底層,比如利用Windows API修改目標(biāo)進(jìn)程中的數(shù)據(jù),或者創(chuàng)建遠(yuǎn)程線程讓目標(biāo)進(jìn)程執(zhí)行匯編代碼或加載第三方庫(如DLL),更有甚者,直接在Windows內(nèi)核中劫持目標(biāo)進(jìn)程網(wǎng)絡(luò)通訊,或進(jìn)行APC注入。

目前傳統(tǒng)的應(yīng)用層注入方式主要有以下幾種:

靜態(tài)注入類:

? ? ? ? 導(dǎo)入表注入

? ? ? ? 注冊表注入

? ? ? ? DLL劫持注入

動態(tài)注入類:

? ? ? ? ?鉤子注入

? ? ? ? ?APC注入

? ? ? ? ?遠(yuǎn)程線程注入

? ? ? ? ?輸入法注入

? ? ? ? ?LSP注入

使用上述方法安裝的插件,其功能實(shí)現(xiàn)大部分要靠硬編碼、鉤子、內(nèi)存修改來實(shí)現(xiàn)。這樣一來,需要耗費(fèi)大量的時(shí)間分析游戲的匯編代碼與通過內(nèi)存中的數(shù)據(jù)來構(gòu)建結(jié)構(gòu)體與游戲?qū)ο蟆?/p>

2. 從硬編碼注入到腳本注入

假如我們可以讓游戲腳本在游戲中執(zhí)行,通過腳本直接使用游戲引擎封裝好的函數(shù)與對象,不就可以事半功倍了嗎?

3. Mono 與 Unity 下的C#游戲腳本

1.?Unity3D

Unity3D是由Unity Technol ogies開發(fā)的一個(gè)讓玩家輕松創(chuàng)建諸如三維視頻游戲、建筑可視化、實(shí)時(shí)三維動畫等類型互動內(nèi)容的多平臺的綜合型游戲開發(fā)工具,是一個(gè)全面整合的專業(yè)游戲引擎。Unity使用戶能夠以2D和3D方式創(chuàng)建游戲,并且引擎提供C#中的主要腳本API ,用于插件形式的Unity編輯器,游戲本身以及拖放功能。在?C#作為引擎使用的主要編程語言之前,Unity支持?Boo?和?JavaScript?版本的?UnityScript。

2. Mono

Mono是一個(gè)免費(fèi)的開源項(xiàng)目。由微軟的子公司Xamarin(前身為Novell,最初由Ximian)和.NET基金會領(lǐng)導(dǎo)。旨在構(gòu)建符合ECMA(歐洲計(jì)算機(jī)制造商協(xié)會)標(biāo)準(zhǔn)的.NET Framework兼容工具集。包括?C#編譯器和帶有實(shí)時(shí)(JIT)編譯的公共語言運(yùn)行時(shí)。

3.?Mono和Unity3D

簡單來說,Mono是Unity3D的一個(gè)運(yùn)行時(shí),負(fù)責(zé)C/C++和C#/CIL的交互。

舉個(gè)例子,隨便打開一個(gè)Unity游戲的根目錄,你會發(fā)現(xiàn)一個(gè)名為UnityPlayer.dll的動態(tài)鏈接庫,這個(gè)動態(tài)鏈接庫封裝是Unity的底層C++代碼。

在?游戲根目錄\Mono\EmbedRuntime\?(某些低版本Unity游戲目錄為游戲根目錄\Mono\,筆者的為 2018.2.0 Beta)下有一個(gè)名為mono.dll的動態(tài)鏈接庫,這個(gè)便是負(fù)責(zé)C/C++和C#/CIL的交互的模塊,網(wǎng)上有開源版本,但許多游戲公司為了防止游戲被惡意修改,通常都重新編譯mono.dll,在其中加入加密游戲數(shù)據(jù)與檢測惡意行為的代碼。

在游戲根目錄\游戲名_Data\Managed\中名為Assembly-CSharp.dll的文件便是C#腳本代碼。

三者的關(guān)系如下:

4.如何利用?Mono平臺實(shí)現(xiàn)游戲腳本入?

利用Mono平臺實(shí)現(xiàn)游戲腳本注入的主要方法有兩種,一種是靜態(tài)修改,直接PatchAssembly-CSharp.dll的代碼。

本文測試環(huán)境是在Windows下,主要是闡述思路,Android平臺的注入同理。
另一種是調(diào)用mono.dll的API,動態(tài)加載C#代碼(移動端同理),本文主要討論后者。

代碼實(shí)現(xiàn)主要由三部分組成:
? ? C#庫文件(負(fù)責(zé)實(shí)現(xiàn)第三方功能)
? ? 動態(tài)鏈接庫(用于在目標(biāo)程序加載腳本)??
? ? 主程序(負(fù)責(zé)注入DLL到目標(biāo)程序)

1.C#庫文件

負(fù)責(zé)實(shí)現(xiàn)第三方功能,代碼需要因游戲而定,主要是通過獲取或修改Unity原生組件(Transform、physics等)的數(shù)據(jù)實(shí)現(xiàn)第三方功能,也可以直接使用開發(fā)者定義的函數(shù),但這種方法需要獲取游戲源代碼,需要解密腳本文件,在此不再贅述。

2.動態(tài)鏈接庫

在目標(biāo)進(jìn)程中載入C#腳本需要以下API,具體參數(shù)查閱mono官方文檔,上面都有詳細(xì)解釋。

通過文件名加載C#腳本文件鏡像。

????????mono_image_open_from_data

從文件鏡像中讀取并將C#代碼編譯為IL代碼,至此,C#代碼被即時(shí)編譯完畢。

????????mono_assembly_load_from_full

獲取IL代碼的鏡像。

????????mono_assembly_get_image

通過類名獲取類句柄,供????????????????????????mono\_class\_get\_method\_from\_name調(diào)用。

????????mono_class_from_name

通過類句柄和函數(shù)名獲取函數(shù)地址,供mono\_runtime\_invoke調(diào)用。

????????mono_class_get_method_from_name

通過函數(shù)地址運(yùn)行IL代碼,代碼開始運(yùn)行。

????????mono_runtime_invoke

在調(diào)用mono的API之前,我們需要獲取API的函數(shù)地址,基本方法如下:? ?

首先獲取mono.dll的模塊句柄

HMODULE hMono = GetModuleHandle(L"mono.dll");

再獲取API地址

typedef void* (__cdecl *MONO_IMAGE_OPEN_FROM_DATA)(char *ImageName);

MONO_IMAGE_OPEN_FROM_DATA mono_image_open_from_data;

mono_image_open_from_data = (MONO_IMAGE_OPEN_FROM_DATA)GetProcAddress(hMono, "mono_image_open_from_data");

用這種方法獲取所有需要調(diào)用的API

加載C#腳本代碼

#define ClassName L"ClassName"

#define MethodName L"MethodName"

#define name_space L"name_space"

intptr_t raw_image = ImageOpenFromDataFull(file_data);

intptr_t assembly = AssemblyLoadFromFull(raw_image);

intptr_t image = AssemblyGetImage(assembly);

intptr_t class_id = GetClassFromName(image, name_space, ClassName);

intptr_t method = GetMethodFromName(class_id, MethodName);

RuntimeInvokeMethod(method);

還可以在DLL中實(shí)現(xiàn)C#熱更新,方便調(diào)試。

3.主程序

主程序負(fù)責(zé)將動態(tài)鏈接庫注入到目標(biāo)程序。

通過上文提到的遠(yuǎn)程線程注入方法

使用?CreateRemoteThread?遠(yuǎn)程調(diào)用?LoadLibrary?即可。

5. 腳本注入攻防思路

1 . 如何對抗腳本注入(Anti-Cheat)

對抗腳本注入,有以下幾種、主要思路是在mono.dll上做手腳。

? ? ? ? ·當(dāng)前流行的方法通過修改mono源碼,加密Assembly-CSharp.dll,并在mono_image_open_from_data里加入解密腳本的函數(shù),這樣既可以防止腳本被靜態(tài)Patch,又可以防止動態(tài)注入。

? ? ? ? ? ·Android平臺下的進(jìn)程保護(hù)

? ? ? ? ??·Windows平臺下的進(jìn)程保護(hù)(R0、R3)

另外一種是在其他mono函數(shù)加入檢測代碼。筆者所遇到便是在mono_class_from_name加入檢測代碼,非原生腳本的加載都會導(dǎo)致函數(shù)調(diào)用崩潰。

2.?如何繞過防注入(By Pass)?

·利用沒有被修改的函數(shù)加載代碼,如mono_assembly_foreach枚舉IL代碼鏡像,繞過mono_class_from_name的檢測。

·重寫mono_class_from_name函數(shù)。

·加載另一個(gè)純凈的mono.dll,使用純凈模塊里面的函數(shù)來加載代碼。

6.總結(jié)

利用mono平臺注入C#代碼大大提高了開發(fā)效率,如果是單純用原生Unity組件開發(fā)出來的代碼基本上適用于所有用Unity引擎開發(fā)的游戲。

未來Unity可能會放棄mono平臺,轉(zhuǎn)用LICPP平臺,但是短時(shí)間內(nèi)是不會放棄mono這個(gè)成熟的平臺的,所以,本方法在未來一段時(shí)間內(nèi)都有利用價(jià)值。

點(diǎn)擊閱讀原文查看更多

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的输入法注入源码_将注入进行到底:利用Mono注入C#游戏脚本的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。