在看雪不知不觉的潜水就几年了。也吸收到了很多的知识,但是苦于某些方面的东西,大家都不愿意公开。下面就来说说如何来找真正的明文包。
在游戏逆向过程中,通常会遇到下面几种情况的发包。
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期)