上一篇文章里,我们对技能名字进行分析,得到了一个数组,但是经过观察,我们发现这个数组是一个临时存放的数组,只有当技能栏打开时才会显示当前一栏的技能,这样我们在获取所有技能信息时是很不方便的,所以下面我们要换一个方向找到真正的技能库遍历。在之前找到的数组上下F2断点,并获取同一个技能的对象,我们会发现及时从新打开技能栏,获取到的技能对象都是一样的,只是存放的地址发生了变化。所以我们可以通过CE对这个地址进行扫描,并通过重新打开技能栏来过滤掉临时存放的地址。 分别在数据窗口中观察这两个地址,我们发现第二个地址的结构和临时存放的结构是一样的,也就是说这里就是拷贝到临时地址中的数组。 在这个地址上下硬件访问断点,切换技能栏,游戏断到一个新的数组位置
这里同样是一个+8偏移和一个8+4的数组,在ebx+8处下断,观察断下的值,发现里面的内容是固定不变的,重新打开技能栏,ebx也不会重新生成。我们继续分析ebx的来源,在上面可以得到来源于一个CALL的返回eax 在CALL上下断,分析参数,发现这个CALL只有一个参数,而参数的值很可能就是技能类型的ID 到CALL里面分析eax的来源,得到来源于局部变量[ebp-10],而这个局部变量在上面的以结构体参数传到CALL中并被赋值。 到CALL 9CB360中分析来源,首先得到一个+10偏移 继续向上分析,可以得到一个数组套链表的结构 对代码的走向进行分析,可以得出数组套链表的节点+8中存放的数值会反复的与外面传入的技能类型ID进行比较,所以说这个位置存放的就是技能类型ID执行到返回后,继续分析ecx的来源,可以得到+20偏移 再次执行到返回可以得到基地址 既然得到了基地址,是不是说我们的分析结束了呢?不!还没有结束!我们对数组套链表的结构进行观察后发现,这里的元素和节点实在是太多了,我们需要继续分析传入到CALL中的技能类型ID的来源 我们执行到返回后得到了一个数组 直接用CE扫描这个ebx可以得到一个基地址 接下来分析数组里面元素,可以得出以下公式[[0x047CECD0]+138]+n4+4 技能类型n=1为1转类型IDn=2为2转类型IDn=3为3转类型IDn=4为4转类型ID而0转的技能类型所有职业都为0可以说,追到这里我们就已经可以通过关联来获取到完整遍历了,但是如果为了提高一点代码效率,我们可以用技能类型ID经过加密计算获取到数组套链表的数组下标,这部分代码就在数组套链表的上面 最终我们可以整理出公式如下技能类型ID 循环右移5 得到结果为G[[[0x03CF46D8]+20+4]+(G%[[0x03CF46D8]+20+8])4]+4 链表[[[0x03CF46D8]+20+4]+(G%[[0x03CF46D8]+20+8])4]+8 ID[[[0x03CF46D8]+20+4]+(G%[[0x03CF46D8]+20+8])*4]+10 对象链表+4 链表链表+8 ID链表+10 对象
[对象+8]-4 技能数组元素数量[[对象+8]+n8+4]+4 技能ID[[[对象+8]+n8+4]+8]+0 技能名字ASCII完整的技能遍历已经获取到了,虽然有些复杂,不过成就感是慢慢的,当然如果有小伙伴觉得这个办法太麻烦,也可以用传参调CALL的方式获取,被检测到了不要哭哦。从安全角度来讲,这个部分正向代码的设计其实要比逆向麻烦很多,如果能在关键的CALL中加入弱VM并加入本地检测,会得到意想不到的效果。玩游戏,学逆向,做安全,欢迎感兴趣的小伙伴关注我们。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
建议楼主不要指出是啥游戏,不然可能会被运营商追着打