内存地址,知道dll的偏移量和基地址如何获取内存地址来设置值

Posted

技术标签:

【中文标题】内存地址,知道dll的偏移量和基地址如何获取内存地址来设置值【英文标题】:Memory address, knowing the offsets and the base address of a dll how can I obtain the memory adress to set values 【发布时间】:2021-01-05 00:12:22 【问题描述】:

我有我的基本内存地址"GameAssembly.dll"+00DA5A84 和一些offets。加上这个,我得到了我需要的地址。 (红色矩形)。每次重置游戏时都会更改。

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

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

查看变量内部的值我得到了这个。

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);

【问题讨论】:

这能回答你的问题吗? How this memory address is calculated? 请不要多次发布同一个问题。 是的,每次启动可执行文件时,基地址都会发生变化,您对此无能为力,这就是处理器和操作系统的工作方式,尤其是在 x32 保护模式和 x64 中.几年前我本可以在 DOS 中帮助您,但对于现代 Windows 和 .NET,请等待有人回答您,用更多细节改进您的问题或添加 赏金 我知道它会改变,我在问如何获得具有基本内存地址和偏移量的新地址。就像作弊引擎获取新地址(红色矩形)一样,我怎样才能以编程方式获取它。 (另外,我再次写了这篇文章,因为它被降级了,没有人再看到它,即使我尝试更新它,赏金选项也不再可用,可能是因为降级?) 这对您有帮助吗? ***.com/questions/14467229/… & codeproject.com/articles/716227/… 【参考方案1】:

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

"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);

【讨论】:

看来这正是我想要的。我做错了,因为我收到此消息错误 System.ComponentModel.Win32Exception: 'Couldn't read 4 byte(s) from 0x5C.',我现在要更新我的帖子,这样你就可以看到我的步骤了一步,所以你可以告诉我我做错了什么。另外,非常感谢您的回复,如果您能给我一些建议,以及从头开始学习这种东西的资源,我将不胜感激。谢谢! @Sharki 它返回一个整数 为什么? ProcessModule.BaseAddressIntPtr。只需返回 IntPtr。 MemorySharp 也有public RemoteModule this[string moduleName],你可以通过RemoteModule.BaseAddress获取基地址。 我很迷茫,很抱歉。我什至不知道如何使用 BaseAddress() 方法... @Sharki 我没用过 MemorySharp 但试试A_ptr = sharp["GameAssembly.dll"].BaseAddress + 0x00DA5A94; 它有效,我得到了与使用 ProcessModule.BaseAdress 相同的 IntPtr,但我也得到了相同的错误消息。 System.ComponentModel.Win32Exception: 'Couldn't read 4 byte(s) from 0x16AB53D.' 我将使用我正在尝试的相同代码更新我的帖子。我也想为给您带来这么多麻烦而道歉。【参考方案2】:

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

例如,想象一下这段代码,在一个虚构的简单 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 的地址并修改它。

【讨论】:

以上是关于内存地址,知道dll的偏移量和基地址如何获取内存地址来设置值的主要内容,如果未能解决你的问题,请参考以下文章

微信PC端获取个人信息

C++ 函数挂钩(仅限内存地址)

linux内核 - 如何获取物理地址(内存管理)?

操作系统--存储管理3

反射式DLL注入--方法

C中的结构访问