多种方法跳出线程发包

        明文发包CALL是分析一款游戏功能的主要突破口,但是很多游戏都是线程发包,需要跳出线程才能得到明文CALL的位置。跳线程的方式有很多种,不同的游戏也有不同的跳出方式,下面我们来看一下都有哪些方法可以跳出线程。

一、常规的方法,通过线程内封包写入来源跳出线程

        其实对于线程发包来说,关键的就是要找到包内容是从哪里写入的,往往这个写入的过程不止一个,也可能是多个,所以不要以为一次写入断点就可以搞定所有的线程发包。

示例1:幻想神域单机版

        以《幻想神域单机版》为例,首先我们来到WSASend处下断点,游戏断下后观察包内容,发现每次游戏断下包内容都会变化,那么我们就不能对包内容下写入断点,而是分析包地址的来源。返回后对pBuffers结构进行分析,得出包地址的来源是0x00B92181处的ECX(如图)

        向上分析ecx的来源,并逐层观察,观察各层偏移地址在哪一层开始不会变化,最终得出[edi+2888]是最外层被写入的位置,我们在edi+2888上下写入断点,游戏断下(如图)

        虽然断下了,但是我们发现代码并没有跳出线程循环,那么我们需要继续分析写入的eax的来源。同样,在0x00B92038处的edx的地址是不变的,而其内部被不断的写入,那么我们在这里继续下写入断点(如图)

        游戏断下,断到一个新的函数中(如图)

        通过堆栈的变化,可以看出代码以及跳出了线程循环,经过几层返回,跳到最外层的明文包处,我们可以在这里进行定位,方便以后对其他函数进行分析(如图)

示例2:某传奇类网游

        这款游戏是调用send函数发送封包,我们在下断时发现包内容的地址是变动的,这样我们就无法在封包内容上下写入断点。所以我们要分析包地址的来源,找到写入的位置跳出线程。执行到返回后很容易发现,包内容的来源。(如图)

        在注释处下断我们发现eax始终为0,所以我们只需要考虑esi的来源即可,向上看发现esi来源于eax,而eax是call 00ED1030的返回值。下断后F7观察call内部的代码(如图)

        我们发现eax是来源一个数组,而多次下断我们发现00ED103E处数组中的eax是不断递增的,也就是说我们无法再固定的地址上下写入。所以我们需要分析数组中ecx和eax的来源来判断下一次发包会被写入的地址是那一条。很容易分析得出如图所示位置的[ECX+C]+[ECX+4]*4是下一次即将被写入的地址(如图)

        dd [0CD100C0+C]+[0CD100C0+4]*4后随意发包,游戏断下(CD100C0为当前ecx的值),断下后得到如下代码(如图)

        堆栈中的返回地址如下

调用堆栈

地址 堆栈 函数过程 / 参数 调用来自 结构

02B3E668 00ED1A21 包含MMOGame-.00F0C81C MMOGame-.00ED1A1F

02B3E688 00ED5795 MMOGame-.00ED1980 MMOGame-.00ED5790

02B3E6B8 01209073 MMOGame-.00ED5650 MMOGame-.0120906E

02B3E6FC 0120DAAA MMOGame-.01209000 MMOGame-.0120DAA5

这时我们已经跳出了线程,很容易我们便分析出明文包的函数头部(如图)

二、通过分析关键跳转跳出线程

示例1:某2D阴间网游

        在这款游戏中,我们通过常规的写入断点方法很难跳出线程,因为在写入时会有大量的干扰包让我们无法断到正确的线程外。

        我们在send函数处下F2断点,并执行到返回,发现返回到图中位置时无法继续返回,说明此时已经来到线程循环最外层。

        在此处下断,我们发现断下的频率并不高,只有正常发送的封包才会断下。

        而在上面的跳转处下断,发现会立刻断下,也就是说这里的跳转会对是否需要发送的封包进行拦截。

        很明显在[EBP-C]小于等于0时,会直接跳过经过发包的函数,那么我们直接去分析这个局部变量的来源,发现他其实来源于上面的CALL 0x9C4460

        在CALL里很容易追到来源

        由于这里的eax+10中,eax是不变的,所以我们直接在eax+10上下写入断点

        做一个发包动作,游戏断下

        向外层返回,并观察游戏断下情况,可以找到只有某个动作会断的功能CALL,他们共同调用的CALL就是明文发包函数。

示例2:韩服剑灵2

        前面的方法都是固定不变的,首先我们用xdbg64找到其发包函数WSASend

        由于这里每次断的包内容地址是变化的,所以我们要取追一下来源,执行到返回后来到函数调用处

        这里的包内容来源于rax+[rdi+18],而下断之后我们可以发现rax始终都0,所以我们继续向上追rdi,可以得到来源于CALL的返回值。

        在CALL上下断,并单步到内部,可以得到一个数组,这发包方式和传奇永恒的特别像

        这里的RCX是不变的,所以我们可以直接配出包内容的公式为[rcx+18]+([rcx]&FFFFFFFF)*8

        填入rcx的值,在数据窗口中跟随,并在下面不远处选择一个地址,提前下好写入断点,不断的走路发包,等待游戏断下

        我们发现写入的这个位置还是在原来那个函数内部,也就是说我们还是没有跳出线程

        那么我们要继续向上追rbp的来源,在执行到返回后得到了[r14+rax]

        在这里下断后发现r14始终是0,而rax是不变的,于是我们在rax上下写入断点,走路后游戏断下

        现在这个位置就是很多人都会遇到的难点,继续向上追可以得到一个数组,而这数组的下标是随机获取的,想从这个里入手很麻烦

        既然这里不好下写入断,那我们只要整体函数的执行流程做一个分析。

        在上面我们发现了一个位置断的特备频繁,发包的执行流程中会掺杂大量的假包,并跳到函数尾部,不执行发包代码。而这个位置的上面会有一个判断,用来分辨当前执行的代码是否是真的发包代码。

        所以我们分别取追一下r14d和eax的来源,并最终得到了两处赋值的位置

        我们在下面的数组上下断,获取到真正发包时的rbp的值,并对+40和+88进行下断观察,可以发现+88是决定代码流程的关键,因为有的时候+40不变,而+88会改变,此时恰好会让二者不相等,实现真的发包。

        于是我们在这个+88偏移上下写入断点,尝试跳出线程。在游戏内下断断的狠频繁,我们很难做出写入的动作。所以我们要来带创建角色界面下断,在这里可以很轻松的断下,并来到跳出线程的代码里

 

三、其他方式跳出线程

示例1:接着上面的剑灵2继续分析

        我们可以用CE对+88这个地址下写入断点,然后挨个尝试,其中会有一个写入会在线程外,这种方式并不是万能的,是因为代码恰好是这么去写的才能够达到这样的效果,如果写入的来源是固定的代码,并在其他位置进行判断那会麻烦很多

示例2:接着上面的剑灵2继续分析

        这方式有一些玄学,就是在模块内扫描比较函数中的基地址,虽然扫描到的基地址有很多,不过在前面的几个里面就会有一个在线程外,跳过去下断可以返回到功能CALL。当然这种方式虽然有一定的道理,但也是在我们走投无路的情况下才去尝试的。

 

示例3:通过扫描包长跳出线程

        以某2D传奇类游戏为例,我们在正常分析线程发包时发现,这个游戏跳线程还是比较麻烦的,虽然常规方式也可以跳出,但是我们需要选择一种更加简单有效的方式。

        首先我们在WSAend下断,并做一个发包动作让其断下

 

        这里的包长是1D,我们用CE去扫描这个数值,需要注意的是要在断下的情况下去扫描

        接下来做一个其他包长的动作去进行过滤,可以得到一个结果

        我们在这个地址上下写入断点,走路后游戏断下

 

        像外层返回后发现其实我们已经跳出线程了,找到明文发包函数即可

        以上就是跳出线程发包的几种方式,当然跳线程不能死记硬背,要根据自己对线程的理解去跳出线程,后续有新的方式在进行补充。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值