外挂学习之路(1)--- bp send 回溯寻找关键call

先废话一下----好久没有更新博客了,更新一下。学习外挂也有几年时间了,零零散散没有学习到什么东西,更没有做出什么有用的项目,也没有什么总结文档,从头再来吧,人不立志难以成事。

以下文字都是自己的感悟,不是什么正规文档,写给自己总结看看,如有高人看到错误之处希望不吝赐教。

外挂主要有模拟挂,内存挂,脱机挂。模拟挂一般指模拟点击代替反复的人工操作,内存挂一般是指先找到关键call,然后写个dll注入到游戏里面,脱机则稍微复杂一点,需要先分析游戏里面的协议,自己写个游戏客户端冒充游戏客户端,完成所有游戏功能,既然游戏是自己写的就可以随便diy。模拟挂较为简单(不考虑驱动保护),脱机挂较为高大上,先以内存挂为主进行学习。

内存挂主要工作是找call,找到关键call之后就是自己写段汇编代码调用该call以达到外挂的目的。当然在这之前要写好dll以及注射器,常见的注射方式是全局钩子hook到游戏进程和远程线程注入,这两个方式的具体代码以后再做讨论。再来说说各种各样的找call方法,今天先说一种通过网络发包下断点回溯的方法,在od命令框里面输入 bp send或者bp wsasend.(根据游戏具体使用的函数而定),然后对游戏进行操作如捡物、嗑药、打怪等,客户端肯定要向服务器发送数据包,断点断住之后层层向上回溯,直到执行指定操作会断其他与服务器的交互不会中断,比如寻找捡物call时捡物会断而走路不断此时断点一般就是所搜寻的断点。

好了暂时先写这么多吧,后续有收获就继续更新。。。

近期研究一个游戏无法用上述方法追踪到关键call,分析其原因如下:

上述方案适用于手工触发之后游戏直接调用send函数向外发包,但是好一点的游戏发包都有自己的发包队列,防止发包失败,向外发包时候先把数据投放到一个队列里面 ,然后写个线程不断的读取队列里面的内容,一有内容立即向外发送,即发包过程和手工触发过程在两个不同的线程里面,这样通过send函数回溯call的时候最多可以回溯到那个循环发包的任务里面,无法找到真正的触发任务的call。

----------再次更新---------

经过再次思考,估计大部分游戏都有自己的发包队列,但是bp send找call为什么还是那么流行呢?

其实找到的call不一定对应原生的激发动作函数,只要找到这个激发动作向服务器发送了什么样的数据包就可以了,这样想想bp send 找call的方法又可以通用了,无论是否有发包队列,你咋发我就写挂也咋发就可以了。

但是这样一来就和一般辅助教程有一点冲了,冲突如下:

写一点伪代码,有发送队列的网络模型如下

void 打坐函数()//以游戏中的打坐技能为例
{
     将打坐要发的数据包加入到发送队列里面
}

//发包线程
void sendpackthread()
{
    while(true)
    {

         //检测发送数据包的队列
         
         //发送数据包函数
         sendpack(...);
    }
}

//真实的发包流程
void sendpack(...)
{
     //数据加密和压缩处理
     
     //调用系统API
     send();
}

按照这个模型理解的话,所有动作都是调用sendpack函数发送的,外挂call的也是sendpack,这就和一般教程中的打坐call走路的时候不会中断有冲突,有时间继续研究....


=============================================================================================

每每在其他技术论坛一提到广海大家就会取笑我:“广海呀,就是那些只会BP SEND 和CTRL+F9 的那些人啊”,听到这样的嘲笑起初自己也十分瞧不起BP SEND有段时间甚至刻意避免使用这个断点。其实不是人家的错,是我们自己将BP SEND这把利器用死了,学东西把东西学死了是非常大的悲哀,我们要用聪明智慧来展示出自己的实力,实力可以攻破任何谣言。 

