对反游戏外挂技术的思索及实现

游戏 游戏 1676 人阅读 | 0 人回复

<
媒介

现如今,有许多游戏中挂硬件,它们能够修正游戏显现的数据战内乱部代码,去到达谋与长处的目的。正在完成反中挂妙技前,我先引见一下常睹的三种中挂:
1.模仿类中挂:该中挂能够道是最早的中挂了,它是往游戏收收假造的按键动静去模仿人的脚工操作。完成的思路为:
  1.正在Ring3层利用SendMassage、PostMassage、keybd_event、mouse_event等背动静行列中收收按键动静
  2.利用回调函数KeyboardClassServiceCallback战MouseClassServiceCallback往类驱动输进摁键动静。
 2.内乱部Call挪用中挂:利用顺背妙技阐发出游戏内乱部的汇编代码,把内里临游戏玩家有益的函数做为中挂的完成功用。完成的思路为:
  1.利用顺背东西,来除壳战内里的反调试功用
  2.阐发游戏的利用历程、玩家本身的疑息、背包疑息、仇敌疑息等
  3.顺背阐发出游戏的明文收包功用
  4.按照游戏的明文收包函数战报文疑息阐发游戏内乱部功用完成的函数
 3.脱机中挂:阐发出游戏客户端战效劳端之间的通讯逻辑,利用本人收收战承受数据去跟效劳端停止交互。完成的思路以下:
  1.利用顺背东西,来除壳战内里的反调试功用
  2.顺背阐发游戏中的汇编代码,阐发出减解稀算法及各类资本疑息
  3.阐发出登录启包,获得各类跟游戏相关的疑息
  4.整开觅路算法,完成挂机
庇护call函数战基址数据

1.近来玩动物年夜战僵尸战连连看等游戏的时分发明,那些游戏需求经由过程启动程序才气一般运转,那末我突收偶念,假如正在程序运转前,修正游戏中的部门代码段数据,等需求运转游戏时再经由过程另外一个程序规复代码段数据,那末就能够起到庇护游戏的感化。
150329ufrtfax685ff0ao0.png

2.关于游戏中挂建造者,他们常常民俗性的利用OD东西战CE东西、ida东西等,找出游戏的基址数据(也为齐局变量)战内乱部call,然后修正基址数据大概修正施行流程,挪用内乱部call。那末正在游戏运转前便对基址数据地点战某些call后接地点停止修正,等需求运转游戏时,再修正回基址地点战call挪用的地点,就能够起到反中挂的感化。
150330ybj1xz1r91tmbazj.png

3.接下去,引见一下如许做的感化:
150330gb8in5gne3edeg5y.png

4.俭朴引见一下完成的流程:
  1.读与PE文件疑息到内乱存中,遍历PE文件中的代码段,找到函数头部地点战利用的齐局变量地点;
  2.正在代码段中,找出挪用函数的call指令,把call后接地点停止修正,关于数据,找到利用齐局变量的mov指令,修正地点操作数;
  3.运转时,利用CreateProcess函数创立线程并挂起,然后规复代码段中的数据并运转历程
150330v5xjwegk54ww5uwq.png

5.我开辟了一款反游戏中挂东西(该东西及其源码可正在文章结尾下载)去模仿那个历程,正在文件挑选框挑选要庇护的PE文件,把需求庇护的函数及数据增加到右边栏中,施行庇护时,正在PE文件目次下会生成已庇护的PE文件,面击运转时,就可以一般运转。
150331fq9j98qdq855doq5.png

150331slva5wyfktuovjkm.png

检测代码段

1.正在游戏出有运转之前,修正、增加或删除PE文件的两进造疑息能够起到修正程序流程的感化,从而起到中挂的感化。完成的妙技有:正在代码段的空白地区增加"洞窟代码",修正OEP的值,退让伐跳转到洞窟代码;利用Inline HOOK施行中挂功用函数;修正代码段中的跳转指令战call后接地点,施行游戏内乱部汇编指令大概变更内乱部call等
150331a33vg2ogm3o19k9s.png

2.正在游戏运转时,经由过程中挂东西静态修正、增加或删除历程代码段数据大概静态注进shellcode一样也能起到修正程序流程的感化,那末需求校验PE文件战游戏内乱存数据就能够检测出游戏中挂。
150331jqhb666qanbzbnah.png

3.正在理想使用中,能够计较出PE文件的校验值,寄存正在游戏第三圆程序的数据段中大概寄存正在游戏的效劳器端,那末正在游戏运转前校验PE文件值战运转时静态检验历程内乱存,接下去利用东西去模仿那个历程:
  1.挑选PE文件计较PE文件校验值战记载代码段数据;
  2.挑选需求校验的文件,一样也计较出校验值并比力能否变化;
  3.挑选正正在运转的历程,比力代码段数据能否变化。
150332o7d2rpdgdfnd7wfk.png

4.完成的思路为:
  1.利用MD5算法计较出前后PE文件的校验值,并停止比力;
   2.先利用数组寄存PE文件代码段数据,后读与历程内乱存中的代码段数据,然后比力数组数据能否不异
150332rpkyxx8zpovnywwp.png

 5.正在游戏运转时,把游戏运转过程当中利用过的函数及其相关的存放器疑息寄存正在效劳端,正在效劳端检测函数的挪用流程,就能够断定游戏内乱部call有无不法挪用。不外我那里模仿那个历程的方法是把函数运转时的疑息写到日记文件中,检察日记疑息去断定游戏内乱部call能否被不法挪用。
150332d6g5y3uou4c5j100.png

