如何修改C#内存读取代码以THREADSTACK0-0000032C为基地址?
如何将多偏移指针读取代码的基地址替换为THREADSTACK0-0x32C?
Got it, let's tackle this problem. To replace the fixed base address 0x1002CAA70 with THREADSTACK0 - 0x32C, we need to dynamically get the target thread's stack base address first—since THREADSTACK0 in Cheat Engine refers to the base address of the thread's stack. Here's how to modify your code:
Key Steps to Implement:
- Add Windows API Calls to retrieve thread information (we'll use
NtQueryInformationThreadto get the Thread Environment Block (TEB), which contains the stack base address). - Calculate the New Base Address by subtracting
0x32Cfrom the stack base address obtained from the TEB. - Fix Potential 64-bit Compatibility Issues (your original code uses
intfor process handles, which can break on 64-bit systems—we'll switch toIntPtrinstead).
Modified Full Code:
using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace ConsoleApplication1 { class Program { const int PROCESS_WM_READ = 0x0010; const int THREAD_QUERY_INFORMATION = 0x0040; const int ThreadBasicInformation = 0; // Define structures for thread information [StructLayout(LayoutKind.Sequential)] struct THREAD_BASIC_INFORMATION { public IntPtr ExitStatus; public IntPtr TebBaseAddress; public IntPtr StackBase; public IntPtr StackLimit; public IntPtr SubSystemTib; // ... other fields we don't need can be omitted } // Import required APIs [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] public static extern IntPtr OpenThread(int dwDesiredAccess, bool bInheritHandle, int dwThreadId); [DllImport("ntdll.dll")] public static extern int NtQueryInformationThread(IntPtr threadHandle, int threadInformationClass, ref THREAD_BASIC_INFORMATION threadInformation, int threadInformationLength, out int returnLength); [DllImport("kernel32.dll")] public static extern bool ReadProcessMemory(IntPtr hProcess, Int64 lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); static void Main(string[] args) { try { // Get target process Process process = Process.GetProcessesByName("Tutorial-x86_64")[0]; IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, process.Id); // Get target thread (we'll use the first thread of the process) ProcessThread targetThread = process.Threads[0]; IntPtr threadHandle = OpenThread(THREAD_QUERY_INFORMATION, false, targetThread.Id); // Retrieve thread basic information to get TEB and stack base THREAD_BASIC_INFORMATION threadInfo = new THREAD_BASIC_INFORMATION(); int returnLength; NtQueryInformationThread(threadHandle, ThreadBasicInformation, ref threadInfo, Marshal.SizeOf(threadInfo), out returnLength); // Calculate our new base address: THREADSTACK0 - 0x32C Int64 stackBase = (Int64)threadInfo.StackBase; Int64 baseAddress = stackBase - 0x32C; // Now proceed with your original pointer reading logic int bytesRead = 0; byte[] buffer = new byte[4]; ReadProcessMemory(processHandle, baseAddress, buffer, buffer.Length, ref bytesRead); Int64 baseValue = BitConverter.ToInt32(buffer, 0); Int64 firstAddress = baseValue + 0x10; ReadProcessMemory(processHandle, firstAddress, buffer, buffer.Length, ref bytesRead); Int64 firstValue = BitConverter.ToInt32(buffer, 0); Int64 secondAddress = firstValue + 0x18; ReadProcessMemory(processHandle, secondAddress, buffer, buffer.Length, ref bytesRead); Int64 secondValue = BitConverter.ToInt32(buffer, 0); Int64 thirdAddress = secondValue + 0x0; ReadProcessMemory(processHandle, thirdAddress, buffer, buffer.Length, ref bytesRead); Int64 thirdValue = BitConverter.ToInt32(buffer, 0); Int64 fourthAddress = thirdValue + 0x18; ReadProcessMemory(processHandle, fourthAddress, buffer, buffer.Length, ref bytesRead); Int64 fourthValue = BitConverter.ToInt32(buffer, 0); ReadProcessMemory(processHandle, fourthValue, buffer, buffer.Length, ref bytesRead); Console.WriteLine(BitConverter.ToInt32(buffer, 0)); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } Console.ReadLine(); } } }
Notes:
- Thread Selection: The code uses the first thread of the process (
process.Threads[0]). If your target pointer is tied to a specific thread, make sure to select that thread instead of the first one. - x64 Compatibility: We switched the
hProcessparameter inReadProcessMemoryfrominttoIntPtrto support 64-bit processes and handles. - TEB Structure: The
THREAD_BASIC_INFORMATIONstruct includes theStackBasefield directly, which is exactly what Cheat Engine labels asTHREADSTACK0.
内容的提问来源于stack exchange,提问作者shiny
相关产品推荐
相关产品推荐

