访问另一个程序的值

时间:2013-03-27 00:27:37

标签: c++ windows reverse-engineering

所以,我一直想知道如何使用我的c ++代码访问不同程序的值。

我知道我必须知道内存位置并以某种方式访问​​它,但我不知道如何。

让我们说我有一个游戏,我有一个具有一定健康状态的角色,我想用我的c ++代码读取健康状况(类似于你如何使用作弊引擎读取不同的值程序)。

我将如何做到这一点?

为清楚起见:操作系统是windows

3 个答案:

答案 0 :(得分:7)

您可以使用ReadProcessMemory / VirtualQuery(比ReadProcessMemory更安全)和WriteProcessMemory函数。

如果你很聪明,你可以注入一个DLL,那么你可以在代码中使用指针

int * money = 0x00400000+0x00ABCDEF;//pointer to money address
*money = 5000;//set money to 5000.

如果您需要DLL示例,请参阅以下内容:

Red Alert 3 Player Information Mod

Need for Speed: Underground 2 cheat mod

有时指针可以改变他们所指向的内容,就应用而言,这可能是“危险的”。

当您访问指向受保护的内存区域的指针,无法访问的内存,而不是您想要的内容或应用程序可能崩溃的无效位置时。我不知道Cheat Engine是如何阻止它的,但你有一些选择,我建议的那些:

  • 正常退出应用程序并让用户知道您无法处理它
  • 使用try / catch块处理问题? (一定要捕获正确的错误)
  • 硬退出应用程序
  • 什么也不做,让应用程序表现得很奇怪/崩溃
  • ...越来越多

我自己编写了指针类来处理解除引用并在遇到错误时停止(返回null)

//null as last parameter automaticly "Dereferences"
template<class T = DWORD, class S = DWORD> struct Pointer
{
private:
    std::vector<S> params;
    S variable;
    bool MoreThanOne;
public:
    //null as last parameter automaticly "Dereferences"
    template<class... Args> 
    Pointer(Args... args) 
    {  
        std::array<S, sizeof...(args)> list = {args...};
        for( auto i : list)
            params.push_back(i);
        if(params.size() > 1)
            MoreThanOne = true;
        else
            MoreThanOne = false;
    }
    T ResolvePointer() 
    {  
        variable = params[0];
        if(!MoreThanOne)
            return (T)variable;
        try
        {
            auto it = params.begin();
            ++it;  
            for(; it != params.end(); ++it)
            {
                if(*reinterpret_cast<S*>(variable) == NULL)
                    return static_cast<T>(NULL);
                variable = *reinterpret_cast<S*>(variable) + *it;
            }
        }
        catch(...)
        {   
            return static_cast<T>(NULL);
        }
        return (T)variable;
    }
    T operator()()
    {
        return ResolvePointer();
    }
};

用法:

unsigned long ipaddr = htonl(Pointer<unsigned long>(0x00400000+0x008E3A74,0x04,0x38,NULL)());//pointer to players IP address
if(ipaddr != NULL)//....

答案 1 :(得分:0)

如果不使用特定的IPC机制,则不应写入其他进程的内存空间。操作系统通常会出于显而易见的原相反,您需要使用目标应用程序的扩展机制,或者反编译/修改/十六进制编辑来实现您想要的更改。话虽如此,这样做可能违反了您正在搞乱的软件的服务条款。

要清楚,代码将编译得很好,让你设置指向任何你喜欢的任意地址的指针,但是一旦你尝试读取或写入该地址,操作系统就会介入并导致错误条件。

如果您没有通过这样做违反软件EULA,可以参考以下内容找到您想要修改的内容:

  • 如果代码可以反编译成某种可读的源代码形式,请执行此操作并在那里进行修改。
  • 使用十六进制编辑器编辑已编译的二进制文件,查找明确定义的值并更改它们(max_health总是从25开始?这可能是唯一足以定位和修改的值)。关于这一点的注意事项:确保要插入的值与原始值相同,否则会破坏事物并产生未定义的结果。
  • 应用程序是否提供了扩展机制,例如脚本API或mod支持?如果是这样,这可以是用于引起所需系统更改类型的向量。

答案 2 :(得分:0)

除非:

,否则您无法访问其他流程中的变量
  1. 您的程序使用“调试功能”来访问值。
  2. 您使用某种IPC(共享内存,管道,消息队列)来共享/传输数据。
  3. 每个进程都有自己的地址空间[1],如果没有一些访问它的机制,就无法访​​问另一个进程的地址空间。

    [1]假设我们正在讨论使用适当内存管理的“真正”操作系统。在某些操作系统中,例如传统的DOS,进程之间没有内存保护。但是没有理智的人使用这些操作系统,除非系统使用非常微弱的处理器和少量内存运行。