6.完成的思路为:
  1.调式历程,轮回承受调式变乱;
  2.正在刚开端调式时,把函数头部修正为CC;
  3.当发明中止时,断定发作中止的地点能否为函数头部地点,是的话,把线程高低文疑息记载正在日记文件中
  1. //调式历程
  2. DebugActiveProcess(pid):                           
  3. //轮回等候调式变乱                           
  4. while (WaitForDebugEvent(&de, INFINITE))                              
  5.     {                              
  6.     ......                              
  7.     PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord;                              
  8.     //触收创立调式历程变乱时                              
  9.     if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)                              
  10.         //修正函数头部                              
  11.         SetUserFunc(&de);                           
  12.     //触收非常变乱时                              
  13.     else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode)                              
  14.         //判定触收非常地点                           
  15.         if (OnExceptionDebugEvent(&de))                           
  16.             continue;                       
  17.     //持续承受调式变乱                              
  18.     ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);                              
  19.     }
复造代码
HOOK检测

1.如今,有林林总总的HOOK妙技,包罗 InLine HOOK、IAT HOOK、API HOOK等,此中年夜部门需求注进dll去完成HOOK功用,那末游戏运转时,效劳端大概游戏第三圆程序能够检测有没有dll注进,有的话,实时肃清失落。完成的思路为:
1.先记载游戏运转过程当中用的dll文件名;2.游戏运转时遍历历程利用的dll文件名,若碰到没有名dll文件名,则停止开释;
150332i45psxlkss3s1zj3.png

2.利用东西模仿那个历程:挑选历程,选中dll文件地点目次,面击检测dll,便可检测出历程中能否有dll注进。
150333kprzmwulbflwgcrr.png

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;
150333fn1niki1jvhv1jz1.png


150334gleus2llx9lz2fl2.png

4.利用东西模仿那个历程:选中历程战PE文件,再面击 IAT HOOK按钮大概InLine HOOK按钮便可停止检测。
150334gdbb68nn7dlv4tqx.png

多开检测战静态调式东西检测

1.如今的挨金事情室能够同时开多个号去刷金币,那末需求限定游戏多开,当静态调式历程时,正在使命办理器中能够看到调式东西的主线程成了调式历程,那末调式器内乱存内里一定会有调式历程的内乱存疑息,那末找到调式东西后再查找内里能否露有游戏历程的内乱存疑息,若有则能够断定,游戏处于调式形态。
150334nrgqj4xybsjr7jgb.png

2.关于防多开,常常会用到上面的代码,那末中挂建造者修正跳转指令大概NOP失落汇编代码就能够完成多开。为了避免这类状况,我那里把CreateMutex函数头部修正为CC,利用调式器的方法不竭监控非常变乱,当CreateMutex函数头部触收中止非常时,获得互斥体变量名(地点为:ESP+8),并断定该变量名能否呈现过,若呈现过,则检测出历程呈现多开。完成的枢纽代码以下:
  1. //创立互斥体
  2.     HANDLE hMutex = CreateMutex(NULL,FALSE,"XXXXXX");
  3.     DWORD dret = GetLastError();
  4.     if(hMutex)
  5.     {
  6.         if (ERROR_ALREADY_EXISTS == dret)
  7.         {
  8.             CloseHandle(hMutex);
  9.             return 0;
  10.         }
  11.     }
  12.    .............
  13.     //WaitForSingleObject(hMutex,INFINITE);
  14.   ............
  15.     ReleaseMutex(hMutex);
  16.     return 0;
  17. }
复造代码
检测多开的枢纽代码:
  1. //消除HOOK 规复本值
  2.         WriteProcessMemory(&pde->dwProcessId, g_pCreateMutex,&g_Orignal,sizeof(BYTE),NULL);
  3.         //获得线程高低文
  4.         ctx.ContextFlags = CONTEXT_CONTROL;
  5.         GetThreadContext(g_cpdi2.hThread,&ctx);
  6.         //获得ESP+8的值
  7.         ReadProcessMemory(g_cpdi2.hProcess, LPVOID(ctx.Esp + 0x8), &EspContent, sizeof(DWORD), NULL);
  8.         printf("EspContent: %x\n", EspContent);
  9.         //掏出地点并获得字符串
  10.         Name[NameNum++] = (char*)(EspContent);
  11.         //判定有没有反复互斥名
  12.         list<string> list1;
  13.         for (int i = 0; i < NameNum; i++)
  14.         {
  15.             list1.push_back(Name[i]);
  16.         }
  17.         int len1 = list1.size();
  18.         list1.unique();
  19.         int len2 = list1.size();
  20.         //少度没有等,则有反复元素
  21.         if (len1 != len2)
  22.         {
  23.             IsOpenMore = 1;
  24.             return -1;
  25.         }
  26.         //让EIP为当前地点
  27.         ctx.Eip = (DWORD)g_pCreateMutex;
  28.         //设置线程高低文
  29.         SetThreadContext(g_cpdi2.hThread, &ctx);
  30.         //持续调式
  31.         ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);
复造代码
3.关于多开检测,我借念出了三种检测办法:
1.获得历程代码段疑息,利用代码段疑息婚配的方法去断定能否有不异的历程运转;
2.获得历程局部的窗心句柄,婚配查找有没有跟窗心题目不异的窗心,有则阐明多开;
3.对历程名停止婚配;
150334s9i9l1ixxuutl1p9.png

150335ylq2l2mlo4j34l5m.png

4.关于调式东西检测,仍是利用代码段识别法:获得OD东西中代码段疑息婚配寻觅不异历程,若有,则再识别内乱部有没有游戏历程的内乱存疑息并且再断定调式历程能否为调式东西的子历程,二者有一建立,则阐明游戏历程处于调式形态,完成的枢纽代码以下:
[code]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
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
回复 关闭延时

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则