内存地址,了解dll的偏移量和基地址,如何获取内存地址以设置值

问题描述

我有我的基本内存地址"GameAssembly.dll"+00DA5A84和一些信息。加起来,我得到了我需要的地址。 (红色矩形)。每次重置游戏后,这一情况就会改变。

Figure1

获得内存地址后,我可以执行以下操作:

public void isImpostor(IntPtr addrs,int valuetoWriteInMemory)
{
   using (var sharp = new MemorySharp(Process.GetProcessesByName("Among Us").FirstOrDefault()))
   {
       sharp[addrs,false].Write(valuetoWriteInMemory);
   }
}

var addrs = new IntPtr(0x210A83A8);
isImpostor(addrs,0x0);

不过,我不确定如何获取该内存地址。不确定该怎么做:

"GameAssembly.dll" + 0x00DA5A94 + 0x28 + 0x34 + 0x0 + 0x5C并获得0x210A83A8的结果。


已更新:

为了知道GameAssembly.dll的AddressBase是什么,我有方法

public int GetModuleAddress(String pName,String dllName)
{
         Process p = Process.GetProcessesByName(pName).FirstOrDefault();
         foreach(ProcessModule pm in p.Modules) 
              if (pm.ModuleName.Equals(dllName)) 
                   return (int)pm.BaseAddress;
         return 0;
}

Console.WriteLine(GetModuleAddress("Among Us","GameAssembly.dll");
Console.WriteLine((IntPtr)GetModuleAddress("Among Us","GameAssembly.dll")); 
Result1 (As integer): 2043150336
Result2 (After Casting to IntPtr): 2043150336 here I can do the addition I mentioned before.

它返回一个int,所以我无法添加GameAssembly.dll + 0x00DA5A94。假设我将此结果转换为IntPtr。一旦将其强制转换为IntPtr,我就可以做到。

IntPtr A_ptr =(IntPtr)GetModuleAddress("Among Us","GameAssembly.dll") + 0x00DA5A94;

但是我收到此消息错误

System.ComponentModel.Win32Exception: 'Couldn't read 4 byte(s) from 0x5C.'

我也尝试使用toString("X")方法将地址转换为十六进制,结果为79C80000,但我既不能79C80000 + 0x00DA5A94 也不能0x79C80000 + 0x00DA5A94。 / p>

查看变量内部的值,我明白了。

BaseAdressDLL: 2043150336
A: 0,Aptr: 2057460372 (or 0x00000000 and 0x7aa25a94 respectively)
Bptr: 92 (or 0x0000005c)

我做错了什么?我也为我的英语感到抱歉。

我尝试使用Cheat引擎提供给我的BaseAdress,并且它运行良好,因此我以为我不知道如何正确获取AdressBase。

var sharp = new MemorySharp(Process.GetProcessesByName("Among Us").FirstOrDefault());


/* This does`t work 
IntPtr GameB = (IntPtr)GetModuleAddress("Among Us","GameAssembly.dll");
IntPtr GameAssemblyDllBaseAddress = sharp.Read<IntPtr>(GameB,false);
IntPtr A_ptr = GameAssemblyDllBaseAddress + 0x00DA5A94;
IntPtr A = sharp.Read<IntPtr>(A_ptr,false);
*/


// But this does it.
IntPtr A = (IntPtr)0x11F7FC18; // Using AddressBase directly.

// -------------
IntPtr B_ptr = A + 0x5C;
IntPtr B = sharp.Read<IntPtr>(B_ptr,false);

IntPtr C_ptr = B + 0x0;
IntPtr C = sharp.Read<IntPtr>(C_ptr,false);

IntPtr D_ptr = C + 0x34;
IntPtr D = sharp.Read<IntPtr>(D_ptr,false);

IntPtr isImpostor_ptr = D + 0x28;
// read
int isImpostor = sharp.Read<int>(isImpostor_ptr,false);
// write
sharp[isImpostor_ptr,false].Write(0x1);

解决方法

您拥有的是一堆指针。让我们给他们起个名字吧:

"GameAssembly.dll" + 0x00DA5A94  - pointer to A
    + 0x5C                       - A + 0x5C  - pointer to B
        + 0x0                    - B + 0x0   - pointer to C
            + 0x34               - C + 0x34  - pointer to D
                + 0x28           - D + 0x28  - pointer to int (let's call it isImpostor_ptr)

如果您想知道isImpostor的值,则需要取消引用(读取存储在内存地址中的值)isImpostor_ptr

isImpostor = [isImpostor_ptr]   or   isImpostor = [D + 0x28] 

要获取D,您需要取消引用C + 0x34,依此类推,最终您会得到:

isImpostor = [[[[["GameAssembly.dll" + 0x00DA5A94] + 0x5C] + 0x0] + 0x34] + 0x28]

在C#中:

IntPtr A_ptr = GameAssemblyDllBaseAddress + 0x00DA5A94;
IntPtr A = sharp.Read<IntPtr>(A_ptr,false);
IntPtr B_ptr = A + 0x5C;
IntPtr B = sharp.Read<IntPtr>(B_ptr,false);
IntPtr C_ptr = B + 0x0;
IntPtr C = sharp.Read<IntPtr>(C_ptr,false);
IntPtr D_ptr = C + 0x34;
IntPtr D = sharp.Read<IntPtr>(D_ptr,false);
IntPtr isImpostor_ptr = D + 0x28;
// read
int isImpostor = sharp.Read<int>(isImpostor_ptr,false);
// write
sharp[isImpostor_ptr,false].Write(valueToWriteInMemory);
,

那些偏移量是堆栈上变量的地址。它们的位置完全取决于起点之前调用的功能。

例如,在一个虚构的简单16位处理器中使用以下代码来传递所有参数,想象一下这段代码:

void Func1()
{
    int var1 = 1;  
    Func2();
}

void Func2()
{
    int var2 = 2;
    Func3(var2);
}

void Func3(int i)
{
    int var3 = 3;
    BREAKPOINT // This is where your calculations should start
}

当代码达到BREAKPOINT时,堆栈看起来像(X =基地址):

0xX0000000 <- Return address of the next line Func1 after the call to Func2
0xX0000004 <- var1
0xX0000008 <- Return address of the next line Func2 after the call to Func3
0xX000000C <- var2
0xX0000010 <- contents of var2 as passed to Func3

鉴于您知道基本地址,并且了解如何回溯到堆栈,您可以找到var1的地址并对其进行修改。