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


16

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

また、最初にptraceを使用して添付した後/proc/$pid/mem/proc/$pid/mapsファイルから抽出されたスタックの境界から読み取りを試みました(ここで提案されています)が、読み取りが失敗し続けますプロセスのさまざまな部分(ヒープなど)から読み取ります。

何が間違っていますか?他のオプションはありますか?


あなたは電話したwaitpidptrace(PTRACE_ATTACH,…)read(そうでない場合があります可能な競合状態)?どのエラーがread返されますか?子はそのメモリマッピングに特有のことをしていますsleepか。コードを次のような単純な子で試してみることができますか?
ジル 'SO-邪悪なことをやめる'

ptraceの後にwaitを使用し、子にscanfを入れて強制的に待機させました。
user4537

これはLinuxのみですか?Solarisには/ procファイルシステムもありますが、哲学的にはLinuxとはまったく異なります。多くの「バイナリファイル」。
ブルースエディガー

system( "pstack pid ")を実行し、出力を解析します..
vrdhn

参照してください。完全なコマンドが長すぎる:psのいくつかの例のために
ステファンChazelas

回答:


5

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;
}

こんにちはSam、あなたのコードは(実際に私が現在行っていることですが)実行しますが、パフォーマンスに大きなオーバーヘッドがあります。
user4537

@ user4536:なるほど。私はそれを書き留める時間があるときに投稿する別の戦略を念頭に置いています。あなたの典型的なスタックサイズは?
サムホセバー

私の研究では特定のスタックサイズを想定していないため、本当に言うのは難しいですが、この議論のために、少なくとも数ページの長さを言ってみましょう。あなたの戦略に関するヒントを教えてください。とにかく助けてくれてありがとう!
-user4537

1

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

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

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

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



1

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


1
本当にmemsそうmapsですか?(ファイルシステムのmems下にエントリが表示されません/proc。)OPは既にスタック境界の読み取りについて言及/proc/$pid/mapsしていますが、それらは異なる方法を提案していますか?
JigglyNaga

タイプミスを編集しました。私は答えで言及したとおりに行い、132 KBのスタックデータをダンプしました。OPが何を間違えたかについての詳細情報が必要です。たぶん、OPはスタック境界の読み取りに使用したコードを共有できます。彼が返事をしなければ、私は私のものを共有します。
アジェイブラフマクシャトリヤ16

0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.