繁体   English   中英

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

[英]how to find the address of data in memory?

我需要找到一种方法来找到另一个程序的值的地址。 我先找到了地址,但关闭并重新打开程序后又不再次搜索它们,我不知道如何找到它们(我需要程序自己找到它们)。 任何人都知道我该怎么做(对不起,如果不清楚,我真的不知道如何解释),如果您感到困惑,只是问一下,我会尽力弄清楚

我正在使用C ++

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

编辑

, as you requested, here's a little code and a food for thought. ,按照您的要求,这里有一个小的代码和思想食品。 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可以轻松完成此操作。 下载该库,并查看非托管挂钩的示例。

程序可以很容易地找到其自身变量的地址( &variable )。 如果它在事物上协作,则可以通过某种常规IPC机制将其发送到其他程序。 但是,另一个程序通常无法直接执行很多操作-至少在典型的系统(* BSD,Linux,Windows等)上,每个进程将分别映射内存,因此一个地址位于一个内存中在另一个环境中不能直接使用。

几乎所有人都将提供某种调试功能,使您可以从另一个进程访问一个进程的内存,但是工作方式千差万别。

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

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

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

还有一点想法:

让我猜猜您要做什么:您想在另一个进程中停止倒数。 在这种情况下,您可以通过游戏工具手动找到地址,然后由调试器将断点设置为在写入地址时暂停,然后通过目标程序中的各种可能操作使断点发生。 这样,您可以确定哪些代码正在减小该值,并可能修改EXE / DLL以禁用这些代码。 目标程序很有可能会崩溃或不再招待您,因为您禁用的相同代码会减少您和对手的精力:-)

如果您只想一次了解该指针以将其包含在代码中,则可以使用诸如cheatengine之类的程序来获取该指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM