首页
社区
课程
招聘
[原创][原创]如何逆向游戏的线程发包
发表于: 2016-5-6 10:32 17066

[原创][原创]如何逆向游戏的线程发包

2016-5-6 10:32
17066

在看雪不知不觉的潜水就几年了。也吸收到了很多的知识,但是苦于某些方面的东西,大家都不愿意公开。下面就来说说如何来找真正的明文包。

在游戏逆向过程中,通常会遇到下面几种情况的发包。
1.在主线程直接发包
2.在线程中发包
-------------------------------------------
1. 主线程发包

在游戏里面如何分辨是不是主线程发包?
首先肯定是跳转到3大发包函数,send , sendto ,WSASend 分别下段。 如果下断点马上就断下,那么基本就是线程发包了。除此之外,是主线程发包的可能性比较大了。
这种情况下,我们只需要通过不同的动作来断下,找到最外层的相同的call函数,就是真正的明文包了。

--------------------------------------------
2.线程发包

那么线程发包是什么情况呢?
就是在发包函数上下断点马上就断下,而且断的非常的频繁,基本就可以确定是线程发包了。

找线程发包的主要步骤如下:
找到真正的发包函数, 找到包内容的位置。 再跟包内容的写入位置,基本就可以找到正确的明文包了。

下面以某个游戏的明文包来分析下:

首先来到send sendto wsasend的位置下断点,发现wsasend会断点,但是包长包内容一直就只有2个,并且包长包内容不变,所有可以确定他是假的发包了。 单步跟入,跟到call [eax + 64]虚表的位置,步入,得到下面的地址。这个地址就是windows内部的发包函数

