内容参考于:易道云信息技术研究院VIP课
上一个内容:模拟游戏登陆器启动游戏并且完成注入
首先正常分析软件程序有没有漏洞,需要通过它的操作侵入,比如买东西,就通过买东西的按钮它背后有源代码就看源代码,没有源代码就逆向分析,然后尝试性的去修改它的参数,然后看看有没有什么不合理的地方有没有漏洞,对于网络游戏来讲前面说的东西就没必要了,因为网络游戏里不管你是吃药也好、走路也好,所有操作最后它一定是通过数据包的形式反映给服务器的,所以就直接观察它的数据包,或者说我们模拟数据包的发送,直接就进行测试,这样它有什么限制不严格的地方就可以看出来了。
游戏客户端与服务端协作形式:有两种
1.
发送结果型,比如我们吃药,它的做法是,首先在界面里按了一个吃药的操作,按下之后生命值就会增加,这个时候在客户端就会看有没有药、有没有cd、能不能吃,能吃就增加了,本来还有1点生命值吃药之后100点,这时就要写到服务器,把100发送给服务器,这个操作存在漏洞,在发送之前这个100我们是可以更改的,这种操作它往往会有加密的技术,防止被修改,但是不管怎样这种结构就决定了是可以更改的,防止不了,大部分游戏不会采用这种结果,但是也有(某勇士)。
2.
这一种由UI的操作吃药,还是检测有没有药,有没有cd、能不能吃(这里检测是为了让服务端压力变小),这个时候发送请求吃药(告诉服务器我要吃药了),服务器收到吃药请求就去看服务器上的数据(就是服务器再去判断能不能吃药、有没有cd、能不能吃),服务器验证完成得出可以吃药就把数据写到数据库里(完成吃药),然后就给客户端说吃药完成了,这样的过程可以攻击的点就很少。
大部分游戏都是第一种和第二种相互结合的,要明白一个道理,安全的本质不是技术的对决,而是经济的对决,比如走路这样的操作,如果服务还是频繁验证的话是比较浪废性能的,走路这种请求会频发触发如果服务器还验证会导致很卡,所以服务器会不得不放弃一些验证的操作,改用第一种结果式,就是把结果给服务器比如走路的坐标,这就造成了漏洞、
还有本质上用的是第二种,但是第二种它是连续性的,比如要三个第二种操作才能完成一件事,其中一个被人为修改掉也会造成漏洞,不管怎样说核心的点都在网络通信的地方。
现在主线任务:
通过逆向分析,找到游戏发送数据,接收数据的过程,这个是很好找的,找到这个过程利用起来是不方便的,因为游戏往往都有加密的过程,所以要找它明文发送数据的位置,因为只有找到这种地方才能很好的利用,找到这种地方之后就可以接收数据发送数据了,这样就可以既可以欺骗客户端又可以欺骗服务端,这样测试漏洞就很方便了,找到漏洞之后要给出修改的建议,就是我们很清楚攻击什么位置,面对这种地方的攻击我们应该怎样防护,现在搞是跟安全有关的事情,然后这样的测试是很有必要的大量的网络游戏或者大量的游戏都有这样的漏洞,比如以前的吃鸡(绝地求生)飞天遁地瞬移秒杀千里万里子弹都是这种情况
游戏数据包的处理流程:
客户端发送数据:
首先ui操作,比如吃药操作,就会根据吃药组织一个数据包给服务器,一般组织数据包的地方就是明文,为什么是明文,如果不是明文搞的很复杂,在开发的时候也是费劲,所以组织数据包的位置就是明文,比如01代表吃药02代表使用技能,然后组织的数据包就是 01 23,这个23就是代表吃的什么药,然后01代表吃药,然后02 01,02是使用技能01代表的技能,如果说可以用wpe一类的软件可以截取到这个数据直接改,就是不去动游戏而是在网卡这个阶段,就能把这个东西给截取到,所以游戏往往在组织完数据之后会有一个加密的操作,加密完才发送,然后现在可以看出攻击的点就在组织数据的位置。
客户端接收数据:
接收数据之后,然后解密数据,然后根据包的内容调用对应的函数(分发数据),然后使用数据(函数执行中),然后现在看攻击的点就是分发数据这里,然后解读虽然是明文,但也不是很容易,但是真的可以全部解读出来以后会发现,大部分逆向工作都不需要做了
游戏网络通信架构模型:
单线程:
直接看发送数据的这里,首先我们写代码是一行一行的,然后调用一个函数之后,这个函数执行完返回之后再继续往下,然后假设这个函数是发送数据的,如果数据特别大,没发送完它就会卡住(阻塞),所以这种单线程模式用的比较少,这种模型,通过发送数据往回找可以找到组织数据,从ui操作往后找可以找到组织数据,接收数据时就是通过接收数据往后找可以找到解密数据之后分发数据之前,然后通过使用数据往后找也能找到分发数据前,只要它是这种模型就能找到。
然后使用数据,比如血量增加了,通过血量的变化就能找到分发数据之前
多线程:
它与单线程的不同是加密完数据之后写到一个缓存里,然后线程b去读取缓存然后发送数据,这种的从发送数据的位置就找不到组织数据的位置了,然后从ui操作找后面的东西也是找不到,这样的要找那块缓存空间,通过缓存空间的读写来找
接收数据也是通样的道理
一般就这两种架构
游戏网络通信常见函数:
send、recv 一般用于tcp通信,默认为阻塞型通信。
sento、recvfrom 一般用于UDP通信,它可以直接根据指定ip和端口进行访问,不行创建socket,微信和qq应该用的就是这个
WSASend、WSARecv 天生异步操作,配合完成端口使用(看这里:iocp完成端口,详细简单的完成端口使用)
recv:
recv之后就是处理数据
WSARecv:
要去找 GetQueuedCompletionStatus 函数,详情看 iocp完成端口 这里。