谁都可以创造奇迹给我一个私服挂吗奇迹的

悬赏5积分我来回答
提问者:&&A&|[四川 攀枝花];& 19:27:00
全国最大免费法律咨询中心,等您法律在线咨询!
回答者专区
系统自动回复
尊敬的用户您好,如果您的问题还没有律师回复,或者当前律师的回复还没有解决您的问题,建议您直接找或者电话咨询(请说明来自中顾法律网),快速解决您的问题。您也可以拨打全国免费法律咨询热线:400-000-9164,进行电话咨询。
等待您来回答
请输入问题标题!(至少含有6-60个汉字)
注:请选择事情发生的地区
专业律师推荐
专业工程建筑律师咨询
中顾法律网版权所有 Copyright
国家信息产业部备案 鲁ICP备奇迹私服1.03h辅助官网免费下载,奇迹私服1.03h辅助官方最新版下载-126下载
我的下载文件          
好评:50.00%(0)
差评:50.00%(0)
分享给好友:复制地址
用户其它文件
最新上传文件
相关热门排行
文件描述介绍
=================================重要提醒:【奇迹私服1.03h辅助】已经更新至最新稳定版功能更稳定强大!永久免费!老版本已失效,请下载此最新版↓最新稳定版本地高速下载:
电信用户高速下载:  
其他网络高速下载:  
=================================
猜你喜欢的
文件下载地址
电信高速下载
联通高速下载可以给我一个私服挂吗奇迹的_百度知道
可以给我一个私服挂吗奇迹的
我有更好的答案
不可以.请玩公服
来自:求助得到的回答
其他类似问题
为您推荐:
奇迹的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁奇迹私服经验之谈,论使用外挂者与反外挂者
自&&石器时代&&开始, 外G这一名词渐渐为世人所知. 到盛大SD第一款网游&&传奇&& 刚开始的宣传语 &永无外G&基本上所有的玩家都知道了有个叫外G的玩意. 等到了&&基本上玩游戏的都是人手一挂.但是当时的运营商并没有怎么把反外G放在心上-当时游戏的模式只是点卡与月卡. 只要你玩游戏,总是要付费的.运营商需要担心的,只是外G会造成多少用户流失而已. &&石器&&的运营商很绝--干脆自己卖外G.而 &&传奇&&,&&则谣传与外G分成. 这段时间乃是外G的黄金期.但是从某外G的作者被判刑后外G似乎一下子收敛了很多. 但是实际的情况呢?
& 到了如今&免费游戏&大行其道,而且虚拟物品交易越来越成熟的今天,外G这东西一下被各运营商列为了头号打击对象.为何运营商一下积极了那么多?原因很简单: 假设运营商出售某虚拟道具价值10元,这道具是消耗品,而且每个玩家都需要. 如果某外G提供一样的功能.你说运营商要损失多少? 又假设运营商提供个途径获得某道具需要玩家花费100元.但是为了保留不花钱的玩家好让花钱的玩家去折腾,总不可能不让游戏里出吧.即使几率再低也挡不住机器人24小时不停的折腾然后拿到5173之类的地方挂个50元卖. 这又损失多少?于是呼,游戏内游戏外.网上现实中. 打击外G成了运营商们的头号大事.
& 外G怎么办? 写挂赚钱的又怎么办? [- 好吧.老哥我承认老哥我也是外G作者大军中的一员. 而且很早就开始从事这一行业.&似乎外G一夜间就混不下去了... 这就错了. 在虚拟物品交易广为人知的如今. 既然游戏运营可以换种模式赚更多的钱!外G为什么不可以?
& 如今的外G模式是怎么样的? 以某人为例子, 某人为三个工作室专门提供外G的更新与制作,一个游戏一个月收维护费x元.而工作室则24小时挂机器人打宝,打钱然后出售.单单这三家工作室便有超过500台机机器在从事光荣的任务.运营商会损失多少的利益? 而且以前那套对付外G的办法还拿工作室没奈何.
& 于是呼又诞生了一种职称: 网络游戏反外G工程师.
& 但是目前从事这一职业者多半是软件安全出身. 绝大多数没有开发过外G. -- 你都不知道别人怎么攻击,何谈有效的防御呢?这便是老哥我写此文的原因.
& 驱动反外G - 看起来很美
一. 论反外G驱动& 随着国内软件安全行业的发展,驱动这一名词逐渐被摘去神秘的光环. 而3721的出现,告诉了人们驱动这东西不仅仅是用于硬件越来越多的人认识到驱动的巨大作用,当&&引入了 nProtect 反外G系统后,似乎驱动反外G成了相当理想的选择.
& 但这一切,只是看起来很美. 随着越来越多的ROOTKIT出现,各大杀毒厂商逐渐的加强了这一方面的监控. 越来越多的各类监控软件也使得驱动反外G举步维难.
& 在进入正题之前,首先要明确一点. 你的驱动将是游戏客户端的组成部分, 很多ROOTKIT上可以用的手段你不能使用.游戏玩家并不是专业人士,他们更相信他们所选择的杀毒软件. 总不能当你的游戏运行时,杀毒软件便提示说 - 这是个ROOTKIT
& 首先老哥我们抛开驱动的兼容性不谈 - 这也没法谈, 正如你驾驶汽车,你可以保证自己不出错. 但是你能保证其他人都能吗?说到驱动反外G,你应该立马想到 HOOK SSDT与SSSDT 拦截API防止游戏进程被修改. 可是这真的那么有效吗?&& 好,你想说阻止 OpenProcess,ReadProcessMemory,WriteProcessMemory 这三个API就好? 不 - 相信老哥我,这只能防防菜鸟而已.即使你不考虑兼容性把 PsLookupProcessByProcessId,ObOpenObjectByPointer,ObOpenObjectByName,KeAttachProcess 等全HOOK,真的就能阻止修改了吗?
& 不,老哥我们来看看下面的代码.
Function GetInfoTable(ATableType:dword):PvarmSize:mPtr:St: NTSbeginResult :=mSize := $4000;repeat&& mPtr := VirtualAlloc(nil, mSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);&& if mPtr = nil then E&& St := ZwQuerySystemInformation(ATableType, mPtr, mSize, nil);&& if St = STATUS_INFO_LENGTH_MISMATCH then&&&&& begin&&&&&&& VirtualFree(mPtr, 0, MEM_RELEASE);&&&&&&& mSize := mSize * 2;&&&&&until St && STATUS_INFO_LENGTH_MISMATCH;if St = STATUS_SUCCESS&& then Result := mPtr&& else VirtualFree(mPtr, 0, MEM_RELEASE);
function iOpenProcess(ProcessId:DWORD):DWORD;var&&&&&&& HandlesInfo: PSYSTEM_HANDLE_INFORMATION_EX;&&&&&&& ClientID:TClientID;&&&&&&& pbi:_PROCESS_BASIC_INFORMATION;&&&&&&& oa:TObjectA&&&&&&& hProcessCur,hProcessToDup,hProcessToRet:DWORD;&&&&&&& Ret:DWORD;&&&&&&& I:Ibegin&&&&&&& SetPrivilege('SE_DEBUG',TRUE);&&&&&&& Result:=0;&&&&&&& FillChar(oa,SizeOf(TObjectAttributes),0);&&&&&&& FillChar(ClientID,SizeOf(TClientID),0);&&&&&&& oa.Length:=SizeOf(TObjectAttributes);
&&&&&&& HandlesInfo:=GetInfoTable(SystemHandleInformation);
&&&&&&& for I:=0 to HandlesInfo^.NumberOfHandles do&&&&&&& begin&&&&&&&&&&&&&&& If (HandlesInfo^.Information.ObjectTypeNumber=5) Then //OB_TYPE_PROCESS&&&&&&&&&&&&&&&&&&&&&&& ClientID.UniqueProcess:=HandlesInfo^.Information.ProcessId;&&&&&&&&&&&&&&&&&&&&&&& If ZwDuplicateObject(hProcessToDup,HandlesInfo^.Information.Handle,GetCurrentProcess,@hProcessCur,PROCES
S_ALL_ACCESS,0,$4)=STATUS_SUCCESS then& If ZwQueryInformationProcess(hProcessCur,ProcessBasicInformation,@pbi,Sizeof(_PROCESS_BASIC_INFORMATION),@Ret)=STATUS_SUCCESS then&&&&&&&&& If (pbi.UniqueProcessId=ProcessId) Then&&&&&&&&&&&&&&&&& If ZwDuplicateObject(hProcessToDup,HandlesInfo^.Information.Handle,GetCurrentProcess,@hProcessToRet,P
ROCESS_ALL_ACCESS,0,$4)=STATUS_SUCCESS then&&&&&&&&&&&&&&&&& begin&& Result:=hProcessToR&& B&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& if hProcessCur&0 then ZwClose(hProcessCur);&&&&&&& if hProcessToDup&0 then ZwClose(hProcessToDup);&&&&&&& VirtualFree(HandlesInfo,0,MEM_RELEASE);&&&&&&& SetPrivilege('SE_DEBUG',FALSE);
& 枚举系统中所有已知举柄达到取得进程Handle的函数. 你或许会认为,拦截ZwDuplicateObject,ZwQueryInformationProcess不就解决问题了?& 这没错,你是对的.但是你不能这样做,你做的是反外G,不是ROOTKIT, 当你尝试这样做的时候,你会发现你的杀毒软件提示你. 这是ROOTKIT的典型行为怎么办? 难道你要象ROOTKIT那样关闭掉玩家的杀毒软件? 还是联系各大杀毒软件厂商告诉他们: 麻烦您修改你们的规则?
& 仅仅是RING 3的普通运用而已, 千万不要认为做外G的不会驱动. 相反,与游戏开发公司那点可怜的薪水比起来. 外G的利润只会让更多的驱动开发者加入这一行列. 即使你HOOK接管了这一切函数,不管是inline还是普通的ssdt. 下面的驱动轻易的就能突破任意的HOOK.
NTSTATUS NTAPI GetRealAddress(PIMPORT_ENTRY Import){&&&&&&& MODULE_INFORMATION mi,&&&&&&& DWORD&&&&&&& i,j;&&&&&&& DWORD&&&&&&& dwKernelB&&&&&&& NTSTATUS&&&&&&&&&&&&&& PDWORD&&&&&&& KiServiceT&&&&&&& UNICODE_STRING NtdllN
if (KeGetCurrentIrql()!=PASSIVE_LEVEL) return STATUS_PASSIVE_LEVEL_REQUIRED;
RtlZeroMemory(&mi,sizeof(mi));if (!NT_SUCCESS(status=MapKernelImage(&mi,&dwKernelBase)))
RtlZeroMemory(&idmi,sizeof(idmi));RtlInitUnicodeString(&NtdllName, L"\\SystemRoot\\System32\\ntdll.dll");&&&&&&&&&&&&&& if (!NT_SUCCESS(status=MapPeImage(&idmi,&NtdllName)))
try {&&&&&&&&&&&&&&& for (i=0;Import.szNi++){&&&&&&&&&&&&&&&&&&&&&&& Import.dwAddress=0;&&&&&&&&&&&&&&&&&&&&&&& switch (Import.dwType) {& case IMPORT_BY_NAME:&&&&&&&&& if (!(Import.dwAddress=GetProcRva(mi.hModule,Import.szName))) {#ifdef DEBUG&&&&&&&&&&&&&&&&& DbgPrint("GetRealAddress(): Failed to get %s rva!\n",Import.szName);#endif&&&&&&&&& }&&&&&&&&&& case IMPORT_BY_RVA:&&&&&&&&& Import.dwAddress=(DWORD)Import.szN&&&&&&&&&& case IMPORT_BY_ADDRESS:&&&&&&&&& Import.dwAddress=(DWORD)Import.szName-dwKernelB&&&&&&&&&& case IMPORT_BY_SERVICE_ID:&&&&&&&&& // do not search this rva if it has been already found&&&&&&&&& if (!KiServiceTable_RVA) {&&&&&&&&&&&&&&&&& if (!(KiServiceTable_RVA=FindKiServiceTable(mi.hModule))) {#ifdef DEBUG&& DbgPrint("GetRealAddress(): Failed to get KiServiceTable RVA!\n");#endif&&&&&&&&&&&&&&&&&&& }&&&&&&&&& }&&&&&&&&& KiServiceTable=(PDWORD)(KiServiceTable_RVA+mi.hModule);&&&&&&&&& Import.dwAddress=KiServiceTable[(DWORD)Import.szName]-mi.dwImageB&&&&&&&&&& case IMPORT_BY_SERVICE_NAME:&&&&&&&&& if (!KiServiceTable_RVA){&&&&&&&&& if (!(KiServiceTable_RVA=FindKiServiceTable(mi.hModule)))&&&&&&& &&&&&&&&& }&&&&&&&&& Import.dwId=GetIdForName(idmi.hModule,Import.szName);&&&&&&&&& KiServiceTable=(PDWORD)(KiServiceTable_RVA+mi.hModule);&&&&&&&&& Import.dwAddress=KiServiceTable[Import.dwId]-mi.dwImageB&&&&&&&&&& default:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& } //Case End
if (Import.dwId==0){if (!KiServiceTable_RVA)KiServiceTable_RVA=FindKiServiceTable(mi.hModule);KiServiceTable=(PDWORD)(KiServiceTable_RVA+mi.hModule);for (j=0;KiServiceTable[j];j++){if (Import.dwAddress==KiServiceTable[j]-mi.dwImageBase){Import.dwId=j;}}&&&&&& }Import.dwAddress=dwKernelBase+Import.dwA}}except(EXCEPTION_EXECUTE_HANDLER){return STATUS_ADD_FUNCTION_FAILED;}
try {UnmapPeImage(&mi);UnmapPeImage(&idmi);}except(EXCEPTION_EXECUTE_HANDLER){return STATUS_CODE_REBUILDING_FAILED;}
return STATUS_SUCCESS;}&
& 面对任何HOOK,只需要从NT的内核文件中取出其真实的地址,很轻易的就可以饶过SSDT的HOOK,INLINE HOOK只需要恢复代码即可.& 更何况你的驱动肯定会比外G的驱动还晚加载.即使除开上面这些不谈,你依然要面对你的驱动被PATCH,或者被个假冒的驱动所替代. 更别说 lpk.dll usp10.dll 了.
& 这时你应该会想反驳老哥我,看看 nPROTECT ,安博士 吧. 好的,那么老哥我们来看看下面这段函数.
NTSTATUS ReadPhysicalMemory(char *startaddress, UINT_PTR bytestoread, void *output){&&&&&&& HANDLE&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& UNICODE_STRING&&&&&&& physmemS&&&&&&& OBJECT_ATTRIBUTES&&&&&&& WCHAR&&&&&&&&&&&&&&&&&&&&&&& physmemName[] = L"\\device\\physicalmemory";&&&&&&& UCHAR*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& NTSTATUS&&&&&&&&&&&&&&& ntStatus = STATUS_UNSUCCESSFUL;
&&&&&&& __try&&&&&&& {&&&&&&&&&&&&&&& RtlInitUnicodeString( &physmemString, physmemName );&&&&&&
&&&&&&&&&&&&&&& InitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );&&&&&& &&&&&&&&&&&&&&& ntStatus=ZwOpenSection( &physmem, SECTION_MAP_READ, &attributes );&&&&&&&&&&&&&&& if (ntStatus==STATUS_SUCCESS)&&&&&&&&&&&&&&& {&&&&&&&&&&&&&&&&&&&&&&& //hey look, it didn't kill it
&&&&&&&&&&&&&&&&&&&&&&& UINT_PTR&&&&&&&&&&&&&&&&&&&&&&& PHYSICAL_ADDRESS&&&&&&& viewB&&&&&&&&&&&&&&&&&&&&&&& UINT_PTR&&&&&&&&&&&&&&&&&&&&&&& UINT_PTR
&&&&&&&&&&&&&&&&&&&&&&& viewBase.QuadPart = (ULONGLONG)(startaddress);&&&&&&&& &&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&& length=0x2000;//pinp-& //in case ofa overlapping region&&&&&&&&&&&&&&&&&&&&&&& toread=
&&&&&&&&&&&&&&&&&&&&&&& memoryview=NULL;
&&&&&&&&&&&&&&&&&&&&&&& DbgPrint("ReadPhysicalMemory:viewBase.QuadPart=%x", viewBase.QuadPart);
&&&&&&&&&&&&&&&&&&&&&&& ntStatus=ZwMapViewOfSection(& physmem,& //sectionhandle& NtCurrentProcess(), //processhandle (should be -1)& &memoryview, //BaseAddress& 0L, //ZeroBits& length, //CommitSize& &viewBase, //SectionOffset& &length, //ViewSize& ViewShare,& 0,& PAGE_READWRITE);
&&&&&&&&&&&&&&&&&&&&&&& if (ntStatus==STATUS_SUCCESS)&&&&&&&&&&&&&&&&&&&&&&& {& offset=(UINT_PTR)(startaddress)-(UINT_PTR)viewBase.QuadP& RtlCopyMemory(output,&memoryview[offset],toread);
& ZwUnmapViewOfSection( NtCurrentProcess(), memoryview);&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&& else&&&&&&&&&&&&&&&&&&&&&&& {& DbgPrint("ReadPhysicalMemory:ntStatus=%x", ntStatus);&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&& ZwClose(physmem);&&&&&&&&&&&&&&& };
&&&&&&& }&&&&&&& __except(1)&&&&&&& {&&&&&&&&&&&&&&& DbgPrint("Error while reading physical memory\n");&&&&&&& }
&&&&&&& return ntS}
& 直接读取物理内存, 到目前为止,这个方法依然对 nPROTECT 保护的进程有效.
& 实际上反外G驱动能拦截的不过是API而已, 你能拦截 mov eax,[xxxxxxx] 吗?& 别忘记,你在驱动中采取的手段越多,驱动的兼容性必定越差. 在家中的玩家还好说,可是面对目前主要的玩家多数在网吧上网的情况,你不的不考虑各种网吧管理软件.& 这样的情况,不谈兼容性光是你的驱动到底有没有机会被加载还是个问题.即使是在家中上网的玩家,你难道要告诉使用 Vista 或者 Windows 7 的普通用户: 请关闭你的UAC
& 好吧,这样写下去简直没完没了.& 综上所述, 反外G驱动, 这只是看起来很美而已.
& 怎么办??
& 二. 如何有效的阻止外G& 前言中提到,要有效的反外G,必先了解外G如何运作.& 在前文中,也描述了当前外G主要的运作模式. 现在外G已不是要求什么三步瞬移,格位刺杀之类的特殊功能了,对于工作室.&& 他们的需要仅仅是稳定的机器人,如果游戏提供的话,他们常常还需要能够把挂机角色上的金钱物品邮寄或者交易给某个账号的功能. 那么制作一个这样的机器人至少需要的是什么?& 1. 游戏角色的生命值,魔法值之类的数据& 2. 游戏角色的物品数据& 3. 游戏角色周围的怪物数据& 4. 移动函数& 5. 热键函数 [假如客户端接受 SendMessage 模拟键盘这样的消息,这不需要]& 6. 选中怪物函数& 7. 打开NPC函数& 8. 打开仓库函数& 9. 交易或邮寄函数& 其中 4-9 可以被一个数据包发送函数所替代,例如:
procedure SendPack(buf:PClen:DWORD);
procedure TOSEND;asmpush&&& -1push&&& SENDPACK_STAKmov&&&& eax, dword ptr fs:[0]push&&& eaxmov&&&& dword ptr fs:[0], espsub&&&& esp,$18push&&& ebxpush&&& esipush&&& edimov&&&& edi, ecxxor&&&& ebx, ebxxor&&&& eax, eaxjmp&&&& SENDPACK_JMP
beginasmmov& ecx, [CALL_BASE];mov& ecx, [ecx+$20];call TOSEND;
procedure SendBuyItem(ItemId,ItemPos,ItemCount:DWORD);var//25 00 01 00 00 00 14 00 00 00 00 00 00 00 01 00 00 00 AA 21 00 00 01 00 00 00 01 00 00 00//25 00 01 00 00 00 ByteCount 00 00 00 00 GroupCount ItemId ItemPosItemCountPack:Array [0..29] of BbeginFillChar(Pack,SizeOf(Pack),0);Pack[0]:=$25;Pack[2]:=$01;Pack[6]:=$14;Pack[14]:=$01;CopyMemory(@Pack[18],@ItemId,4);CopyMemory(@Pack[22],@ItemPos,4);CopyMemory(@Pack[26],@ItemCount,4);SendPack(@Pack[0],30);
& 归根结底, 要反外G,主要防御的只有两点:& 1. 防止外部修改内存& 2. 防止外部调用函数
& 对于第一点,比如修改某个怪物的数据,使得客户端判断该怪物在游戏角色的攻击范围之内.& 最佳的解决办法不是去HOOK什么内存读写函数. 而是把判断这些数据的责任交给服务器端.& 可如果是引进的游戏呢? 解决办法便是CRC32或者别的什么HASH算法校验这段内存数据.
& 对于第二点,最简单的办法便是在函数内取得 ESP 判断函数的返回地址.以上面的那段函数为例. 只要游戏开发商稍微更改一下他的发包函数,判断下call 的来源, 老哥我想这已经会让外G的作者头痛很久.
& 实质上反外G是否有效最大的前提,在于不能让反外G机制被饶过. 仅仅是单纯的客户端保护,作用非常有限.& 对于没有代码的情况下,比较简单的解决办法:& 1. 客户端反外GDLL中 HOOK connect,recv,send. 在 connect 时使其连接到反外G服务器端.保留connect所使用的socket, 在recv , send 中判断该socket对数据进行二次加密/解密
& 2. 反外G服务器端监控客户端的情况,如有异常则中断用户数据的转发.
& 下面以国内完美公司的游戏,&&完美世界&&作为改造对象.以自调试做为手段为elementclient.exe增加一个对抗外部调用的方法.
& 老哥我们先来看看&&完美世界&&的发包函数:
005B7BD0& /$& 6A FF&&&&&&&& push -1005B7BD2& |.& 68 68A68800&& push 005B7BD7& |.& 64:A1 0000000&mov eax, dword ptr fs:[0]005B7BDD& |.& 50&&&&&&&&&&& push eax005B7BDE& |.& 64:&mov dword ptr fs:[0], esp005B7BE5& |.& 83EC 18&&&&&& sub esp, 18005B7BE8& |.& 53&&&&&&&&&&& push ebx005B7BE9& |.& 56&&&&&&&&&&& push esi005B7BEA& |.& 57&&&&&&&&&&& push edi005B7BEB& |.& 8BF9&&&&&&&&& mov edi, ecx005B7BED& |.& 6A 07&&&&&&&& push 7&&&& ; /Arg1 = 005B7BEF& |.& E8 FC390D00&& call &&&&&&&&&&&&&&&&&&&&&&&&&&& ; \elementc.005B7BF4& |.& 33DB&&&&&&&&& xor ebx, ebx005B7BF6& |.& 33C0&&&&&&&&& xor eax, eax005B7BF8& |.& 83C4 04&&&&&& add esp, 4005B7BFB& |.& &&&& mov dword ptr [esp+18], eax005B7BFF& |.& 895C24 1C&&&& mov dword ptr [esp+1C], ebx005B7C03& |.& 895C24 20&&&& mov dword ptr [esp+20], ebx005B7C07& |.& C&mov dword ptr [esp+14], 008A6C08005B7C0F& |.& C3&mov dword ptr [esp+C], 008B3818005B7C17& |.& C&mov dword ptr [esp+10], 22005B7C1F& |.& 8B7424 38&&&& mov esi, dword ptr [esp+38]005B7C23& |.& 895C24 2C&&&& mov dword ptr [esp+2C], ebx005B7C27& |.& 3BF3&&&&&&&&& cmp esi, ebx005B7C29& |.& 76 2D&&&&&&&& jbe short 005B7C58005B7C2B& |.& 8D46 FF&&&&&& lea eax, dword ptr [esi-1]005B7C2E& |.& B9 && mov ecx, 2005B7C33& |.& D1E8&&&&&&&&& shr eax, 1005B7C35& |.& 894C24 20&&&& mov dword ptr [esp+20], ecx005B7C39& |.& 74 0A&&&&&&&& je short 005B7C45005B7C3B& |&& D1E1&&&&&&&&& /shl ecx, 1005B7C3D& |.& D1E8&&&&&&&&& |shr eax, 1005B7C3F& |.^ 75 FA&&&&&&&& \jnz short 005B7C3B005B7C41& |.& 894C24 20&&&& mov dword ptr [esp+20], ecx005B7C45& |&& 51&&&&&&&&&&& push ecx&& ; /size005B7C46& |.& 53&&&&&&&&&&& push ebx&& ; |block005B7C47& |.& FF15 6C548A00 call dword ptr [&&MSVCRT.realloc&]&&&&&&; \realloc005B7C4D& |.& 83C4 08&&&&&& add esp, 8005B7C50& |.& &&&& mov dword ptr [esp+18], eax005B7C54& |.& C&&&& mov dword ptr [esp+1C], eax005B7C58& |&& 8B4C24 34&&&& mov ecx, dword ptr [esp+34]005B7C5C& |.& 56&&&&&&&&&&& push esi&& ; /n005B7C5D& |.& 51&&&&&&&&&&& push ecx&& ; |src005B7C5E& |.& 50&&&&&&&&&&& push eax&& ; |dest005B7C5F& |.& FF15 44548A00 call dword ptr [&&MSVCRT.memmove&]&&&&&& ; \memmove005B7C65& |.& 8B5424 24&&&& mov edx, dword ptr [esp+24]005B7C69& |.& 83C4 0C&&&&&& add esp, 0C005B7C6C& |.& 8D4424 0C&&&& lea eax, dword ptr [esp+C]005B7C70& |.& 03D6&&&&&&&&& add edx, esi005B7C72& |.& 53&&&&&&&&&&& push ebx005B7C73& |.& 50&&&&&&&&&&& push eax005B7C74& |.& 8BCF&&&&&&&&& mov ecx, edi005B7C76& |.& &&&& mov dword ptr [esp+24], edx005B7C7A& |.& E8 B1DAFFFF&& call 005B5730005B7C7F& |.& 8B4C24 18&&&& mov ecx, dword ptr [esp+18]005B7C83& |.& 8AD8&&&&&&&&& mov bl, al005B7C85& |.& 51&&&&&&&&&&& push ecx&& ; /block005B7C86& |.& C&mov dword ptr [esp+18], 008A6C08&&&&&&&& ; |005B7C8E& |.& FF15 68548A00 call dword ptr [&&MSVCRT.free&]&&&&&&&&& ; \free005B7C94& |.& 8B4C24 28&&&& mov ecx, dword ptr [esp+28]005B7C98& |.& 83C4 04&&&&&& add esp, 4005B7C9B& |.& 8AC3&&&&&&&&& mov al, bl005B7C9D& |.& 64:890D 00000&mov dword ptr fs:[0], ecx005B7CA4& |.& 5F&&&&&&&&&&& pop edi005B7CA5& |.& 5E&&&&&&&&&&& pop esi005B7CA6& |.& 5B&&&&&&&&&&& pop ebx005B7CA7& |.& 83C4 24&&&&&& add esp, 24005B7CAA& \.& C2 0800&&&&&& ret 8
& 对比上面的发包CALL的例子,可以发现 005B7BD0 - 005B7BF6 均由外G完成, 而达到绕过 005B7BEF call
& 那么在这里,挑选 005B7BF8& |.& 83C4 04&&&&&& add esp, 4 作为监控点.& 这个例子中,首先老哥我们修改 elementclient.exe 文件, 将 005B7BF8 处的代码改为 CC 90 90. 方便写老哥我们的调试器代码
& 接下来老哥我们看看老哥我们将用于防止外部调用的调试器部分:
program AntiC{$APPTYPE CONSOLE}uses Windows,SConstWINDOW_TITLE='Element Client';WINDOW_CLASS='ElementClient Window';THREAD_ALL_ACCESS=STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $3FF;CHECKPOINT_ADDR=$005B7BF8;
function OpenThread(dwDesiredAccess:DWORD;bInheritHandle:BdwThreadId:DWORD):THANDLE; stdcall external kernel32 name 'OpenThread';
procedure MainLvar& hW2iThread,hW2iProcess,dwW2iThreadId,dwW2iProcessId,hW2iWnd:DWORD;
& DebugEv:DEBUG_EVENT;& Regs:CONTEXT;& dwContinueStatus,WorkBytes,dwCallRet:DWORD;
& fp:TH& hThread:DWORD;begin& FillChar(Regs,SizeOf(CONTEXT),0);& dwW2iThreadId:=0;& dwW2iProcessId:=0;& hW2iProcess:=0;& hW2iThread:=0;& fp:=0;
&&&&&&& hW2iWnd:=FindWindow(WINDOW_CLASS, nil);&&&&&&& if( hW2iWnd&0) then dwW2iThreadId:=GetWindowThreadProcessId(hW2iWnd,@dwW2iProcessId);& if (dwW2iProcessId&0) then hW2iProcess:=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwW2iProcessId);& if (hW2iProcess&0) then hW2iThread:=OpenThread(THREAD_ALL_ACCESS, FALSE, dwW2iThreadId);&& if (hW2iThread&0) then& if DebugActiveProcess(dwW2iProcessId) then& begin&&&&&&&&&&&&&&& while(TRUE) do&&&&&&&&&&&&&&& begin&&&&&&&&&&&&&&&&&&&&&&& if (WaitForDebugEvent(DebugEv,10)) then&&&&&&&&&&&&&&&&&&&&&&& begin& dwContinueStatus:=DBG_EXCEPTION_NOT_HANDLED;
& Case DebugEv.dwDebugEventCode of
&&& EXCEPTION_DEBUG_EVENT:&&&&&&&&& begin&&&&&&&&&&&&&&&&& if(DWORD(DebugEv.Exception.ExceptionRecord.ExceptionAddress)=CHECKPOINT_ADDR) then&&&&&&&&&&&&&&&&& begin&& hThread:=OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEv.dwThreadId);&& SuspendThread(hThread);
&& Regs.ContextFlags:=CONTEXT_FULL;&& GetThreadContext(hThread,Regs);
&& ReadProcessMemory(hW2iProcess,Pointer(Regs.esp),@dwCallRet,4,WorkBytes);
&& //非常简单的判断, 应该为枚举代码段地址,或者对每个正常的调用地址作判断&& if dwCallRet&$00A87000 then&& begin&&&&&&&&&& WriteLn('发现外部调用!');&&&&&&&&&& // 随便做点什么吧&& end else begin&&&&&&&&&& Regs.Esp:=Regs.Esp+$c; // add esp,0c&&&&&&&&&& SetThreadContext(hThread,Regs);&&&& ResumeThread(hThread);&& CloseHandle(hThread);&&&&&&&&&&&& &nbs,&&&
&&&&&&&&&&&&&&&&& dwContinueStatus:=DBG_CONTINUE;&&&&&&&&&
&&&&&&&&& EXIT_PROCESS_DEBUG_EVENT:&&&&&&&&& begin&&&&&&&&&&&&&&&&& ExitProcess(0);&&&&&&&&&&&&&&&&& &
& ContinueDebugEvent(DebugEv.dwProcessId, DebugEv.dwThreadId,dwContinueStatus);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& end&&& else WriteLn('附加到进程失败!');
& WriteLn;&&&&&&& WriteLn('按下回车键退出!');& ReadLn;&&&&&&& ExitProcess(0);
beginMainLend.
&& C++ 版本如下:
// cl AntiCall.cpp /link user32.lib
#include#include
#define W2I_WINDOW_TITLE TEXT("Element Client")#define W2I_WINDOW_CLASS TEXT("ElementClient Window")#define CHECKPOINT_ADDR&&&&& 0x005B7BF8
int main(int argc, char* argv[]){&&&&&&& HANDLE hW2iT&&&&&&& HANDLE hW2iP&&&&&&& DWORD dwW2iThreadId;&&&&&&& DWORD dwW2iProcessId;&&&&&&& HWND hW2iW&&&&&&& DWORD dwCallR
&&&&&&& hW2iWnd = ::FindWindow(W2I_WINDOW_CLASS, W2I_WINDOW_TITLE);
&&&&&&& if( hW2iWnd&0 && ( dwW2iThreadId = ::GetWindowThreadProcessId(hW2iWnd, &dwW2iProcessId) )&&&&&&&&&&&&&&& && dwW2iProcessId && ( hW2iProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwW2iProcessId) )&&&&&&&&&&&&&&& && ( hW2iThread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, dwW2iThreadId) ) && DebugActiveProcess(dwW2iProcessId) )&&&&&&& {&&&&&&&&&&&&&&& DEBUG_EVENT DebugEv;&&&&&&&&&&&&&&& DWORD dwContinueS
&&&&&&&&&&&&&&& while(TRUE)&&&&&&&&&&&&&&& {&&&&&&&&&&&&&&&&&&&&&&& if(WaitForDebugEvent(&DebugEv, 10))&&&&&&&&&&&&&&&&&&&&&&& {& dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
& switch(DebugEv.dwDebugEventCode)& {& case EXCEPTION_DEBUG_EVENT:&&&&&&&&& {&&&&&&&&&&&&&&&&& if((DWORD)DebugEv.u.Exception.ExceptionRecord.ExceptionAddress==CHECKPOINT_ADDR)&&&&&&&&&&&&&&&&& {&& HANDLE hThread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEv.dwThreadId);&& SuspendThread(hThread);
&&&&&&&&&&&&&&&&&&&&&&& &,&&&&&&&&&&&& &,&&&&&&&&&&&&&&&& CONTEXT Regs = {0};&& Regs.ContextFlags = CONTEXT_FULL;&& ::GetThreadContext(hThread, &Regs);
&& ReadProcessMemory(hW2iProcess, (void*)Regs.Esp, &dwCallRet, 4, &len)&& //非常简单的判断, 应该为枚举代码段地址,或者对每个正常的调用地址作判断&& if(dwCallRet&0x00A87000)&& {&&&&&&&&&& printf("发现外部调用.\n\n");&&&&&&&&&& // 随便做点什么吧&& }else{&&&&&&&&&& Regs.Esp += 0 // add esp,0c&&&&&&&&&& ::SetThreadContext(hThread, &Regs);&& }&& ResumeThread(hThread);&& CloseHandle(hThread);&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&& dwContinueStatus = DBG_CONTINUE;&&&&&&&&&&&&&&&&&&&&&&&&&& }
& case EXIT_PROCESS_DEBUG_EVENT:&&&&&&&&& {&&&&&&&&&&&&&&&&& return 0;&&&&&&&&&&&&&&&&&&&&&&&&&& }& }
& ContinueDebugEvent(DebugEv.dwProcessId, DebugEv.dwThreadId, dwContinueStatus);&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&& }&&&&&&& }&&&&&&& else&&&&&&& {&&&&&&&&&&&&&&& printf("附加到进程失败!\n\n");&&&&&&& }&&&&&&& printf("按任意键退出!\n");&&&&&&& getchar();
&&&&&&& return 0;}
& 上面的代码仅仅是非常简单的判断call的来源.只有一个判断点,而且是个INT 3.
& 在实际运用中,增加多个判断点. 动态生成各种不易被发现的异常. 让反外G与与客户更加紧密的结合. 并且采用上文提到的反外G服务器端校验模式.例如盛大SD的 RODynDll.dll 以及其生成的 DynTmp0.dat
& 本文就此结束,虽然还有更多的方法对抗外部调用,内存修改. 但是在外G已不再是可以随便得到样本加以分析的时候.了解外G制作所需再加以反制, 是每个从事游戏安全工作者应该具备的基本素质.
& 正如标题开头的那句:& 道高一尺魔高一丈.
(以上文章摘自网络,若有冒犯请来信告知,本站1日内删除,)
精湛架设唯一网站:
精湛架设版权所有 CopyRight

我要回帖

更多关于 谁都可以创造奇迹 的文章

 

随机推荐