如何在内存中找到数据的地址?

时间:2010-04-10 04:59:20

标签: c++ memory-address

我需要找到一种方法来查找另一个程序的地址值。我手头找到了地址但我不知道如何在我关闭并重新打开程序之后再次找到它们而不再搜索它们(我需要程序在它上面找到它们)。 谁知道我怎么能这样做(对不起,如果我不清楚,我不知道如何解释它真的) 如果你的困惑只是问,​​我会尽力说清楚

即时使用C ++

5 个答案:

答案 0 :(得分:4)

假设您的平台是Windows,我发现将您自己的DLL注入目标进程很方便。从那里,您可以进行堆散步并查找值。获得之后,通过IPC将其发送回您的流程(例如,使用Boost的message_queue)。

修改

Blood ,正如您所要求的,这里有一些代码和值得思考的东西。 DLL本身非常简单,例如:


#include <Windows.h>

/** You can use this one to examine the given memory blocks.
  * However, since you're inside another process, you cannot use
  * std::cout. But you'll get the idea (just an example). The code
  * is from my another project.
  */
void MyDump(const void *m, unsigned int n)
{
        const unsigned char *p = reinterpret_cast<const unsigned char *>(m);
        char buffer[16];
        unsigned int mod = 1;

        memset(&buffer, 0, sizeof(buffer));

        std::cout << "------------------------------------------------------------------------------------\nOffset     | Hex                                                | ASCII            |\n------------------------------------------------------------------------------------\n0x" << std::setfill('0') << std::setw(8) << std::hex << (long)m << " |";

        for (unsigned int i = 0; i < n; ++i, ++mod) {
                buffer[i % 16] = p[i];

                --mod;

                if (mod % 4 == 0)
                        std::cout << " ";

                ++mod;

                std::cout << std::setw(2) << std::hex << static_cast<unsigned int>(p[i]) << " ";

                if ((mod == 16 && i != 0) || i == n - 1) {
                        if (i == n - 1) {
                                for (unsigned int j = 0; j < (16 - mod) * 3; ++j)
                                        std::cout << " ";

                                if (mod <= 4)
                                        std::cout << " ";

                                if (mod <= 8)
                                        std::cout << " ";

                                if (mod <= 12)
                                        std::cout << " ";
                        }

                        mod = 0;

                        std::cout << "| ";

                        for (unsigned short j = 0; j < 16; ++j) {
                                switch (buffer[j]) {
                                        case 0x7:
                                        case 0x8:
                                        case 0x9:
                                        case 0xa:
                                        case 0xb:
                                        case 0xd:
                                        case 0xe:
                                        case 0xf:
                                                std::cout << " ";

                                                break;

                                        default: std::cout << buffer[j];
                                }
                        }

                        std::cout << " |";

                        if (i == n - 1) {
                                std::cout << "\n------------------------------------------------------------------------------------\n";

                                return;
                        }

                        memset(&buffer, 0, sizeof(buffer));

                        std::cout << "\n0x" << std::setfill('0') << std::setw(8) << std::hex << (long)m + i << " |";
                }
        }
}

BOOL APIENTRY DllMain(HANDLE h_module, DWORD ul_reason_for_call, LPVOID)
{
        switch (ul_reason_for_call) {
                case DLL_PROCESS_ATTACH:
                        /** Do the heap walk here, please see
                          * http://msdn.microsoft.com/en-us/library/ee175819%28v=VS.85%29.aspx
                          * for enumerating the heap.
                          */

                        break;

                case DLL_THREAD_ATTACH: break;

                case DLL_THREAD_DETACH: break;

                case DLL_PROCESS_DETACH:
        }
}

现在您已拥有DLL,您仍需要将其注入所需的进程。使用EasyHook API可以轻松完成此操作。下载库并查看非托管挂钩的示例。

答案 1 :(得分:3)

程序可以非常轻松地找到自己变量的地址(&variable)。如果它在事物中合作,它可以通过一些正常的IPC机制将其发送到其他程序。另一个程序通常不会(通常)能够直接使用它 - 至少在一个典型的系统(* BSD,Linux,Windows等)上,每个进程都会分别映射内存,所以一个地址就在一个不能直接用于另一个。

几乎所有人都会提供某种调试功能,允许您从另一个进程访问一个进程的内存,但是它的工作原理差异很大。

答案 2 :(得分:1)

关闭并重新打开程序后,地址全部随机化。下次运行时无法保存地址。

相反,您需要为您拥有的任何数据设计文件结构。将其写入文件,以某种方式表达除地址之外的结构关系,并在读取时恢复指针链接。这称为序列化。

答案 3 :(得分:1)

理论上,如果您了解目标程序的工作方式及其内部数据结构,您可以找到目标变量的地址,因为在运行时动态分配的每个单字节内存始终可以从某些信息中找到除了源自函数内部的变量之外,代码静态地知道。然而,实际上,通过检查程序的二进制表示来理解程序几乎是不可能的。所以你运气不好: - )

多一点想法:

让我猜猜你要做什么:你想在另一个进程中停止一个整数倒计时。如果是这种情况,您可以通过游戏工具手动查找地址,然后通过调试器设置断点以在写入地址时暂停,然后通过目标程序中的不同可能操作使断点发生。这样,您可以确定哪些代码正在减少该值,并可能修改EXE / DLL以禁用这些代码。机会是目标程序会更频繁地崩溃或者不再招待你,因为你禁用的相同代码会降低你和你的对手的能量: - )

答案 4 :(得分:0)

如果您只想知道指针一次将其包含在代码中,您可以使用像cheatengine这样的程序来获取指针。