6F244405    6A 44           push    44
6F244407    68 8045246F     push    6F244580
6F24440C    E8 7FCFFFFF     call    6F241390
6F244411    33FF            xor     edi, edi
6F244413    897D E0         mov     dword ptr [ebp-20], edi
6F244416    803D B864276F 0>cmp     byte ptr [6F2764B8], 0
6F24441D    0F85 24240000   jnz     6F246847
6F244423    393D 5C60276F   cmp     dword ptr [6F27605C], edi
6F244429    0F86 18240000   jbe     6F246847
6F24442F    FF35 8860276F   push    dword ptr [6F276088]
6F244435    FF15 D412246F   call    dword ptr [<&API-MS-Win-Core-Pro>; kernel32.TlsGetValue
6F24443B    8945 D4         mov     dword ptr [ebp-2C], eax
6F24443E    3BC7            cmp     eax, edi
6F244440    0F84 01240000   je      6F246847
6F244446    897D E4         mov     dword ptr [ebp-1C], edi
6F244449    833D C464276F 0>cmp     dword ptr [6F2764C4], 1

一般情况下,游戏里面不会修改真正的windows发包函数,所有通过这个内部的WSPSend函数基本就可以返回到正确的发包函数了,也有些情况会修改内部的发包函数,但是原理相同。这里就不多说了。

通过上面的特征,可以找到真正的发包函数

8E6E2D    85C0            test    eax, eax
008E6E2F    0F84 34030000   je      008E7169
008E6E35    8B4A 10         mov     ecx, dword ptr [edx+10]
008E6E38    8BD1            mov     edx, ecx
008E6E3A    C1E2 04         shl     edx, 4
008E6E3D    2BD1            sub     edx, ecx
008E6E3F    8D44D0 38       lea     eax, dword ptr [eax+edx*8+38]
008E6E43    8987 740D0000   mov     dword ptr [edi+D74], eax
008E6E49    8378 74 01      cmp     dword ptr [eax+74], 1
008E6E4D    C745 FC 0000000>mov     dword ptr [ebp-4], 0
008E6E54    0F85 80000000   jnz     008E6EDA
008E6E5A    8B70 50         mov     esi, dword ptr [eax+50]!!
008E6E5D    8B4E 0C         mov     ecx, dword ptr [esi+C]
008E6E60    8B56 10         mov     edx, dword ptr [esi+10]
008E6E63    6A 00           push    0
008E6E65    51              push    ecx  包长
008E6E66    52              push    edx  包内容
008E6E67    8BCF            mov     ecx, edi
008E6E69    E8 A2640000     call    008ED310                         ; 明文包
008E6E6E    8B46 10         mov     eax, dword ptr [esi+10]
008E6E71    85C0            test    eax, eax
008E6E73    74 13           je      short 008E6E88
008E6E75    50              push    eax  
008E6E76    8D8F 200C0100   lea     ecx, dword ptr [edi+10C20]
008E6E7C    E8 FF310000     call    008EA080
008E6E81    C746 10 0000000>mov     dword ptr [esi+10], 0

---------------------------
追到这了。发现上面还是跳不出线程循环。
这时候我们利用od dd查看包的内容,找他写入的地方。
发现[eax+50]+10  就是包内容,而eax+50的值一直在变化。 这个时候在上面下写入断点就可以返回到正确的明文包的位置了。
注意:有些地方有vm,需要跟踪ebp来跳出去。

但是虽然追到了正确的明文包,但是发现还是有些问题,在线程里面如何发包的?
008ED815    F7F7                div     edi
008ED817    895D F8             mov     dword ptr [ebp-8], ebx
008ED81A    8BF2                mov     esi, edx
008ED81C    8B51 04             mov     edx, dword ptr [ecx+4]
008ED81F    8D0476              lea     eax, dword ptr [esi+esi*2]
008ED822    03C0                add     eax, eax
008ED824    03C0                add     eax, eax
008ED826    03D0                add     edx, eax
008ED828    807A 08 00          cmp     byte ptr [edx+8], 0
008ED82C    8955 FC             mov     dword ptr [ebp-4], edx
008ED82F    0F84 A3000000       je      008ED8D8
008ED835    391A                cmp     dword ptr [edx], ebx
008ED837    75 1D               jnz     short 008ED856                   ; 12A7354C == ecx
008ED839    8B49 04             mov     ecx, dword ptr [ecx+4]           ; [[[[ecx + 4] + 180] + 4] +10 ] + 10
008ED83C    8D1401              lea     edx, dword ptr [ecx+eax]         ; [[[ecx + n*0c0] + 4] +10 ] + 10
008ED83F    8B45 08             mov     eax, dword ptr [ebp+8]
008ED842    8910                mov     dword ptr [eax], edx             ; [[edx + 4] +10 ] + 10
008ED844    8D147F              lea     edx, dword ptr [edi+edi*2]
008ED847    5F                  pop     edi
008ED848    8D0C91              lea     ecx, dword ptr [ecx+edx*4]
008ED84B    5E                  pop     esi
008ED84C    8948 04             mov     dword ptr [eax+4], ecx
008ED84F    5B                  pop     ebx
008ED850    8BE5                mov     esp, ebp
008ED852    5D                  pop     ebp
008ED853    C2 0800             retn    8
008ED856    8BC3                mov     eax, ebx
在写入的地方发现有 一个数组,在这个数组里面有所有的包。   里面有真的包,假的包,其实追到这的时候,就离真正的明文包很近了,肯定就在他的上面附近。

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

下面来总结下明文发包:
基本上就这样。

1.找到正确的发包函数
2.找到对内容进行写入的地方
2.根据写入的地方跳出线程循环

线程发包的流程一般都是下面这样的

主线程
{
   明文包(往某个地址里面写入数据)

}

线程{
   循环 取某个地址的包内容的数据
   判断包是否有用{
      如果是有用的包的话,就执行发包动作
  }
}

线程发包的东西差不多就是这样的了。 。。。。如果有什么不对的地方,大婶们多指点小弟一下。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (11)
雪    币: 324
活跃值: (60)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
沙发!!楼主如果是64位程序,用到WinSocket的还是32位的吗?或者这样问,WinSocket只有32位的吗?
2016-5-6 10:36
0
雪    币: 76
活跃值: (28)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
没啥区别吧。 但是找底层的发包函数只针对本机有效。必须是在本机上找到的,然后才能在游戏中套用
2016-5-6 10:57
0
雪    币: 94
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
意识就是有个包队列,然后线程不停地取包,发包?
2016-5-6 14:17
0
雪    币: 9479
活跃值: (757)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
其实没有这么麻烦,按你的情况,直接od断wsasend,条件断点屏蔽掉心跳包,堆栈直接找到明文发包函数,
经常都有多个线程发包的
2016-5-6 14:20
0
雪    币: 284
活跃值: (250)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
还是不是很明白,直接下条件断点我觉得会好一点。。。
2016-5-6 18:47
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
大神能留个联系方式么???我在线程发包这里卡住了找了一整天啊没头绪
2017-1-8 23:57
0
雪    币: 238
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
无边 其实没有这么麻烦,按你的情况,直接od断wsasend,条件断点屏蔽掉心跳包,堆栈直接找到明文发包函数, 经常都有多个线程发包的
人家都说了是线程发包了还在想回溯堆栈  666
2018-5-27 23:58
0
雪    币: 238
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9

我遇到最难的就是驱动发包的游戏
最后于 2018-5-27 23:58 被武装的蔷薇编辑 ,原因:
2018-5-27 23:58
0
雪    币: 272
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
你的思路也没错。我前两天也搞定一个,直接找到游戏按钮的处理函数上了,按钮里有发包前的明文。
我的思路是这样的,我在发包线程里折腾了两天,大部分发包线程是个死循环,一般有两个读取数据包的形式,一种是封包线程和发包线程共享一个内存地址,这个地址是一个缓冲区,封包好的数据放在这里,发包线程读取这里的数据包发出去。只要找到这个地址,下硬件写入断点,再ret几次可能就是明文包的地方了,不过这个地址需要花点时间去找找,有时候隐藏的指针比较深,另一种形式是,利用windows提供的线程同api函数,我遇到的这个游戏就是这种的,他的发包线程在没有数据包的时候,会调用WaitForSingleObject,并且阻塞线程,我当时想,肯定封包线程会有与之对应的函数能够让WaitForSingleObject返回继续往下运行,查了一下是SetEvent函数。具体两个函数的作用不明白的可以自行百度,是做线程同步的。试了一下,断在SetEvent了,那么调用SetEvent的一方肯定是封包的线程,断在封包线程上就很近了。点k按钮看看调用栈,自己ret返回几层后基本上就是了。
最后于 2020-2-27 00:53 被榴莲味奥利奥编辑 ,原因:
2020-2-27 00:33
0
雪    币: 83
活跃值: (1087)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
11
已阅
2020-2-27 14:52
0
雪    币: 36
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
没有续集了吗
2021-1-21 15:31
0
游客
登录 | 注册 方可回帖
返回
//