诚然BP SEND在网游发展的初期是一把无往而不利的万能断点,因为客户端总要跟服务器通讯,所以一有动作就会断下来。而现今网游开发人员都有防范外挂的意识和手段,在他们的作品中自然对于大家手中的这个BP SEND会使出各种手段加以遏制。 

举个简单的例子,星尘传说 这是我第一个研究的游戏 他就专门针对BP SEND做了很好的处理,专门做了一个负责发包的模块,通过消息和事件跟主体程序进行通讯,我们的单步跟踪自然无法跟随消息追随到功能CALL,无数次的CTRL+F9都只能深陷在一个无尽的消息等待循环中。还有些强力的游戏制作者,自己编写WS2_32.DLL,用于网络通信,我们还傻乎乎的去截取系统API自然是一无所获。还有些开发商会HOOK WS2_32.DLL,监测用户的动作,触发了它的规则轻则掉线,重则封号。 

游戏在进步,而我们只知道 BP SEND + CTRL+F9 可想而知,太公钓鱼。 

我们先讲如何穿透消息封锁的BP SEND 
原理:虽然消息和事件可以阻挡我们对代码的回溯跟踪,但是作为程序运行的忠实记录者 “堆栈”却将程序运行的关键步骤都记录下来了。然而,堆栈中并不会记录所有的CALL调用。示意图: 

模块1: 游戏主体进程 
↓ 
模块2: CALL1(获取技能ID)→CALL2(获取角色ID)→CALL3(获取目标ID)→CALL4(错误检查)→压入技能ID参数 压入角色ID参数 压入目标ID参数→技能CALL5(id1,id2,id3)→CALL6(发送消息给发包等待模块) 


模块3:CALL7(消息等待模块) 
↓↑ 
send( ); 

这就是一个使用消息阻断BP SEND跟踪技能CALL的反调试手段,我们使用CTRL+F9无法跨越CALL6 和CALL 7 ,只能在 CALL7 和SEND()之间无限循环。 
而以上过程在堆栈中能在BP SEND断下时留下什么呢?答案是会留下CALL 6 CALL 7的踪影,我们并不会看到我们想要找到的技能CALL,会得到类似的堆栈内容: 

0012F07C 003AF1D5 返回到 Lua5.003AF1D5 来自 Lua5.0039AAD0 
0012F080 00000000 
0012F084 /0012F0A0 
0012F088 |77D1B6A3 返回到 USER32.77D1B6A3 来自 USER32.OffsetRect 
0012F08C |0012F1F8 
0012F090 |FFFFFFFC 
0012F094 |FFFFFFE9 
0012F098 |0012F174 
0012F09C |0D3A3000 
0012F0A0 ]0012F0B0 
0012F0A4 |77D1C1A2 返回到 USER32.77D1C1A2 来自 USER32.77D1C1AE 
0012F0A8 |00721B88 
0012F0AC |77F0ED36 返回到 GDI32.77F0ED36 
0012F0B0 \00000006 
0012F0B4 003AAEFE 返回到 Lua5.003AAEFE 来自 Lua5.003AAE90 
0012F0B8 1994BFB0 
0012F0BC 00000050 
0012F0C0 0347DC70 
0012F0C4 00000000 
0012F0C8 12630438 
0012F0CC 0012F0E8 
0012F0D0 /0012F0E8 
0012F0D4 |0039ABA7 返回到 Lua5.0039ABA7 来自 Lua5.003ADEC0 
0012F0D8 |12630438 

堆栈中记录的是模块与模块中相联系的CALL的返回地址,同时还会残留下来部分模块内部曾经压入到堆栈的对后面进程有用的参数。 

事有蹊跷,人有傻笨的,有聪明的,我们先讲体无脑方法: 
老天是公平的辅助辛勤的汗水总会有回报,在寻找CALL之前如果做足了准备工作的话,那一些基本的数据例如人物ID 技能ID 怪物ID这些通过看就能看出来大概是个什么样子,数据是几位,都什么开头,例如角色ID 23e7 怪物ID 4000329 技能ID 77512等等,有了这些辛勤的劳动成果,我们很容易在堆栈中发现他们,有这些数据传递的过程就是我们要找的地方,自然通过反复的跟踪测试我们能够找到最终想要的技能CALL,但是,事无绝对,如果你在堆栈中捕捉不到这些ID 的踪影那再辛苦的劳动也会徒劳一场。 


