游戏外挂检测和反检测
關(guān)于游戲外掛檢測(cè)和反檢測(cè)(真正的防封技術(shù))
在網(wǎng)上找到篇關(guān)于游戲外掛檢測(cè)和反檢測(cè)的文章拿來跟斷點(diǎn)的朋友分享。詳細(xì)文章見附件,這里寫些簡(jiǎn)介。
????一:內(nèi)存探測(cè)法
????????服務(wù)器發(fā)送個(gè)Paket檢測(cè)游戲內(nèi)存,然后返回服務(wù)器。這對(duì)游戲公開的掛威脅大。
????????反偵測(cè)基本思想是攔截Peket,返回偽裝Peket。
????二:DLL掃描
????????游戲反外掛系統(tǒng)(Module32First/Module32Next)掃描游戲中的DLL,返回。
????????反偵測(cè)思想是DLL隱藏。
????三:進(jìn)程掃描
????????游戲反外掛系統(tǒng)(Process32First/Process32Next)掃描用戶進(jìn)程,返回。
????????反偵測(cè)思想也是進(jìn)程隱藏(如將外掛進(jìn)程注入到游戲進(jìn)程)
????四:窗口掃描
????????游戲反外掛系統(tǒng)(EnumWindows)掃描進(jìn)程窗口,返回。這主要針對(duì)有GUI界面的外掛(外掛都有)
????????反偵測(cè)思想是隨機(jī)產(chǎn)生窗口類名和窗口名。(現(xiàn)在很多外掛都能做到這點(diǎn))
暴雪和黑客的戰(zhàn)爭(zhēng)(游戲外掛與反外掛)BZ加亮
[??? sell=5][/sell][??? post]如前一篇文章所說,D2X中hacks的發(fā)展大約可以分為三個(gè)階段,即前1.10的發(fā)展成熟期,1.10的過渡期以及1.11的衰落期。
一直到1.09d(1.10前的最后一個(gè)版本)為止,D2X中幾乎沒有作弊檢測(cè)機(jī)制,這一時(shí)期是hacker們最幸福的時(shí)期。說沒有是因?yàn)樗鼪]有專門的檢測(cè)代碼,而說幾乎沒有是因?yàn)樗行C(jī)制還是可以用來做作弊檢測(cè)用途的。
一處是它的自動(dòng)升級(jí)機(jī)制。在戰(zhàn)網(wǎng)上玩過的玩家都知道,每次連到戰(zhàn)網(wǎng)的時(shí)候,會(huì)有一個(gè)對(duì)話框提示正在檢查游戲版本,如果用戶本機(jī)和服務(wù)器端額版本不一致的話,自動(dòng)進(jìn)行升級(jí)。Diablo的自動(dòng)升級(jí)功能在游戲業(yè)界可能是首創(chuàng),這大大降低了游戲的上手難度。我接觸過不少外國(guó)玩家,跟國(guó)內(nèi)玩家不同的是,他們中很多人都是一些15歲不到的小孩,讓他們自己從網(wǎng)上下載補(bǔ)丁包升級(jí)幾乎是不可能的事。自動(dòng)升級(jí)的過程如下:
1,玩家連到戰(zhàn)網(wǎng);
2,服務(wù)器端發(fā)送一個(gè)專門用于版本檢查的DLL到客戶端;
3,客戶端在本機(jī)保存該DLL;
4,客戶端調(diào)用LoadLibrary加載DLL
5,客戶端調(diào)用該DLL導(dǎo)出的一個(gè)函數(shù)。該函數(shù)通過計(jì)算幾個(gè)重要的客戶端游戲文件的校驗(yàn)判斷版本是否匹配,不匹配則做自動(dòng)升級(jí)。
6,客戶端版本檢測(cè)完畢,調(diào)用FreeLibrary卸載DLL并刪除文件。
在這個(gè)過程中,由于版本檢查DLL保存在服務(wù)器端,因此顯然它可能會(huì)被隨時(shí)修改,增加一些其他功能,如作弊檢測(cè)。從版本檢測(cè)相關(guān)代碼(見文末)調(diào)用的Win32 API,LoadLibraryA/GetProcAddress/FreeLibrary/DeleteFileA,可以大致看出這一過程。
另外一處不為人知的機(jī)制是,在玩家連上戰(zhàn)網(wǎng)后,服務(wù)器端有時(shí)(不是一定會(huì)發(fā),而且發(fā)送時(shí)機(jī)也不確定)會(huì)發(fā)送一個(gè)DLL (Extrawork.dll)到客戶端運(yùn)行,然后把結(jié)果返回給服務(wù)器端,其工作原理和版本檢測(cè)機(jī)制的工作原理非常類似。顯然這個(gè)機(jī)制也可以用于作弊檢測(cè)。不過根據(jù)很多hacker觀測(cè)的結(jié)果,extrawork.dll一般用于收集玩家的系統(tǒng)配置信息,包括CPU主頻、內(nèi)存容量、操作系統(tǒng)版本等。
雖然這兩點(diǎn)機(jī)制都可能用于作弊檢測(cè),但在1.10以前的時(shí)間里,沒有跡象表明暴雪利用了這點(diǎn),因此在這一時(shí)期出現(xiàn)的hacks也都沒有相應(yīng)的反檢測(cè)措施。
版本檢測(cè)的相關(guān)代碼:
XXXX45A3???????????????? lea???? ecx, [esp+124h]
XXXX45AA???????????????? push??? ecx???????????? ; IX86ver0.dll
XXXX45AB???????????????? call??? ds:LoadLibraryA
XXXX45B1???????????????? mov???? ebp, eax
XXXX45B3???????????????? test??? ebp, ebp
XXXX45B5???????????????? jz????? loc_6FF046F1
XXXX45BB???????????????? push??? offset aCheckrevision ; "CheckRevision"
XXXX45C0???????????????? push??? ebp???????????? ; hModule
XXXX45C1???????????????? call??? ds:GetProcAddress
XXXX45C7???????????????? mov???? esi, eax
XXXX45C9???????????????? test??? esi, esi
XXXX45CB???????????????? jnz???? short loc_6FF045DF
XXXX45CD???????????????? push??? offset aErrorFailedT_0 ; "<ERROR: Failed to execute Versioning DL"...
XXXX45D2???????????????? call??? nullsub_1
XXXX45D7???????????????? add???? esp, 4
XXXX45DA???????????????? jmp???? loc_6FF046EA
XXXX45DF loc_XXXX45DF:
;......
XXXX46E6???????????????? call??? esi???????????? ; CheckRevision
XXXX46E8???????????????? mov???? ebx, eax
XXXX46EA
XXXX46EA loc_XXXX46EA:?????????????????????????? ; CODE XREF: DownloadAndRunVersioningDLL+15A j
XXXX46EA???????????????? push??? ebp???????????? ; hLibModule
XXXX46EB???????????????? call??? ds:FreeLibrary
XXXX46F1
XXXX46F1 loc_XXXX46F1:?????????????????????????? ; CODE XREF: DownloadAndRunVersioningDLL+F3 j
XXXX46F1???????????????????????????????????????? ; DownloadAndRunVersioningDLL+11E j ...
XXXX46F1???????????????? mov???? eax, [esp+430h+hArchive]
XXXX46F5???????????????? pop???? ebp
XXXX46F6???????????????? test??? eax, eax
XXXX46F8???????????????? jz????? short loc_XXXX4700
XXXX46FA???????????????? push??? eax???????????? ; hArchive
XXXX46FB???????????????? call??? Storm_252_SFileCloseArchive
XXXX4700
XXXX4700 loc_XXXX4700:?????????????????????????? ; CODE XREF: DownloadAndRunVersioningDLL+278 j
XXXX4700???????????????? push??? 32h???????????? ; dwMilliseconds
XXXX4702???????????????? call??? ds:Sleep
XXXX4708???????????????? mov???? esi, ds:DeleteFileA
XXXX470E???????????????? push??? offset g_szVersionDLLName ; lpFileName
XXXX4713???????????????? call??? esi ; DeleteFileA
XXXX4715???????????????? mov???? al, [esp+42Ch+FileName]
XXXX471C???????????????? test??? al, al
XXXX471E???????????????? jz????? short loc_XXXX472A
XXXX4720???????????????? lea???? eax, [esp+42Ch+FileName]
XXXX4727???????????????? push??? eax???????????? ; lpFileName
XXXX4728???????????????? call??? esi ; DeleteFileA
暴雪在WOW開發(fā)的后期,終于能夠騰出人手來升級(jí)持續(xù)了2年之久的D2X 1.09d。由于1.09d時(shí)期hacks泛濫,暴雪覺得有必要打擊一下這種囂張的氣焰,于是加入了hacks檢測(cè)機(jī)制,這就是在1.10時(shí)期經(jīng)常提起的packet 64/65檢測(cè)。
何謂packet?packet即網(wǎng)絡(luò)數(shù)據(jù)包,D2中服務(wù)器端和客戶端之間的交互是通過互相發(fā)送packet進(jìn)行的。D2中的packet又分為out-of-game(進(jìn)入游戲前)packet和in-game(游戲內(nèi))packet兩種,這里提到的都是in-game packet。in-game packet的第一個(gè)字節(jié)為packet ID,指示該packet的含義,接著的是相應(yīng)的(可變長(zhǎng))參數(shù)。比如ID 01代表walk命令,長(zhǎng)度為5字節(jié),ID后面跟兩個(gè)16位參數(shù),指示walk的目的坐標(biāo),因此它的格式為:01 [WORD x] [WORD y]。需要注意的是D2中不同patch版本的packet ID含義是不一樣的,不能通用。1.10中的一個(gè)比較完整的in-game packet列表可以在這里找到:http://www.edgeofnowhere.cc/viewtopic.php?t=303771
跟hacks檢測(cè)有關(guān)的是packet 64和65。packet 64長(zhǎng)度是9字節(jié),格式為:64 [DWORD address 1] [DWORD address 2],后面的兩個(gè)DWORD是服務(wù)器端想檢測(cè)的兩個(gè)內(nèi)存地址;packet 65長(zhǎng)度為1字節(jié)(沒有參數(shù)),檢查4個(gè)最有可能被patch的地址。packet 64/65的檢查結(jié)果經(jīng)過簡(jiǎn)單的混淆處理(增加sniffer抓包分析的難度)后發(fā)送回服務(wù)器端,如果被檢測(cè)地址里的指令或數(shù)據(jù)被改過,檢測(cè)結(jié)果自然就和原先的不符,因此暴雪就知道你在用hack。這種檢測(cè)方法就是所謂的memory probe,即內(nèi)存探測(cè)法。那暴雪怎么知道應(yīng)該檢測(cè)哪些地址呢?hack的detour patch(旁路點(diǎn))是固定的,像maphack和d2jsp這種著名的公開發(fā)行的hack,暴雪當(dāng)然會(huì)拿來研究因此也會(huì)知道它們patch了哪些地方。至于那些自己開發(fā)自娛自樂的,暴雪是沒法知道的,因此相對(duì)安全點(diǎn)兒。但是如果你的patch點(diǎn)正好和maphack、d2jsp這些相同,那還是有可能不幸中標(biāo)。
以下為packet 64檢測(cè)中的相關(guān)代碼片斷,其中eax和ecx分別為兩個(gè)待檢測(cè)的內(nèi)存地址,檢測(cè)結(jié)果分別存入局部變量var_result1和var_result2中隨后發(fā)送回服務(wù)器端:
.text:XXXXF362 $CHECK_RESULT1: ; CODE XREF: CheckDetectionResult+87 j
.text:XXXXF362 cmp eax, esi ; not zero
.text:XXXXF364 jz short $CLEAR_RESULT1 ; Jump if Zero (ZF=1)
.text:XXXXF366 mov [ebp+arg1], esi
.text:XXXXF369 mov eax, [eax]
.text:XXXXF36B mov [ebp+var_result1], eax
.text:XXXXF36E mov [ebp+arg1], -1
.text:XXXXF375 jmp short $CHECK_RESULT2 ; Jump
.text:XXXXF39B $CHECK_RESULT2: ; CODE XREF: CheckDetectionResult+A5 j
.text:XXXXF39B ; CheckDetectionResult+C4 j
.text:XXXXF39B cmp ecx, esi ; Compare Two Operands
.text:XXXXF39D jz short $CLEAR_RESULT2 ; Jump if Zero (ZF=1)
.text:XXXXF39F mov [ebp+arg1], 1
.text:XXXXF3A6 mov ecx, [ecx]
.text:XXXXF3A8 mov [ebp+var_result2], ecx
.text:XXXXF3AB mov [ebp+arg1], -1
.text:XXXXF3B2 jmp short $SEND_DETECT_RESULT ; Jump
packet 65的檢測(cè)代碼和packet 64類似,除了它檢測(cè)的是幾個(gè)固定地址。
packet 64/65的memory probe機(jī)制,結(jié)合前一篇介紹過的已有的version-checking.dll和extrawork.dll,就構(gòu)成了暴雪在Diablo II 1.10 patch中采用的hacks檢測(cè)機(jī)制。
下圖顯示了d2jsp 1.2.0中使用的部分旁路點(diǎn)(d2jsp 1.2.0用于Diablo II 1.11b,但意思是一樣的)。
暴雪在1.10補(bǔ)丁中加入hack檢測(cè)機(jī)制,在某種程度上直接導(dǎo)致了原本和諧的D2X游戲黑客社群的分裂。一部分出于對(duì)檢測(cè)機(jī)制的顧慮,停止更 新自己的作品,如d2hackit;另一部分則把他們的hack具有的反檢測(cè)功能當(dāng)成賣點(diǎn)開始收費(fèi),如d2maphack和d2jsp;還有一部分黑客出 于不滿開始制作這些收費(fèi)hacks的替代品,如d2hackmap,C3PO,d2bs等;甚至有些黑客出來破解這些收費(fèi)hacks。
如前一篇文章所說,暴雪在1.10中加入packet 64/65檢測(cè)。最早公布packet 64被用作hack檢測(cè)的是jhj。當(dāng)然Mousepad在jhj之前就已知道這一點(diǎn),但是他當(dāng)時(shí)正打算對(duì)maphack收費(fèi),反檢測(cè)是一大賣點(diǎn),因此一 直沒有公布。在jhj公布了他的發(fā)現(xiàn)后,我檢查了相關(guān)代碼,又發(fā)現(xiàn)了packet 65也被用作hack檢測(cè)。
如前文的分析,packet 64/65檢測(cè)用的都是memory probe方法,那么memory probe該怎么對(duì)付呢?一種簡(jiǎn)單的想法是在客戶端截獲packet 64/65檢測(cè),不讓它返回檢測(cè)結(jié)果。截獲packet 64/65檢測(cè)思路是對(duì)的,但不返回檢測(cè)結(jié)果其實(shí)也是一種信息,暴雪完全可能根據(jù)這點(diǎn)判斷你在使用hacks,最不濟(jì)也會(huì)把你踢下線,顯然不是好的做法。 對(duì)付memory probe,更好的做法是偽造檢測(cè)結(jié)果。這需要截獲packet 64/65檢測(cè),然后根據(jù)要檢測(cè)的內(nèi)存地址返回該地址被修改前的數(shù)據(jù)(如果已經(jīng)被修改了的話),這樣無論檢測(cè)哪個(gè)地址,檢測(cè)結(jié)果都和沒有使用hacks時(shí) 的一樣。
具體到實(shí)現(xiàn)方法,大約又有三種。
一種是hack在安裝旁路點(diǎn)時(shí),先保存原先的數(shù)據(jù),這樣在遇到檢測(cè)時(shí)就能知道patch前的數(shù)據(jù)。使用這種方法的有d2maphack、d2jsp等。這種方法最簡(jiǎn)單,實(shí)現(xiàn)起來也容易,占用額外內(nèi)存也不大。缺點(diǎn)只能保護(hù)自己,不能保護(hù)其他hacks。
第二種方法由jhj實(shí)現(xiàn),其原理是在加載任何hack之前,先對(duì)游戲中用到的重要的dll做備份,這樣就獲得了這些dll干凈的副本。然后截獲 packet 64/65檢測(cè)入口,根據(jù)檢測(cè)地址,從干凈的副本中返回相應(yīng)的數(shù)據(jù)。這就是jhj在 1.10時(shí)期發(fā)布的antidetection.dll。這種方法最大的優(yōu)點(diǎn)是通用,可以保護(hù)其它hacks-其他hack不需要有任何反檢測(cè)措施就能避 開檢測(cè)。但是這種實(shí)現(xiàn)也有不小的缺陷。其一是它必須搶在其他所有hack之前加載,否則無法獲得干凈副本-如果無法獲得干凈副本這種方法就完全失去意義- 這在有些情況下是不容易做到的,比如無人職守的BOT。其二是所有重要的dll都要備份,這會(huì)額外消耗不少內(nèi)存,對(duì)機(jī)器配置差或者多開BOT的玩家有很大 影響。其三是antidection.dll只備份了它認(rèn)為重要的dll,而不是所有dll,這樣如果有的hack修改的dll不在它的保護(hù)范圍,還是有 可能被抓到。
第三種方法由我實(shí)現(xiàn),稱之為模塊重建法(module re-construction),首先在d2hackmap中實(shí)現(xiàn),后來ABin升級(jí)d2hackit時(shí)請(qǐng)我?guī)兔?shí)現(xiàn)anti-detection模 塊,因此我又把它集成進(jìn)了d2hackit 2.00版本中。這種方法的思路是截獲packet 64/65檢測(cè)入口(顯然所有反檢測(cè)方法都需要這一步),根據(jù)檢測(cè)地址判斷出目標(biāo)模塊名稱和其在硬盤文件路徑,然后從該模塊的硬盤文件開始重建一份干凈的 副本,最后從干凈的副本中返回相應(yīng)的數(shù)據(jù)。這種方法在沒有檢測(cè)活動(dòng)時(shí)(其實(shí)1.10時(shí)期packet 64/65檢測(cè)很少出現(xiàn))不會(huì)消耗額外內(nèi)存,可保護(hù)所有dll,也無需搶先加載。我個(gè)人覺得是一種比較理想的方法。當(dāng)然,模塊重建法的難點(diǎn)在于如何從一個(gè) dll文件重建一份和已加載模塊被修改前完全一樣的副本(其實(shí)是代碼段和只讀數(shù)據(jù)段完全一樣,讀寫數(shù)據(jù)段無所謂),這在以后的文章中應(yīng)該有機(jī)會(huì)介紹到。
另外,除了packet 64/65檢測(cè),別忘了1.10以前一直就有的version-checking.dll和extrawork.dll機(jī)制。雖然它們?cè)谇?.10時(shí)期從 未被用作hack檢測(cè),但是顯然暴雪在1.10時(shí)期開始重視打擊hacks,因此也不得不防。回想一下這兩處機(jī)制,由于這兩個(gè)dll都存放在服務(wù)器端,必 要時(shí)發(fā)送到客戶端運(yùn)行并返回結(jié)果。不讓它們運(yùn)行顯然是不行的。并且顯然它們的檢測(cè)手段也是無限、未知的,偽造檢測(cè)結(jié)果也不可行。那該怎么辦呢?
對(duì)付這種手段的一種比較有效的方法是,截取并保存盡可能多的從服務(wù)器端傳過來的dll,逐一分析,標(biāo)出安全的和不安全的,并對(duì)每個(gè)dll建立簽名 (signature)。這樣在每次客戶端接收到dll時(shí),先計(jì)算出其簽名然后和已事先分析過的所有dll簽名比較,這樣就可知道該dll安不安全(即能 否檢測(cè)出我的hack),如果安全則讓它執(zhí)行,如果不安全則hack會(huì)自己卸載,然后再讓該dll執(zhí)行。這樣就不會(huì)被它抓到。另外對(duì)于未知模塊(即該 dll的簽名不在列表里),應(yīng)該把它保存下來以供事后分析,同時(shí)為保安全hack自己卸載,在以后分析后再把它標(biāo)識(shí)為安全或不安全。當(dāng)然對(duì)于不安全的模塊 還應(yīng)進(jìn)一步研究反檢測(cè)方法然后把它標(biāo)為安全模塊。d2maphack、d2jsp采取的都是這種策略。d2hackmap由于我后來沒有太多精力人工分析 這些模塊,因此只在配置文件里設(shè)置開關(guān)變量,指示d2hackmap遇到這些模塊時(shí)如何處理(有忽略、卸載自身、保存模塊文件并卸載自身三種選擇)。至于 jhj的AntiDetection.dll是沒有這方面的反檢測(cè)保護(hù)的。事實(shí)證明這種策略是比較有效的。一個(gè)可能的原因是由于設(shè)計(jì)所限,這種發(fā)送dll 檢測(cè)機(jī)制尚不具備快速變形、頻繁運(yùn)行的能力。
總結(jié)
以上是生活随笔為你收集整理的游戏外挂检测和反检测的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在互联网大厂,我月入过万,合租却让我落泪
- 下一篇: 从JDK 6升级到JDK 7过程中遇到的