一秒扫雷

可以直接用CE进行雷总数修改,下面是通过C#直接修改雷总数内存地址

 /// PROCESS_ALL_ACCESS -> (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
 public const int PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED| (SYNCHRONIZE | 4095));

 /// STANDARD_RIGHTS_REQUIRED -> (0x000F0000L)
 public const int STANDARD_RIGHTS_REQUIRED = 983040;

 /// SYNCHRONIZE -> (0x00100000L)
 public const int SYNCHRONIZE = 1048576;

 /// https://docs.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
 /// Return Type: HANDLE->void*
 ///dwDesiredAccess: DWORD->unsigned int
 ///bInheritHandle: BOOL->int
 ///dwProcessId: DWORD->unsigned int
 [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "OpenProcess")]
 public static extern System.IntPtr OpenProcess(uint dwDesiredAccess, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);

 /// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
 /// Return Type: BOOL->int
 ///hProcess: HANDLE->void*
 ///lpBaseAddress: LPVOID->void*
 ///lpBuffer: LPCVOID->void*
 ///nSize: SIZE_T->ULONG_PTR->unsigned int
 ///lpNumberOfBytesWritten: SIZE_T*
 [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "WriteProcessMemory")]
 [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
 public static extern bool WriteProcessMemory(System.IntPtr hProcess, System.IntPtr lpBaseAddress, System.IntPtr lpBuffer, uint nSize, ref uint lpNumberOfBytesWritten);
private int GetProcessId(string name)
{
    var process = Process.GetProcesses().ToList().FirstOrDefault(f => f.ProcessName == name);
    return process.Id;
}

 private void button1_Click(object sender, EventArgs e)
 {
     var pid = GetProcessId("MineSweeper");
     var hProcess = NativeApiCall.OpenProcess(NativeApiCall.PROCESS_ALL_ACCESS, false, (uint)pid);

     int address = 0x06241858;// 类总数内存地址
 
     byte[] rBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 };
     uint lpNumberOfBytesWrite = 0;
     var lpBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(rBytes, 0);
     NativeApiCall.WriteProcessMemory(hProcess, (IntPtr)address, lpBuffer, 4, ref lpNumberOfBytesWrite);
 }

关于基址寻找

寻找雷总数内存中的地址

首先打开扫雷游戏,然后打开CE,并从CE中打开扫雷进程;在弹出的进程列表中有三个选项,应用程序、进程、窗口这三个任意选哪个都可以。

现在,回到扫雷游戏,我们发现扫雷游戏的界面上有计时器,雷总数还有一些可以点击的小格子等等;现在假设下,如果扫雷是咱们写代码开发的话,他界面上显示的这些东西,实际上在代码中是不是都有对应的一个地址和一个内存空间,而我们现在就是要找这个地址;当然我们没办直接知道这个地址在什么位置,所以只能根据他对应的一些特征把他找出来;比如根据他的值进行查找;在我的游戏界面中,雷的总数显示的是99

所以现在我们用CE对游戏进行扫描,把存有99的地址都找出来;

现在游戏中存储有99的地址都显示出来了,哇,这一堆堆的哪个才是呢?我们知道new出来的内存空间是不会变化的(除非销毁),但是存储在内存空间里的值是会根据程序运行和用户操作发生变化;现在我们用排除法,先让雷的总数发生一些变化,把总数修改成40个,而其他都不动。

现在我们再根据40这个值进行扫描,发现只剩下一个了;(如果你的界面中还是有很多个值或者一个都没有了,你还可以重复上面的操作,或者根据不同的条件再进行扫描)

那么现在扫出来的这个地址是不是我们想要的雷总数的地址呢?先把他复制到地址列表中,然后我们对他的值进行修改,看看会不会对游戏中的总数有影响

在CE中,把06990968地址对应的值改成1,然后回到游戏,我们发现雷的总数已经变成了1,说明我们找的地址是对的

寻找基址

然而我们上面找到的地址在关闭游戏后就会失效,那如何做到每次打开游戏如何直接找到这个地址呢?并且这个地址不一定每次都存雷的总数,因为每次游戏载入内存的启始地址不是固定的,既然这样,那每次还怎么找雷总数的地址呢?
还记得每次写程序的时候,我们的程序都有一个main函数么,这不就是你程序的起点,而代码中的变量,函数...是不是按你调用的顺序载入到内存中,所以回到游戏来说,游戏载入内存的时候也有一个起点,而存储雷总数的代码也是相对起点存储在某个位置,除非你把游戏的代码改了。
现在在看下我们手里有什么了,扫雷游戏在内存中的起始地址,还有雷总数的地址,雷总数的位置相对起始位置是固定的;那么我们每次打开游戏,雷总数的地址不就是起始地址进行相对距离的偏移了么。所以现在我们要把这个相对距离找出来。
还是利用我们之前找到的雷总数的地址,然后进行扫描

这里有很多参数,相关的解释可以去https://www.cheatengine.org/官网找找

点击ok后,会需要我们选择一个扫描结果保存目录,随便找个目录起个名字就可以

(由于扫描的过程中把游戏关闭了,所以我这里重新扫雷总数的地址,大家看的时候雷总数地址和之前会对不起来,06990968-069D2858)当CE扫完后,我这里有1000多个结果,那么哪个才是呢?

还是使用排除法,把雷总数修改后再进行重新扫描,这里我把雷又改成了99个


这次扫完后只剩了300多个,还是有点多,重复上面的动作,继续改雷个数继续扫

发现重复了好多次还是有一两百个,我们可以换成用地址扫

但是还是有很多结果,怎么办呢,其实到这里已经很接近答案了,我们可以试着随便双击几个结果,复制到地址列表中,尝试修改它的值,如果游戏中的地址也跟着发生变化,那么这个基址和偏移值基本就是我们要找的结果

现在,你可以试试重启扫雷,然后用CE再打开进程,看看这些地址是否还能对应到总数的

posted @ 2020-07-19 13:13  壮哈苗  阅读(484)  评论(5编辑  收藏  举报