簡體   English   中英

在內存中搜索特定值C#(Xbox 360)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM