• 植物大战僵尸:代码实现自动收集阳光


    本次实验内容:通过阳光增加的值为切入点,找到自动收集阳光的关键判断并实现自动收集阳光,首先我们猜测当阳光出现后,我们是否会去点击,这个过程必然是由一个判断和一个时钟周期事件来控制的,那么当我们点击下落的阳光以后,则该判断条件实现,会执行收集阳光的CALL,否则的话继续执行阳光下落的过场动画,这正是正向开发的一种开发手段,此时我们也仅仅是猜测,接下来我们将去验证这个大胆的想法。

    为了找到阳光自动收集的关键跳转,我们需要以阳光增加作为切入点,为啥以它作为切入点呢?我们可以这样思考,当我们点击阳光后阳光增加了,说明已经完成了判断,下一步就是写入变量从而增加阳光,那么我们先来找到阳光的动态地址,并在该动态地址上按下F6键查找写入,然后回到游戏等待阳光出现并点击阳光,此时CE会出现以下代码,我们只需要记下00430A11这个内存地址,然后直接关闭CE。

    接着打开X64dbg附加到游戏进程,附加完成后,游戏会被X64dbg暂停运行,此时我们直接按下F12让游戏运行起来,然后按下Ctrl + G输入00430A11跳转到刚才找到的代码位置,过去以后直接F2下一个断点。

    此时我们需要逆向思考一个问题add dword ptr ds:[eax+0x5560],ecx这条指令是在我们阳光被点击后执行的,也就是说我们已经点击了阳光现在开始赋值了,那判断阳光是否被回收肯定是在这条指令之前出现,所以我们向上找,观察代码我们不难看出执行add dword ptr ds:[eax+0x5560],ecx指令之前有一个无条件跳转jmp 0x00430A0E跳过来的。

    继续向上查找跳转来源,可知在jmp跳转之前有一个je 0x004309EF跳转,经过测试这个地方具体控制阳光是否增加,在向上找就到段首了,此处代码中并没有出现自动收集阳光的关键跳转,因此推断这里应该是一个控制阳光是否增加的子过程(子过程:过程中调用的过程,称为子过程),所以我们继续回朔到上一层。

    为了能够回朔到上一层,我们需要取消阳光递增处的断点,并在段尾00430AB3处下一个F2断点防止程序跑飞,回到游戏等待阳光的出现,然后X64dbg就会断下,断下后直接取消00430AB3处的断点,执行到Ret处即可返回到上一层。

    返回到上一层以后,可以看到我们正是在call <plantsvszombies.sub_4309D0> 这里出来的,而上方就有一个jne plantsvszombies.4313FD关键跳,此处的关键跳转也并不是控制是否回收阳光的关键跳转,而此处的代码量比较少,因此判断此处还是一个子过程,我们继续回溯到上一层。

    我们直接单步F8运行到返回,并出这个CALL,出CALL以后会看到call <plantsvszombies.sub_430E40>没错!我们正是从这个子过程里出来的,接着向上找跳转会看到有一个jne plantsvszombies.431599此处如果将其改为jmp的话即可实现自动收集阳光,也就是说如果jne跳转实现则执行收集阳光,否则继续执行阳光下落的过场动画。

    注意:如果我们在关键跳jne plantsvszombies.4313FD处下断点时,会发现当阳光出现后程序会被无限的断下,这说明是有一个定时器线程在不断的执行判断代码,每次都会判断你是否点击了阳光,所以X64dbg才会被一直断下。

    知道了修改流程,那我们就通过编程的方式来实现修改程序的硬编码,首先我们可以通过以下代码完成字节集的读取。

    #include <stdio.h>
    #include <Windows.h>
    
    byte *ReadByteSet(DWORD Pid, DWORD Base, DWORD Size)
    {
      HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, 0, Pid);
      byte *buf = new byte[Size];
      ReadProcessMemory(handle, (LPVOID)Base, buf, Size, NULL);
      return buf;
    }
    
    int main()
    {
      	byte *Buff = new byte[10];
      	Buff = ReadByteSet(2232, 0x00401000, 10);
      	for (int i = 0; i < 10; i++)
      		printf("%02X ", Buff[i]);
      return 0;
    }
    

    既然有读取内存字节集,那么就有写入字节集,如下代码就是一种字节集写入的实现方式。

    #include <stdio.h>
    #include <Windows.h>
    
    BOOL WriteByteSet(DWORD Pid, DWORD Base, unsigned char *ShellCode, DWORD Size)
    {
      BYTE *Buff = new BYTE[Size];
      memset(Buff, *ShellCode, Size);
      HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, 0, Pid);
      BOOL Ret = WriteProcessMemory(handle, (LPVOID)Base, Buff, Size, NULL);
      if (Ret)
      	return TRUE;
      else
      	return FALSE;
    }
    
    int main()
    {
      unsigned char shell[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
      BOOL temp = WriteByteSet(3772, 0x00401010, shell, 8);
      return 0;
    }
    

    想要实现阳光自动收集,只需要将0x0043158F机器码0x75 0x08修改为0xEB 0x08即可实现效果。

      unsigned char shell[] = { 0xEB };
      BOOL temp = WriteByteSet(9744, 0x0043158F, shell, 1);
    
    文章出处:https://www.cnblogs.com/LyShark/p/15770661.html
    版权声明:本博客文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!

    如果您恶意转载本人文章并被本人发现,则您的整站文章,将会变为我的原创作品,请相互尊重 !
  • 相关阅读:
    第一阶段总结
    第二次项目总结(移动端)
    iOS 配置smart svn8.6.6
    iOS Xcode6.4添加pch文件
    iOS 上传应用到APPStore 详细版
    真机测试
    ios 引导页
    iOS 画图工具的截图
    iOS UIViewController
    iOS 把图片存到相册中
  • 原文地址:https://www.cnblogs.com/LyShark/p/15770661.html
Copyright © 2020-2023  润新知