64位游戏是近些年才开始逐渐盛行的,所以一般一般来说64游戏中的数据结构往往和32位的数据结构类似,或者比32位游戏的结构更加复杂。下面我们通过某游戏的数据分析,来观察一下64位游戏下的数组。
我们以这款游戏的球员列表为例。首先,对球员列表进行观察,寻找突破口进行扫描。经过分析之后,我们发现这个球员列表可以分析的属性并不多,只有球员的位置以及球员的名字。(如图)
对于这类游戏,分析名字一般来说是无法直接找到列表遍历的,而是要经过一层球员名字库。所以我们尝试通过球员位置来进行分析。
游戏中对位置的数据是很少有存放的,不过在数组中对应的位置却不改变。所以问可以通过未知初始值或者发包中得到的具体数据来对对应位置的属性或者对象进行扫描。
通过明文包,我们可以得到球员的ID为8字节的42开头的数值,那么我们随便找一个ID来扫描(如图)
经过扫描之后我们可以得到十几个结果(如图)
改变球员位置之后会有3-4个结果发生变化(如图)
而我们重复做相同的操作,发现每一次扫描都会有一个9B开头的数据,再改变球员位置后就会失效。所以我们怀疑这个遍历可能是一个动态的数组,而每一次改变球员位置都会被重新申请。那么我们对这个9B开头的数据进行访问,看一下周围代码的情况。
下了访问断点之后,我们发现这个数据并不会断下,但是这个数据的周围很明显是一个结构体数组(如图)
于是我们根据对结构的观察, 判断出结构体数组的头部,并用ce进行扫描(如图)
这里可以得到两个结果,分别对两个地址进行观察。我们发现第一个地址相邻的3个地址非常像数组分配内存的结构( 如图)
在我们切换球员位置后,我们发现这里也会随着发生变化(如图)
于是可以判定,这里就是球员列表数组的起始地址和结束地址。我们在起始地址上下一个访问断点,再切换球员列表,游戏断下(如图)
分析RBX来源,得到来源与参数RCX,执行到返回后,得到+68偏移(如图)
继续分析的过程略过,我门直接来到关键代码处(如图)
我们要的地址来源于这里的add rdx, qword ptr [rcx + 8]
分析rdx可以得到来源于shl rdx, 4,而这里的rdx在每次更新后是固定不变的,也就是说这里其实不必继续分析。
分析rcx,可以得到来源于上面的add rdx, qword ptr [rbx + 0x60](如图)
而这里的rbx则来源于一个基地址。
这样我们就得到一个完整的公式,公式如下
[[[[[基地址+60]+[0x1428ccdd4]*10]+8]+830]+68 球员数组起始地址
这就是球员列表数组的分析过程,而这里我们可以看到数组的应用非常的多,包括常规的数组和结构体数组,而数组的入手方式也有很多。在我们没有太多办法的情况下,可以考虑从数组的起始和结束地址入手,然后再到数组的内部观察并分析数组内的属性。