获取变量的静态地址/偏移量

逆向工程 ollydbg 调试 C++ 地址 抵消
2021-07-04 03:30:09

我对逆向工程完全陌生,我目前正在努力获取我自己编写的程序变量的静态偏移量/地址。

所以我用 C++ 编写了以下程序,只是为了得到一些练习:

#include <iostream>
#include <Windows.h>
#include <string>

class Entity
{
public:
    Entity(int health, int max_health, int armor) : m_health{ health }, m_max_health{ max_health }, m_armor{ armor }
    {}
protected:
    int m_health;
    int m_max_health;
    int m_armor;
};

class Player : public Entity
{
public:
    Player() : Entity(200, 400, 50)
    {}
    void heal() { m_health = m_max_health; }
    int get_health() { return m_health; }
private:
};

int main()
{
    Player player;

    while (1)
    {
        std::cout << "player health: " << player.get_health() << "\n";
        Sleep(500);
    }
}

之后我在 x32dbg 中打开了可执行文件。我的第一步是查找字符串引用,然后检查是否可以找到“玩家健康”字符串。这相当简单,它让我看到了以下指令,它们代表了可执行文件的 while 循环: 1

在那之后,我在 010C24EC 处设置了一个断点(如您在图片中看到的),并且我在愚蠢的情况下跟随了 ESP(即 31FE18),这使我得到了 200 的值,我认为这是变量的值,所以我认为地址 31FE18 是我的变量 player.m_health 的地址。现在我的问题是每次重新启动程序时地址都在变化(这是正常的),所以我用C++编写了另一个程序,它读出了另一个进程的Imagebase,所以我想当我减去的地址时我的图像库中的变量,我可以获得静态偏移量,当我将它添加到图像库时,它总是会引导我找到正确的变量。

我很确定我误解了一些事情,如果有人能帮助我,我会非常高兴,因为我真的花了一些时间试图自己解决这个问题,但我尝试过的所有事情都没有奏效迄今为止。

提前致谢。

问候史蒂文

1个回答

注意:这不会使用 x32dbg/ollydbg 来回答问题,而是使用另一种工具。(我似乎无法发表评论)。如果它偏离主题,我深表歉意。

您可以尝试使用作弊引擎(CE)。

如果是,请下载无安装程序版本,因为安装程序包含废话:

在此处输入图片说明

我假设您此时已下载并解压缩了它。

该软件有一个非常好的集成教程,它是文件夹中提供的另一个 .exe。此处阅读有关它的更多信息(它适用于 64 位,但它应该让您了解如何运行 32 位教程)。尝试完成它(或跳过步骤 - 右下角),并且在某个时候(第 6 步和第 8 步)您的问题将得到解决(无意双关语)。

祝你好运 :)


附录

阅读您在下面发布的评论

  • 我通常没有幸运地立即选择正确的 [...]

虽然它并不完美,但 CE 有一个名为“指针扫描”的工具(您可能已经知道这个工具,我正在考虑新的 CE 用户),它可以暴力地强制偏移并降低一个以上的深度级别. 经过很多努力,它可能会奏效。

  • 所以我认为学习如何通过自己编写的小型程序使用它们将是进入它的最聪明的方法。但正如@mrexodia 已经指出的那样,玩家对象通常不会在堆栈上分配。

更笼统地说(我偏离了你的指针问题),我认为这是一个非常好的方法。示例:通过这种方法,我曾经在反汇编我的游戏时发现了一个我不知道 / cmov(或cmovcc在手册中)的操作码,因此我确切地知道内存和代码中的内容。对我很有指导意义,绝对是+1。您还可以通过比较代码和生成的程序集来了解编译器优化。

当涉及到更复杂的游戏时,尝试在独立游戏(当然是单人游戏)或开源游戏(因为它们易于访问)上练习。尝试突击立方体(或突击立方体重新加载)。这个游戏练习起来很有趣,因为没有调试保护和反作弊系统,......你可以例如找到指向本地玩家的指针,或者修改游戏代码/让你的团队立于不败之地,无限弹药等等...

解决您的问题的方法

这是一种直觉,并非基于事实,但我相信在 Java、C# 或 OS 功能(例如地址随机化)中制作的游戏在汇编中更难调试,并且在指针查找方面可能无法预测, ... . 我喜欢使用的一种方法(在大多数情况下查找本地播放器)是使用“代码挂钩”。

例如,如果您想在 AssaultCube(或其他游戏)中找到本地玩家的地址,您可以找到在屏幕上绘制玩家弹药/生命值的 GUI 代码,因为如果您的游戏向您显示您有 100Hp,好吧,它必须在某处提取价值。在这种情况下,您可以做的是使用 CE 并找到 Hp,找到访问此地址的代码,并希望有类似的东西,即拦截此值的 GUI 代码。从那里您可以检索播放器基址。这种技术的真正优点在于您不必乱用指针,这是获取玩家地址的一种非常直接的方法。

缺点是你必须注入一些代码来恢复它。您可以注入手工编写的程序(C、C++、...)或使用 CE 培训师来实现此效果。此时使用调试器可能会帮助您了解数据的来源,并希望找到一种获取指针的方法。

  • 所以我的整个想法似乎很愚蠢/我最大的问题是我不是一个真正聪明的人/或者你会说对我这样的人来说这是浪费时间吗

不,这并不愚蠢,您完全可以做到这一点,对我来说,您绝对不是“真正聪明的人”,因为您正在尝试理解诸如指针之类的低级概念。

我在逆向工程领域没有经验,我不会假装我知道很多东西,但是我有一些关于 stackoverflow / gamedev 的“坏”问题,我显然不知道我在做什么但是嘿,我年轻没关系,这是学习曲线的一部分。起初我什至不明白这些概念,很久以前,我为一个涉及装配补丁的游戏制作了一个“简单”的模组,以提高乐趣。有两个简单的补丁要制作,但我花了几个小时才弄明白。我想说明的一点是你必须从某个地方开始。感谢您的尝试!

在某种程度上,您将花费甚至浪费时间来解决问题、学习技术、调试,......您知道这并不是一个人。这就像画画,我不认为毕加索有一天醒来就知道如何画画,它最终伴随着练习、失败、学习和挫折而来。

现在我意识到这并没有真正回答你的问题,我很抱歉,基本上尝试指针扫描/代码挂钩。我确信有更多我不知道的解决方案可以解决这个问题。