1

別のプログラムのアドレスの値を見つける方法を見つける必要があります。事前にアドレスを見つけましたが、プログラムを閉じて再度検索せずに再度開いた後、それらを再度検索する方法がわかりません(プログラムが自分でそれらを見つける必要があります)。誰も私がこれを行うことができる方法を知っています (私が不明確である場合は申し訳ありませんが、実際に説明する方法がわかりません) 混乱している場合は、質問してください。明確にしようとします

C++を使用しています

4

5 に答える 5

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を使用して簡単に実行できます。ライブラリをダウンロードして、アンマネージ フックの例を参照してください。

于 2010-04-10T05:55:25.273 に答える
3

プログラムは、自身の変数のアドレスを非常に簡単に見つけることができます ( &variable)。協力している場合は、通常の IPC メカニズムによって他のプログラムに送信できます。ただし、他のプログラムは(通常)それを直接処理することはできません-少なくとも典型的なシステム(* BSD、Linux、Windowsなど)では、各プロセスには個別にメモリがマップされるため、1つのアドレス別のもので直接使用することはできません。

ほぼすべてが、あるプロセスのメモリに別のプロセスからアクセスできる何らかのデバッグ機能を提供しますが、その動作方法は大きく異なります。

于 2010-04-10T05:04:13.537 に答える
1

理論的には、ターゲットプログラムの動作とその内部データ構造を理解すれば、ターゲット変数のアドレスを見つけることができます。これは、実行時に動的に割り当てられるメモリの各1バイトは、静的に既知の情報から常に見つけることができるためです。関数内で発生した変数を除くコード。ただし、実際には、プログラムのバイナリ表現を調べてプログラムを理解することはほぼ不可能です。だからあなたは運が悪いです:-)

もう少し考え:

あなたがやろうとしていることを推測させてください:あなたは別のプロセスで整数のカウントダウンを止めたいのです。その場合は、ゲームツールで手動でアドレスを検索し、デバッガーでブレークポイントを設定してアドレスの書き込み時に一時停止し、ターゲットプログラムで可能なさまざまな操作でブレークポイントを発生させます。このようにして、値を減らしているコードを特定し、EXE/DLLを変更してこれらのコードを無効にすることができます。あなたが無効にした同じコードがあなたとあなたの対戦相手のエネルギーを減らすために使用されるので、ターゲットプログラムがより頻繁にクラッシュするか、あなたをもう楽しまない可能性があります:-)

于 2010-04-10T05:24:58.573 に答える
1

プログラムを閉じて再度開くと、アドレスはすべてランダム化されます。次回の実行時にアドレスを保存する方法はありません。

代わりに、どんなデータでもファイル構造を設計する必要があります。アドレス以外の方法で構造的な関係を表現してファイルに書き込み、それを読み戻すときにポインターリンクを復元します。これをシリアル化と呼びます。

于 2010-04-10T05:04:45.107 に答える