登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 163|回复: 0

游戏逆向初探02.植物无CD的实现

[复制链接]

71

主题

1

回帖

146

积分

管理员

积分
146
发表于 2024-12-1 21:30:57 | 显示全部楼层 |阅读模式
思路:每个植物种植下去以后只有过了一段CD以后才能继续种植,说明内部应该是有个控制时间的变量,所以先搜索未知的初始值,种植以后不断变动的值,应该就能过滤出来了。
种植以后立马搜未知的初始值,然后走一段时间CD搜变动的
经过几轮搜索后 植物CD好了,还有一堆数值
image-20240412233736391.png
(植物CD好了肯定要搜一次变动,接着不要种植,多搜几次未变动,然后种植点其他植物搜未变动)
经过几轮搜索减少的数值以后,发现一个可疑的数值
image-20240412233945929.png
玩了几次后,有2个数值是0的比较可疑,拉到观察区看一下再说
image-20240412234044839.png
种了一个豌豆射手后,1B54889C这个地址的数值一直在增加
image-20240412234155601.png
当我给他改成9999以后 立马就可以种植了
image-20240412234225410.png
这说明,这个地址就是控制豌豆射手的CD的,当打到一定的程度,就能种植了,我们对这个地址下个断点,看看是什么情况
image-20240412234533937.png
确实在不断调用inc,还是去x64dbg里面看一下这代码吧
PlantsVsZombies.exe+91E4C:00491E46 - 80 7F 49 00 - cmp byte ptr [edi+49],0000491E4A - 74 1F - je PlantsVsZombies.exe+91E6B00491E4C - FF 47 24  - inc [edi+24] <<00491E4F - 8B 47 24  - mov eax,[edi+24]00491E52 - 3B 47 28  - cmp eax,[edi+28]

image-20240412234748968.png
inc dword ptr ds:[edi+0x24]mov eax,dword ptr ds:[edi+0x24]cmp eax,dword ptr ds:[edi+0x28]jle plantsvszombies.491E6B

这段代码应该就是 先增加CD,然后把增加后的cd取出来放在eax里面,再出去edi+0x28的值比较两个值决定是否要跳转(小于就跳转),所以把inc dword ptr ds:[edi+0x24]改成mov eax,esp 或者jle改成nop或者je就可以实现无CD了
上面的代码既然[edi+0x24]是当前CD,[edi+0x28]是CD最大值,那我们只要遍历每个植物,把0x24这个位置的值改成跟0x28一样,应该也可以实现每个植物无CD了。既然遍历,那就需要知道edi的基址,我们看一下EDI的来源
image-20240413000018458.png
发现是来自eax,eax来自上一层,去上一层看一下
image-20240413000050400.png
lea eax, ds:[edi+eax*1+0x28]这句代码下了几次断点发现,edi的值每次都是增加0x50可能是因为每个植物存储都是0x50个字节吧,eax是来自上面的mov eax, dword ptr ds:[ebx+0x15C],现在就要接着找ebx的来源了
发现ebx来源不是很好跟,因为代码分支比较多,也没看到赋值的地方,可能是来自上一层 要从函数头部跟一下才确定,这里就用简单的方法了,这里断下来后,直接去CE搜索,看能不能找到来源
image-20240413000517440.png
对029d3ed0这个地址下访问断
image-20240413000606735.png
发现是868这个偏移。。跟阳光一样,在继续找就会找到阳光的基址
遍历每个植物CD的代码
  1. DWORD dwAddr = -1;
  2.         ReadProcessMemory(m_hGameProcess, (LPVOID)m_dwBase, &dwAddr, sizeof(DWORD), NULL);//
  3.         //+x868
  4.         dwAddr += OFFSET_BASE_OFFSET1;
  5.         ReadProcessMemory(m_hGameProcess, (LPVOID)dwAddr, &dwAddr, sizeof(DWORD), NULL);//
  6.         //0x15c
  7.         dwAddr += OFFSET_CD_OFFSET1;
  8.         ReadProcessMemory(m_hGameProcess, (LPVOID)dwAddr, &dwAddr, sizeof(DWORD), NULL);//
  9.         for (int i = 0; i < 10; i++)
  10.         {
  11.             DWORD dwTmp = dwAddr + i * 0x50 + 0x28;

  12.             DWORD dwCurCdaddr = dwTmp + 0x24;//当前CD的地址
  13.             DWORD dwMaxCdaddr = dwTmp + 0x28;//最大CD的地址

  14.             DWORD dwCurCdValue = -1;//当前CD值
  15.             DWORD dwMaxCdValue = -1;//最大CD值

  16.             ReadProcessMemory(m_hGameProcess, (LPVOID)dwCurCdaddr, &dwCurCdValue, sizeof(DWORD), NULL);//读取当前CD
  17.             ReadProcessMemory(m_hGameProcess, (LPVOID)dwMaxCdaddr, &dwMaxCdValue, sizeof(DWORD), NULL);//读取最大CD

  18.             if (dwCurCdValue != dwMaxCdValue)
  19.             {
  20.                 WriteProcessMemory(m_hGameProcess, (LPVOID)dwCurCdaddr, &dwMaxCdValue, sizeof(DWORD), NULL);
  21.             }
  22.         }
  23.     }
复制代码

本帖被以下淘专辑推荐:

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|断点社区 |网站地图

GMT+8, 2024-12-23 22:06 , Processed in 0.081386 second(s), 30 queries .

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表