成功せずにサブプロセスのスタックを読み取ろうとします。私はうまくいくことを知っていますが、ptrace
インターフェースptrace
を使用すると一度に1つの単語しか読み取れませんが、スタックの大きな部分をスキャンしようとしています。
/proc/$pid/mem
また、提案されているように、ptraceを使用してファイルに最初に添付した後、ファイルから抽出されたスタック境界から読み取りを試みました。/proc/$pid/maps
ここ)しかし、プロセスの他の部分(ヒープなど)から読み取ろうとすると、同じコードが成功しても読み取りは失敗します(ルートとして実行しても)。
私は何が間違っていましたか?他のオプションがありますか?
答え1
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;
}
答え2
これは調整が必要な別の戦略ですが、大量のデータに対してより効果的です。アイデアは、スタックの内容を取得するためにリモートプロセスでシステムコールを実行することです。アーキテクチャ固有のコードが必要ですが、x86/x86_64のみを対象とする場合、大きな問題は発生しません。
"/tmp/fifo"
たとえば、呼び出しプロセスで名前付きパイプを作成します。PTRACE_SYSCALL
ステップ、waitpid()
待機、およびPTRACE_GETREGS
/PTRACE_PEEKTEXT
または現在実行されているオペコードを確認し、システムコールから返されるまで追跡されたプロセスに入ります。- リモートプロセスのレジスタとそのスタックの小さな領域をバックアップします。
open("/tmp/fifo")
自分のデータ(、write()
スタック内容、close()
記述子)でスタックを上書きして、リモートプロセスでシステムコールを実行します。- リモートプロセスの状態を復元します。
- 呼び出しプロセスからFIFOデータを読み込みます。
名前付きパイプにはよりエレガントな選択肢があるかもしれませんが、今はそれらを思い出していません。私がシステムコールのみを使用する理由は、さまざまなセキュリティ保護のためにリモートコード注入が最新のシステムではかなり信頼できないためです。欠点は、リモートプロセスがシステムコールを実行するまで停止することです(主に計算を実行する一部のプログラムでは問題になる可能性があります)。
以下では、ほとんどのことを行う無料のコードを見ることができます。このソースファイル。コードへのフィードバックを歓迎します!
答え3
別の提案。
メインLinuxカーネルツリーに承認されると、Christopher Yeohのクロスメモリ接続修理する。文書を見るprocess_vm_readv例えば。
答え4
あなたは試すことができますスタック。他のすべての成功した「他のプロセスのスタック読み取り」プログラムと同様に、ptraceを使用します。 /proc/$pid/mem 読み取りを使用してプログラムを操作することはできません。論理的にはそうしなければなりませんが、私はそうできないと信じています。