web-dev-qa-db-ja.com

別のプロセスのスタックを読みますか?

子プロセスのスタックを読み取ろうとしていますが、うまくいきません。 ptraceを使用してそれが可能であることはわかっていますが、ptraceのインターフェイスでは一度に1ワードのみを読み取ることができ、スタックの大部分をスキャンしようとしています。

スタックの境界から/proc/$pid/memを読み取ってみましたが、最初にptraceを使用してそれにアタッチした後(推奨 here )、スタックの/proc/$pid/mapsファイルから抽出されましたが、プロセスの異なる部分(ヒープなど)から読み取ろうとすると、同じコードは成功しますが、読み取りは(rootとして実行している場合でも)失敗し続けます。

私は何が間違っているのですか?他に選択肢はありますか?

17
user4537

ptraceのインターフェイスでは、一度に1ワードしか読み取ることができません。スタックの大部分をスキャンしようとしています

それでは、ループを使用してください。正直に言って、それがptraceの問題を構成する方法がわからないので、リモートアクセスプロセスに常に使用しています。

私はこのようなものを使用します:

static int memcpy_from_target(pid_t pid, char *dest, long src, size_t n)
{
    static int const align = sizeof(long) - 1;

    while (n)
    {
        size_t todo = MIN(n, sizeof(long) - (src & align));
        long data = ptrace(PTRACE_PEEKTEXT, pid, src - (src & align), 0);
        if (errno)
        {
            perror("ptrace_peektext (memcpy_from_target)");
            return -1;
        }
        memcpy(dest, (char *)&data + (src & align), todo);

        dest += todo; src += todo; n -= todo;
    }

    return 0;
}
5
sam hocevar

Procファイルシステムを使用して別のプロセスのスタックを簡単に読み取ることができます(これにはrootアクセスが必要です)。/proc/pid/memから任意に読み取る前に、/ proc/pid/mapsを参照する必要があります。このファイルを読み取るだけで、多数のエントリが表示されます。スタックとしてマークされたエントリに関心があります。これを取得したら、スタックの下限と上限を読み取る必要があります。次に、/ proc/pid/memファイルを開き、スタックの下限を探し、正しいサイズのデータ​​を読み取ります。

別の提案。

メインのLinuxカーネルツリーで受け入れられると、Christopher Yeohの Cross Memory Attach パッチを使用できるようになります。たとえば process_vm_readv のドキュメントを参照してください。

1
sam hocevar

これは、微調整が必​​要かもしれないが、データの大きなチャンクでより効率的になるはずの別の戦略です。スタックの内容を取得するために、リモートプロセスでsyscallsを実行するという考え方です。特定のアーキテクチャコードが必要ですが、x86/x86_64のみを対象とする場合は、それほど面倒ではありません。

  1. 呼び出しプロセスで"/tmp/fifo"などの名前付きパイプを作成します。
  2. トレースされたプロセスにステップインし、システムコールから戻るまで、PTRACE_SYSCALLを使用してステップし、waitpid()を使用して待機し、PTRACE_GETREGS/PTRACE_PEEKTEXTを使用して現在実行されているオペコードを確認します。
  3. リモートプロセスのレジスタとそのスタックの小さな領域をバックアップします。
  4. スタックを独自のデータopen("/tmp/fifo")write()スタックの内容、close()記述子でオーバーライドして、リモートプロセスでシステムコールを実行します。
  5. リモートプロセスの状態を復元します。
  6. 呼び出しプロセスからfifoデータを読み取ります。

名前付きパイプに代わるよりエレガントな方法があるかもしれませんが、今は考えられません。私がsyscallsだけを使用する理由は、リモートコードインジェクションは、さまざまなセキュリティ保護のため、最新のシステムではかなり信頼できないためです。欠点は、リモートプロセスがsyscallを実行するまでハングすることです(これは、主に計算を実行する一部のプログラムでは問題になる可能性があります)。

ほとんどの作業を実装している無料のコードが このソースファイル にあります。コードに関するフィードバックは大歓迎です!

1
sam hocevar

lsstack を試すことができます。他のすべての成功した「別のプロセスのスタックの読み取り」プログラムと同様に、ptraceを使用します。/proc/$ pid/mem読み取りを使用してプログラムを動作させることができませんでした。論理的にはそうすべきですが、そうすることはできないと思います。

0
Bruce Ediger