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

所以我写了以下内容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循环:


之后,我在010C24EC处设置了一个断点(如您所见在图片中),然后我盲目地跟随了ESP(即31FE18),导致我得出了200的值,我认为这是变量的值,因此我认为地址31FE18是我的变量player.m_health的地址。现在我的问题是每次我重新启动程序时地址都会改变(这是正常的),所以我用C ++编写了另一个程序,该程序读取了另一个进程的Imagebase,所以我认为当我减去程序的地址时从我的Imagebase中获取我的变量,当我将其添加到图像库中时,可以获得静态偏移量,该偏移量总是将我引向正确的变量。如果有人可以帮助我,我会很高兴,因为我确实花了一些时间试图自己解决这个问题,但是到目前为止,我尝试过的所有事情都没有奏效。

在此先感谢您。

礼物
史蒂文

评论

在您的情况下,将Player对象分配在堆栈上。如果需要固定地址,请尝试将其放在全局范围内。

@mrexodia感谢您的回复。我之前已经成功完成了操作,但是当播放器是局部变量时,我如何设法获得固定地址(或计算播放器地址将是什么)?
通常您不会这么做,因为通常不会将玩家存储在堆栈中:)但是,如果您可以某种方式在调用堆栈中的某个已知位置提取堆栈地址,则可以这样做。例如,主线程的初始堆栈-x应该为您提供播放器对象的堆栈地址,因为它是在主线程的开头分配在堆栈上的。您是否检查了作弊引擎教程?通常,您可以在代码/数据中找到一个(间接)引用播放器对象的已知位置,以稳定的方式获取指向播放器的指针。

#1 楼

注意:使用x32dbg / ollydbg,但这不能回答问题,而是使用另一种工具。 (我似乎无法发表评论)。抱歉,我很抱歉。
您可以尝试使用作弊引擎(CE)。
如果是,请下载无安装程序版本,因为安装程序包含废话:

我假设您已经下载并解压缩了。
该软件有一个非常不错的集成教程,该文件夹中还包含另一个.exe。在此处阅读有关它的更多信息(适用于64位,但是它应该使您了解如何运行32位教程)。尝试执行此操作(或跳过步骤-右下角),并在某个时候(步骤6和8)将解决您的问题(无需双关语)。
祝您好运:)

附录
从您在下面发表的评论中读取内容

我通常没有足够的幸运儿立即选择合适的一个[...]

CE虽不完美,但它具有称为“指针扫描”的工具(您可能已经知道此工具,我正在考虑新的CE用户),在该工具中,蛮力迫使偏移并下降了多个深度。

因此,它可能会起作用。

所以我认为学习如何在小型的自行编写的程序中使用它们将是最聪明的方法。但是正如@mrexodia所指出的那样,播放器对象通常不会分配在堆栈上。

一般来讲(我偏离了指针问题),我认为这是一种非常好的方法。示例:通过这种方法,我曾经在拆解我的游戏时发现了一个我不知道的/ cmov(或手册中的cmovcc)操作码,因此我确切地知道了如何在内存和代码中放置内容。对我很有启发性,绝对是+1。您还可以通过比较代码和生成的程序集来了解编译器优化。
当涉及到更复杂的游戏时,请尝试练习独立游戏(当然是单人游戏)或开放源代码(因为它们可以访问)。尝试攻击多维数据集(或重新加载攻击多维数据集)。这款游戏非常有趣,因为它没有调试保护,也没有反作弊系统,...例如,您可以找到指向本地玩家的指针,或者修改游戏代码/使团队立于不败之地,无限弹药等等...
解决问题的方法
这是一种直觉,并非基于事实,但我相信使用Java,C#或虚拟机(如地址随机化)等虚拟机制作的游戏。 。很难在汇编中调试,并且在指针查找方面可能是不可预测的,....
我喜欢使用的一种方法(通常在大多数情况下是寻找本地播放器)正在使用“代码挂钩”。
例如,如果您想在AssaultCube(或其他游戏)中找到本地玩家的地址,则可以找到在屏幕上绘制玩家弹药/健康状况的GUI代码,因为如果您的游戏向您显示您有100Hp,那么它必须将值提取到某个地方。在这种情况下,您可以执行的操作是使用CE并找到Hp,找到哪些代码可以访问该地址,并且希望以后会出现截取该值的GUI代码。从那里您可以获取播放器的基本地址。这项技术真正的优点是您不必弄乱指针,这是获取播放器地址的一种非常简单的方法。
缺点是您必须注入一些代码来维护它。您可以注入手工制作的程序(C,C ++等),也可以使用CE培训师来达到此效果。此时使用调试器可以帮助您了解数据的来源,并希望找到一种获取指针的方法。


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


不,它不是愚蠢的,您可以完全理解它,对我来说,您绝对不是“不是一个真正的聪明人”,因为您正试图理解诸如指针之类的低级概念。 />我没有逆向工程领域的经验,我不假装自己了解很多东西,但是我对stackoverflow / gamedev有一些“坏”问题,我显然不知道自己在做什么,但是,还可以,这是学习曲线的一部分。刚开始我什至不了解这些概念,不久前,我为一款涉及组装补丁以改善游戏乐趣的游戏制作了“简单” mod。要制作两个简单的补丁,但是花了我几个小时才弄清楚。我想说的是,您必须从某个地方开始。
您要努力尝试!这就像绘画,我不认为毕加索有一天会醒来并且知道如何绘画,最终会伴随着实践,失败,学习和挫败感。
现在我意识到这并不能真正回答您的问题和道歉,基本上尝试指针扫描/代码挂钩。我确定还有更多解决方案,我不知道。

评论


嘿,谢谢你的回答。是的,我已经完成了几次作弊引擎教程,并且还观看了一些人们对其进行了更深入解释的视频。事实是,在大型游戏中使用作弊引擎追溯指针链时,我遇到了很大的困难。大多数时候,我可以追溯到2或3个偏移量,然后得到太多可能的基本指针。

–GeeHopper
18年7月26日在10:28

而且我通常不足够幸运地立即选择正确的方法,并且对数百个地址进行反复试验似乎也不是正确的方法。因此,我一直在寻找更好的方法来实现这一点,并且发现了很多可行的解决方案,最推荐的解决方案是使用x32dbg之类的调试器。因此,我认为学习如何在小型自编写程序中使用它们是最明智的方法。但是,正如@mrexodia所指出的那样,播放器对象通常不会分配在堆栈上,因此我的整个想法似乎很愚蠢,但至少我从中有所了解。

–GeeHopper
18年7月26日在10:35

无论如何,大多数大型游戏都有一些公共抵消式倾销者,但是我真的很想学习如何独自做这些事情以积累深厚的知识。我最大的问题是我不是一个很聪明的人,要进入这个领域对我来说真的很困难。但是另一方面,学习新事物非常有趣,我真的很愿意花一些时间在上面。但是,您是否认为对它的热情实际上足以积累一些良好的知识,或者您说这对像我这样的人来说是浪费时间?很抱歉这个奇怪的问题。

–GeeHopper
18年7月26日在10:48

我编辑了答案,写下了想到的内容,对不起,似乎有点混乱;)

–潮汐
18年7月26日在22:34

哇,非常感谢您提供这个非常详尽且有启发性的答案。 :)

–GeeHopper
18年7月27日在8:19