Pointers 游戏培训师如何更改内存中';什么是动态的?

Pointers 游戏培训师如何更改内存中';什么是动态的?,pointers,memory-address,Pointers,Memory Address,假设我是一个游戏,我有一个包含我的健康状况的全局int*。游戏培训师的工作是将该值修改为任何值,以实现上帝模式。我查阅了游戏培训师的教程来了解它们是如何工作的,一般的想法是使用内存扫描仪来尝试找到某个值的地址。然后通过注入dll或其他方式修改此地址 但是我用一个全局的int*做了一个简单的程序,每次我运行这个应用程序时,它的地址都会改变,所以我不知道游戏训练师如何硬编码这些地址?还是我的例子错了 我遗漏了什么?编辑:没关系,这似乎只是运气好,但指针的最后3个数字似乎保持不变。也许这是ASLR介入

假设我是一个游戏,我有一个包含我的健康状况的全局
int*
。游戏培训师的工作是将该值修改为任何值,以实现上帝模式。我查阅了游戏培训师的教程来了解它们是如何工作的,一般的想法是使用内存扫描仪来尝试找到某个值的地址。然后通过注入dll或其他方式修改此地址

但是我用一个全局的
int*
做了一个简单的程序,每次我运行这个应用程序时,它的地址都会改变,所以我不知道游戏训练师如何硬编码这些地址?还是我的例子错了


我遗漏了什么?

编辑:没关系,这似乎只是运气好,但指针的最后3个数字似乎保持不变。也许这是ASLR介入并更改基本映像地址或其他什么

糟糕,我用%d作为printf来打印地址,而不是%p。使用%p后,地址保持不变

#include <stdio.h>

int *something = NULL;

int main()
{
    something = new int;
    *something = 5;

    fprintf(stdout, "Address of something: %p\nValue of something: %d\nPointer Address of something: %p", &something, *something, something);
    getchar();
    return 0;
}
#包括
int*something=NULL;
int main()
{
某物=新的int;
*某物=5;
fprintf(stdout,“某物的地址:%p\n某物的值:%d\n某物的内部地址:%p”、&something、*something、something);
getchar();
返回0;
}
动态分配变量的示例 我想要找到的价值是生命的数量,以阻止我的生命减少到0,结束游戏

  • 在这个实例中,玩游戏并搜索lifes变量的位置
  • 找到后,使用反汇编程序/调试器监视该位置的更改
  • 失去生命
  • 调试器应该报告发生递减的地址
  • 将该指令替换为无操作
  • 从一个名为tsearch的程序中得到了这个模式


    通过研究该主题发现了一些相关网站:

    • (谷歌缓存版本)

    通常的方法是跟踪指针链,从静态变量一直跟踪到包含相关变量的堆地址。例如:

    struct CharacterStats
    {
        int health;
        // ...
    }
    
    class Character
    {
    public:
        CharacterStats* stats;
    
        // ...
    
        void hit(int damage)
        {
            stats->health -= damage;
            if (stats->health <= 0)
                die();
        }
    }
    
    
    class Game
    {
    public:
        Character* main_character;
        vector<Character*> enemies;
        // ...
    }
    
    Game* game;
    
    void main()
    {
        game = new Game();
        game->main_character = new Character();
        game->main_character->stats = new CharacterStats;
    
        // ...
    
    }
    
    struct CharacterStats
    {
    国际卫生组织;
    // ...
    }
    类字符
    {
    公众:
    CharacterStats*stats;
    // ...
    虚空命中(智力伤害)
    {
    统计->健康-=伤害;
    如果(stats->health main_character=new character();
    游戏->主要角色->统计=新角色统计;
    // ...
    }
    
    在这种情况下,如果您遵循mikek3332002的建议,在Character::hit()函数中设置断点并取消减法运算,则会导致包括敌人在内的所有角色都是不受攻击的。解决方案是找到“game”变量的地址(该变量应位于数据段或函数堆栈中),并遵循所有指针,直到找到运行状况变量的地址


    一些工具,例如作弊引擎,具有自动执行此操作的功能,并尝试自行查找指针链。不过,对于更复杂的情况,您可能必须求助于逆向工程。

    Gameshark代码等问题的解决方法是:转储应用程序的内存映像,然后执行一件事,然后看看发生了什么变化。可能会有一些变化,但应该有一些模式需要寻找。例如,转储内存、射击、转储内存、再次射击、转储内存、重新加载。然后寻找变化并了解弹药的存储位置/方式。对于健康来说,情况类似,但会有更多变化(因为你至少要搬家)。不过,在最小化“外部影响”的情况下,这样做是最容易的例如,不要因为发生了很多事情而试图在交火期间区分内存转储,当你站在熔岩中,或从建筑物上摔下来,或类似的事情时,进行区分。

    发现访问指针非常麻烦,静态内存值很难适应不同的编译器或游戏版本

    使用malloc()和free()的API挂钩,等等。有一种不同于以下指针的方法。发现从记录所有动态内存分配和并行执行内存搜索开始。然后,找到的堆内存地址与记录的内存分配进行反向匹配。您可以了解对象的大小以及对象内值的偏移量。您可以用回溯方法获取这个,得到一个MalCube()调用的跳回代码地址或C++构造函数。用这个信息,你可以跟踪和修改从那里分配的所有对象。你可以把对象转储并比较它们,找到很多更有趣的值。例如,通用精英游戏教练机“UGRACE”。在Linux上是这样的。它使用LD_预加载。 自适应的工作原理是基于“objdump-D”的反汇编,只需搜索包含已知内存大小的库函数调用

    见:

    Ugtrain来源:

    malloc()钩子如下所示:

    static __thread bool no_hook = false;
    
    void *malloc (size_t size)
    {
        void *mem_addr;
        static void *(*orig_malloc)(size_t size) = NULL;
    
        /* handle malloc() recursion correctly */
        if (no_hook)
            return orig_malloc(size);
    
        /* get the libc malloc function */
        no_hook = true;
        if (!orig_malloc)
            *(void **) (&orig_malloc) = dlsym(RTLD_NEXT, "malloc");
    
        mem_addr = orig_malloc(size);
    
        /* real magic -> backtrace and send out spied information */
        postprocess_malloc(size, mem_addr);
        no_hook = false;
    
        return mem_addr;
    }
    

    但是,如果找到的内存地址位于可执行文件或内存中的库中,那么ASLR很可能是动态的原因。在Linux上,库是PIC(位置独立代码),在最新发行版中,所有可执行文件都是PIE(位置独立可执行文件).

    你需要通过查找来找到该区域。因此,找到它附近的东西。找到一些提示,表明你正在“靠近”你想要的区域。也就是说,现在的工作是确定内存的布局、内存中保存的内容以及你具体要找的内容(以及它的外观)。有趣的是,知道这一点会很酷。虽然我猜操作系统内存保护功能已经到位,可以保护访问非其自身内存的程序。尽管培训师必须设法解决这一问题!是的,如果想避免自己死亡,这是相当直截了当的事情,但我不想阅读/更改实际值e,而不是取消它不是那么常见,但你可以抓住地址的加法