下面就介绍个简单易行的办法: 

我们都知道技能CALL释放的时候是有许多条件限制的,例如蓝是否足够,目标是否存在,是否有障碍等等,我们就抓住这里,进行展开。 

方法:使用内存搜索工具CE或者其他的可以搜索该游戏的工具对提示信息进行搜索,例如:“没有目标”,得到这些数据的存储地址,然后再OD或者其他调试器里,对该段内存下内存访问段,断下来之后,我们就会得到一个完整的堆栈内容,我们将所有的堆栈内容拷贝出来,存到一个文本文件里。 
然后,我们使用BP SEND下断,截获技能CALL释放的包,同样也会得到一个完整的堆栈数据,存 放到另一个文本文件里,我们对得到的2组 堆栈数据进行对比,从下向上,找到不同的地方就是你们该关注和下 手的地方了。至于BP SEND的一些技巧就不详细说了,多数都是使用条件断点来达到截取特定数据的。 

通过上面的“堆栈对比法”,我们就能找到合适的切入点,找到技能CALL,并且顺带将一些技能相关的错误处理CALL也给找到,什么CD冷却呀,障碍物啊等等。 

小结: 
上面通过很长篇幅来说明如何灵活应用BP SEND,也就是不能单纯的使用BP SEND,要和其他的一些断点和方法结合起来使用,才能达到理想的效果。在实际应用中我们还有更多这样的应用实例,大家也不要看完本文就心满意足,啊!我又学到了一种找技能CALL的方法啦,这样就太令我失望了,我要教给大家的不是一种技巧,是一种思维方式,我希望的是你们自己能创造出来更多更灵活的使用方法,这才是我写本文的目的,学习分几个阶段,基础知识,基础技巧,熟练后就要自己创造技巧,方为尚。






  • 12
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
本人曾经是速度追求极端分子,曾经花过三四年时间,潜心把易语言 的一些核心命令以及一些自己曾经项目上用到的一些功能,为了追求速度最大化,基本全部都用汇编做了一遍 今天开源的这个模块只是本人手中的一小部分汇编源码,但是里面也有很多东西需要跟你们介绍一下. 1.核心必备程序集 这部分,完全是通过汇编解析系统几个核心dll的命令 能达到免申明dll命令,直接调用,里面很多函数是基本跳过dll本身的函数入口,直接push参数call到驱动入口处(当初为了追踪这些dll特意用虚拟机windbg了xp系统大部分函数,有懂的可以去看看里面的KiZwOpenProcess 函数 ),为此可以躲过程序在一些调试软件里面被API断点拦截,还有一些拦截鼠标键盘模拟的安全软件或者游戏反辅助的检测.(当然以前这招有效,现在有没有效,没测了),里面还有一个内存加载dll功能,实现dll不落地直接使用里面的dll命令兼容任何系统.这一部分介绍有点多,省这点继续看下一个介绍 2图像处理/找图 通过纯汇编,创建位图,截取窗口位图,汇编二值化位图,汇编浮雕位图,汇编位图去杂点等等这些命令,非常实用在做位图识别,位图找字,找色等,速度我不敢说第一,但是想求你们找一个第一把我比下去.找图功能方面,都是100%的纯汇编代码,无任何杂质.注意一下缺点,就是理论上只能处理24位 32位的位图 3鼠键操作 这块也是通过汇编方式,绕过dll函数,直达驱动外壳调用.一般软件断点不到鼠键函数 其他一些汇编命令,虽然功能不强,但是也比较常用,或者重复使用次数比较多,速度上能节省一点,那就说明软件运行就更快一些.个人做这些命令之前,基本都拿易语言对应的命令测试过速度,大部分都是有很明显的速度提升的.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值