[英]Searching Memory For Specific Values C# (Xbox 360)
编辑:我想我有一个实际的值搜索可能的解决方案的想法。 通过确保用户输入以0结尾,应该可以解决该问题。 这将涉及从uint中减去最后一位(我不知道如何获得,除非我将转换为字符串,将末端修剪回uint方法很丑陋,但我想它可以工作),然后减去它。 如果有人对此有任何提示,请帮助我!
我一直在研究一种程序,用于在Xbox 360上搜索内存以获取特定值,如果您熟悉的话,它类似于“作弊引擎”。 我已经掌握了基础知识,但是遇到了一个问题。 我搜索内存的方法取决于在与您的值一致的地址处开始搜索。 如果这对您没有意义,请使用以下代码:
private void searchInt32(int Value, uint Address, uint BytesToSearch)
{
for (uint i = 0; i <= BytesToSearch; i+=4)
{
int recoveredMem = XboxSupport.littleEndtoInt(XboxSupport.GetMem(Address + i, 4), 0);
//Recover Memory (As Bytes) and convert to integer from address (incremented based on for loop)
if (recoveredMem == Value) //Check if recovered mem = search value
{
writeToFile(Address + i, Convert.ToString(Value)); //If recovered mem = search value, write to a text file
}
siStatus.Caption = String.Format("Searching Bytes {0} out of {1}...", i, BytesToSearch); //Update status caption
}
}
如您所见,将代码保持在最低限度,并且从控制台恢复内存时,代码也要尽可能快。 但是,如果恢复的4个字节与该值不一致,它将永远不会返回您想要的内容。 这显然是一个严重的问题,因为用户将不知道其值在哪里或从何地址开始以返回正确的值。 然后,我尝试使用以下代码解决此问题:
private void searchUInt32(uint Value, uint Address, uint BytesToSearch)
{
siStatus.Caption = String.Format("Recovering Memory...");
byte[] data = XboxSupport.GetMem(Address, BytesToSearch); //Dump Console Memory
FileStream output = new FileStream("SearchData.dat", FileMode.Create);
BinaryWriter writer = new BinaryWriter(output);
writer.Write(data); //Write dump to file
writer.Close();
output = new FileStream("SearchData.dat", FileMode.Open);
BinaryReader reader = new BinaryReader(output); //Open dumped file
for (uint i = 0; i *4 < reader.BaseStream.Length; i++)
{
byte[] bytes = reader.ReadBytes(4); //Read the 4 bytes
Array.Reverse(bytes);
uint currentValue = BitConverter.ToUInt32(bytes, 0); //Convert to UInt
if(currentValue == Value) //Compare
writeToFile(Address + i * 4, Convert.ToString(Value));
siStatus.Caption = String.Format("Searching Bytes {0} out of {1}...", i * 4, BytesToSearch);
}
reader.Close();
File.Delete("SearchData.dat");
}
还有很多代码,但是本质上,它只是使用文件来完成相同的事情。 我最初的目标是让用户能够输入自己要搜索的内存块,但是现在看来,这只是行不通的。 我并不是很想让程序搜索所有的内存,因为这最终可能是一个缓慢的进程(取决于转储的进程的大小),并且通常情况下,所寻找的值可以缩小到可写区域代码,从进程的可执行部分中删除垃圾地址。 我只是想看看是否有人有任何建议,我想我可以从流程中获取条目地址(我有一个功能),并使用一些数学正确的用户输入地址来正常工作,但我没有完全确定该怎么做。 如果有人有任何建议或解决方案,我将不胜感激。 如果需要澄清/清理我的任何帖子,请告诉我,我将很高兴做任何可能有助于回答的事情。 谢谢!
编辑:临时(希望)解决方案:
当我将地址加载到工具中时,它们将作为文本文件中的字符串加载,然后尝试转换为uint。 我使用以下代码解决了偶数问题:
sA[0] = sA[0].Remove(sA[0].Length - 1) + "0"; //Remove last character and replace w/ 0
//Add 16 to the search length
与其将内存转储到磁盘并读取每次迭代,不如逐块扫描目标进程的内存,然后封送数据以利用指针算术的效率。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace MemoryScan {
internal class Program {
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
private static unsafe void Main(string[] args) {
Process process = Process.GetProcessesByName("notepad")[0]; //example target process
int search = 100; //search value
int segment = 0x10000; //avoid the large object heap (> 84k)
int range = 0x7FFFFFFF - segment; ; //32-bit example
int bytesRead;
List<int> addresses = new List<int>();
DateTime start = DateTime.Now;
for (int i = 0; i < range; i += segment) {
byte[] buffer = new byte[segment];
if (!ReadProcessMemory(process.Handle, new IntPtr(i), buffer, segment, out bytesRead)) {
continue;
}
IntPtr data = Marshal.AllocHGlobal(bytesRead);
Marshal.Copy(buffer, 0, data, bytesRead);
for (int j = 0; j < bytesRead; j++) {
int current = *(int*)(data + j);
if (current == search) {
addresses.Add(i + j);
}
}
Marshal.FreeHGlobal(data);
}
Console.WriteLine("Duration: {0} seconds", (DateTime.Now - start).TotalSeconds);
Console.WriteLine("Found: {0}", addresses.Count);
Console.ReadLine();
}
}
}
检测结果
持续时间:1.142秒
找到的:3204
创建一个通用类以简化类型封送处理,如下所示:
public static class MarshalHelper
{
public unsafe static T Read<T>(IntPtr address)
{
object value;
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.Int16:
value = *(short*)address;
break;
case TypeCode.Int32:
value = *(int*)address;
break;
case TypeCode.Int64:
value = *(long*)address;
break;
default:
throw new ArgumentOutOfRangeException();
}
return (T)value;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.