摘要:內部調用外掛使用逆向技術分析出游戲內部的匯編代碼,把里面對游戲玩家有利的函數作為外掛的實現功能。檢測代碼段在游戲沒有運行之前,修改添加或刪除文件的二進制信息可以起到修改程序流程的作用,從而起到外掛的作用。
現如今,有很多游戲外掛軟件,它們可以修改游戲顯示的數據和內部代碼,來達到謀取利益的目的。在實現反外掛技術前,我先介紹一下常見的三種外掛:
1.模擬類外掛:該外掛可以說是最早的外掛了,它是往游戲發送偽造的按鍵消息來模擬人的手工操作。實現的思路為:
1.
在Ring3層使用SendMassage、PostMassage、keybd_event、mouse_event等向消息隊列中發送按鍵消息
2.
使用回調函數KeyboardClassServiceCallback和MouseClassServiceCallback往類驅動輸入摁鍵消息。
?2.內部Call調用外掛:使用逆向技術分析出游戲內部的匯編代碼,把里面對游戲玩家有利的函數作為外掛的實現功能。實現的思路為:
1.
使用逆向工具,去除殼和里面的反調試功能
2.
分析游戲的使用過程、玩家自身的信息、背包信息、敵人信息等
3.
逆向分析出游戲的明文發包功能
4.
根據游戲的明文發包函數和報文信息分析游戲內部功能實現的函數
?3.脫機外掛:分析出游戲客戶端和服務端之間的通信邏輯,使用自己發送和接受數據來跟服務端進行交互。實現的思路如下:
1.
使用逆向工具,去除殼和里面的反調試功能
2.
逆向分析游戲中的匯編代碼,分析出加解密算法及各種資源信息
3.
分析出登錄封包,獲取各種跟游戲相關的信息
4.
整合尋路算法,實現掛機
1.最近玩植物大戰僵尸和連連看等游戲的時候發現,這些游戲需要通過啟動程序才能正常運行,那么我突發奇想,如果在程序運行前,修改游戲中的部分代碼段數據,等需要運行游戲時再通過另一個程序恢復代碼段數據,那么就可以起到保護游戲的作用。
2.對于游戲外掛制作者,他們經常習慣性的使用OD工具和CE工具、ida工具等,找出游戲的基址數據(也為全局變量)和內部call,然后修改基址數據或者修改執行流程,調用內部call。那么在游戲運行前就對基址數據地址和某些call后接地址進行修改,等需要運行游戲時,再修改回基址地址和call調用的地址,就可以起到反外掛的作用。
3.接下來,介紹一下這樣做的作用:
4.簡單介紹一下實現的流程:
1.讀取PE文件信息到內存中,遍歷PE文件中的代碼段,找到函數頭部地址和使用的全局變量地址;
2.在代碼段中,找出調用函數的call指令,把call后接地址進行修改,對于數據,找到使用全局變量的mov指令,修改地址操作數;
3.運行時,使用CreateProcess函數創建線程并掛起,然后恢復代碼段中的數據并運行進程
5.我開發了一款反游戲外掛工具(該工具及其源碼可在文章末尾下載)來模擬這個過程,在文件選擇框選擇要保護的PE文件,把需要保護的函數及數據添加到左邊欄中,執行保護時,在PE文件目錄下會生成已保護的PE文件,點擊運行時,就能正常運行。
1.在游戲沒有運行之前,修改、添加或刪除PE文件的二進制信息可以起到修改程序流程的作用,從而起到外掛的作用。實現的技術有:在代碼段的空白區域添加"洞穴代碼",修改OEP的值,讓程序跳轉到洞穴代碼;使用Inline HOOK執行外掛功能函數;修改代碼段中的跳轉指令和call后接地址,執行游戲內部匯編指令或者調動內部call等
2.在游戲運行時,通過外掛工具動態修改、添加或刪除進程代碼段數據或者動態注入shellcode同樣也能起到修改程序流程的作用,那么需要校驗PE文件和游戲內存數據就可以檢測出游戲外掛。
3.在實際運用中,可以計算出PE文件的校驗值,存放在游戲第三方程序的數據段中或者存放在游戲的服務器端,那么在游戲運行前校驗PE文件值和運行時動態檢驗進程內存,接下來使用工具來模擬這個過程:
1.選擇PE文件計算PE文件校驗值和記錄代碼段數據;
2.選擇需要校驗的文件,同樣也計算出校驗值并比較是否變化;
3.選擇正在運行的進程,比較代碼段數據是否變化。
4.實現的思路為:
1.使用MD5算法計算出前后PE文件的校驗值,并進行比較;
?2.先使用數組存放PE文件代碼段數據,后讀取進程內存中的代碼段數據,然后比較數組數據是否相同
?5.在游戲運行時,把游戲運行過程中使用過的函數及其相關的寄存器信息存放在服務端,在服務端檢測函數的調用流程,就可以判斷游戲內部call有沒有非法調用。不過我這里模擬這個過程的方式是把函數運行時的信息寫到日志文件中,查看日志信息來判斷游戲內部call是否被非法調用。
6.實現的思路為:
1.調式進程,循環接受調式事件;
2.在剛開始調式時,把函數頭部修改為CC;
3.當發現中斷時,判斷發生中斷的地址是否為函數頭部地址,是的話,把線程上下文信息記錄在日志文件中
//調式進程DebugActiveProcess(pid): //循環等待調式事件 while (WaitForDebugEvent(&de, INFINITE)) { ...... PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord; //觸發創建調式進程事件時 if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode) //修改函數頭部 SetUserFunc(&de); //觸發異常事件時 else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode) //判斷觸發異常地址 if (OnExceptionDebugEvent(&de)) continue; //繼續接受調式事件 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus); }
1.現在,有各種各樣的HOOK技術,包括 InLine HOOK、IAT HOOK、API HOOK等,其中大部分需要注入dll來實現HOOK功能,那么游戲運行時,服務端或者游戲第三方程序可以檢測有無dll注入,有的話,及時清除掉。實現的思路為:
1.先記錄游戲運行過程中用的dll文件名;2.游戲運行時遍歷進程使用的dll文件名,若遇到不名dll文件名,則進行釋放;
2.使用工具模擬這個過程:選擇進程,選中dll文件所在目錄,點擊檢測dll,就可檢測出進程中是否有dll注入。
3.那么,除了檢測dll文件外,還可以檢測 IAT表和函數內部代碼的跳轉指令來判斷游戲中是否有IAT HOOK或者InLine HOOK(跟API HOOK差不多,范圍比API HOOK小,我這里就不介紹了),實現的過程為:
1.選中游戲PE文件后,定位到導入表目錄,遍歷INT表中的_IMAGE_THUNK_DATA,通過里面的聯合體u1,來獲取游戲運行后IAT表中的函數地址;
2.選中進程,讀取進程內存中IAT表信息并比較函數地址,不同則說明有 IAT HOOK;
3.對于InLine HOOK,讀取進程代碼段中函數區域的跳轉指令操作數,若發現跳轉到別的函數區域,則說明有InLine HOOK;
4.使用工具模擬這個過程:選中進程和PE文件,再點擊 IAT HOOK按鈕或者InLine HOOK按鈕就可進行檢測。
1.現在的打金工作室可以同時開多個號來刷金幣,那么需要限制游戲多開,當動態調式進程時,在任務管理器中可以看到調式工具的主線程成了調式進程,那么調式器內存里面必然會有調式進程的內存信息,那么找到調式工具后再查找里面是否含有游戲進程的內存信息,若有則可以判斷,游戲處于調式狀態。
2.對于防多開,經常會用到下面的代碼,那么外掛制作者修改跳轉指令或者NOP掉匯編代碼就可以實現多開。為了防止這種情況,我這里把CreateMutex函數頭部修改為CC,使用調式器的方式不斷監控異常事件,當CreateMutex函數頭部觸發中斷異常時,獲取互斥體變量名(地址為:ESP+8),并判斷該變量名是否出現過,若出現過,則檢測出進程出現多開。實現的關鍵代碼如下:
//創建互斥體 HANDLE hMutex = CreateMutex(NULL,FALSE,"XXXXXX"); DWORD dret = GetLastError(); if(hMutex) { if (ERROR_ALREADY_EXISTS == dret) { CloseHandle(hMutex); return 0; } } ............. //WaitForSingleObject(hMutex,INFINITE); ............ ReleaseMutex(hMutex); return 0;}
檢測多開的關鍵代碼:
//解除HOOK 恢復原值 WriteProcessMemory(&pde->dwProcessId, g_pCreateMutex,&g_Orignal,sizeof(BYTE),NULL); //獲取線程上下文 ctx.ContextFlags = CONTEXT_CONTROL; GetThreadContext(g_cpdi2.hThread,&ctx); //得到ESP+8的值 ReadProcessMemory(g_cpdi2.hProcess, LPVOID(ctx.Esp + 0x8), &EspContent, sizeof(DWORD), NULL); printf("EspContent: %x/n", EspContent); //取出地址并獲取字符串 Name[NameNum++] = (char*)(EspContent); //判斷有無重復互斥名 list list1; for (int i = 0; i < NameNum; i++) { list1.push_back(Name[i]); } int len1 = list1.size(); list1.unique(); int len2 = list1.size(); //長度不等,則有重復元素 if (len1 != len2) { IsOpenMore = 1; return -1; } //讓EIP為當前地址 ctx.Eip = (DWORD)g_pCreateMutex; //設置線程上下文 SetThreadContext(g_cpdi2.hThread, &ctx); //繼續調式 ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);
3.對于多開檢測,我還想出了三種檢測方法:
1.獲取進程代碼段信息,使用代碼段信息匹配的方式來判斷是否有相同的進程運行;
2.獲取進程所有的窗口句柄,匹配查找有無跟窗口標題相同的窗口,有則說明多開;
3.對進程名進行匹配;
4.對于調式工具檢測,還是使用代碼段識別法:獲取OD工具中代碼段信息匹配尋找相同進程,若有,則再識別內部有無游戲進程的內存信息并且再判斷調式進程是否為調式工具的子進程,兩者有一成立,則說明游戲進程處于調式狀態,實現的關鍵代碼如下:
void ToolAndOpenMore::GetToolCode(BYTE* ToolCode, CString strPath){ //把PE文件加載到內存中 PVOID PeBuffer =PEFileToMemory(CStringToCharSz(strPath)); //PE文件頭 pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)PeBuffer + pDosHeader->e_lfanew + 0x4); //節表數量 DWORD SectionNum = pPEHeader->NumberOfSections; //PE可選頭 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER); DWORD EP = pOptionHeader->AddressOfEntryPoint; //代碼段節表頭 pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader); tpSectionHeader = pSectionHeader; int j = 0; //遍歷OEP之后的代碼段數據 for (int i = tpSectionHeader->PointerToRawData; i < tpSectionHeader->PointerToRawData + tpSectionHeader->SizeOfRawData && j
5.接下來,使用工具進行檢測:多開檢測只需選中進程點擊“多開檢測”按鈕即可;調式工具檢測要選中進程和調式工具,操作情況如下所示:
1.在游戲的PE文件中添加反調試,不為是一種較好的反外掛方法。在PE文件中修改TLS表信息,擴大最后一個節表并在空白區域添加PIMAGE_TLS_DIRECTORY結構信息、TLS回調函數,并在TLS回調函數中添加反調試功能即可實現反調試。
?2.實現反調試的思路為:
1.把PE文件加載到內存中,使用偏移的方式定位到TLS數據目錄,修改其中的 RVA字段值和Size字段值,讓 RVA指向PIMAGE_TLS_DIRECTORY起始地址;
2.定位到最后的節表結構并增加SizeOfRawData的值和修改Characteristics的值,使最后的節表具有可執行特性。
3.最后把生成的PIMAGE_TLS_DIRECTORY結構數據和回調函數ShellCode復制到最后的節表中。
3.除了往PE文件添加TLS反調式外,還可以添加SEH反調試,實現的思路為:
?
1.先在代碼段,尋找足夠大的空閑區域,若沒有找到,則新增最后節表大??;
2.確定空閑區域開始地址,修改OEP的值,在空閑區域添加觸發SEH異常的Shellcode,在該Shellcode中有異常處理函數,該異常處理函數會判斷游戲是否處于調式中,如果沒有處于調式狀態則跳回OEP中,否則中止;
4.接下來使用工具添加反調試,選中文件,點擊按鈕即可。
以上使用的工具和源碼可在該處下載:https://github.com/chenpan01/Anti_GameAssist。希望該工具及源碼對大家有所幫助,工具存在bug的話,歡迎提出,大家共同探討,共同提升!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119317.html
摘要:下面列舉了游戲開發中常見的崗位以及兩條常見的協作開發的流水線其實學習游戲引擎,前期對于任何崗位來說路線都是相似的,基本上就是一個熟悉基本操作理解基本概念拓展專業知識的過程。當然這不是絕對的,任何引擎的開始階段和大成階段都是相似的。 這是【游戲開發那些事】第51篇原創 前言:游戲引擎,表面...
摘要:規則分為可能是錯誤,最佳實踐,變量聲明等等,賀前輩的建議是能用的規則都用上。峰會中獎品挺多的,可惜與我擦肩而過。 iWeb峰會的消息是在開場前兩天才從朋友圈看到,稍微有點匆忙,只花了不到兩個小時的時間了解下相關主題。發現涉及的知識還是蠻多的,甚至一些平時也沒有接觸過。所以一些關注點,理解的層次都很有限,甚至可能有誤區,僅供參考及知識面的拓展。 工具應用類 峰會的主題是HTML5,又分為...
閱讀 2065·2021-10-11 10:59
閱讀 924·2021-09-23 11:21
閱讀 3540·2021-09-06 15:02
閱讀 1609·2021-08-19 10:25
閱讀 3364·2021-07-30 11:59
閱讀 2362·2019-08-30 11:27
閱讀 2574·2019-08-30 11:20
閱讀 2963·2019-08-29 13:15