2013-10-28 31 views
0

編輯:我想我有一個可能的解決方案的價值的實際搜索的想法。通過確保用戶輸入以0結尾,問題應該得到解決。這將涉及從uint(我不知道如何得到,除非我轉換爲字符串,修剪結束回uint方法這是醜陋的,但我想它可以工作),然後減去它的最後一位數字。如果有人有關於如何做到這一點的任何提示,請幫助我!搜索內存的具體價值C#(Xbox 360)

我一直在尋找一個程序來搜索Xbox 360上的特定值的內存,如果你很熟悉,它類似於「Cheat Engine」。我已經掌握了基本知識,但我遇到了一個問題。我搜索記憶的方法取決於在與您的價值相符的地址開始搜索。如果這樣做沒有意義的,你這裏是代碼:

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 
+0

不完全相關,但對於整潔的緣故,我會把i + = 4的for循環,以避免所有這些* 4s和/ 4 –

+0

我不確定是否轉發這種類型的ca使用,但它似乎已經失去了對這裏性能的所有希望:'byte [] data = XboxSupport。GetMem(Address,BytesToSearch);'更好地做到這一切在內存和一口大小的塊...你應該能夠找出如何找到你的輸入值重新排列(可能不止一次),而不是重新排列正在搜索的數據以及... – 2013-10-28 18:01:02

+0

@WeylandYutani完成,謝謝 – Matt

回答

0

相反傾銷存儲到磁盤和閱讀每次迭代,掃描目標的過程中塊存儲器中,然後封送數據利用指針運算的效率。

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; 
    } 
} 
+0

問題是我沒有搜索可以在計算機上找到的進程 - 否則此代碼將非常優秀。可悲的是,目前還沒有辦法在Xbox 360上掃描正在運行的進程內存,至少我目前知道 – Matt

+0

@NoviceProgrammer等待,所以'XboxSupport.GetMem()'是一個不存在的組合函數? PS - 使用按位算術。清除n中的最低位。 'n = n | 0xFFFFFFFE' – 2013-10-29 14:41:00

+0

@ebyrob是的,它是我創建的函數。什麼是按位算術?這只是使最低值爲0或完全刪除它? – Matt