GNU/Linux >> Linux の 問題 >  >> Linux

Linux –Linuxで/proc / $ pid / memから読み取る方法は?

Linuxのproc(5) マニュアルページには、/proc/$pid/memと書かれています。 「プロセスのメモリのページにアクセスするために使用できます」。しかし、それを使用する簡単な試みは私にしか与えません

$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error

catではないのはなぜですか 独自のメモリを印刷できます(/proc/self/mem )?そして、シェルのメモリ(/proc/$$/mem)を印刷しようとすると、この奇妙な「そのようなプロセスはありません」というエラーは何ですか。 、明らかにプロセスが存在します)? /proc/$pid/memから読み取るにはどうすればよいですか 、じゃあ?

承認された回答:

/proc/$pid/maps

/proc/$pid/mem は、プロセスと同じ方法でマップされた$ pidのメモリの内容、つまりオフセット xのバイトを示しています。 疑似ファイル内は、アドレス xのバイトと同じです。 過程の中で。プロセスでアドレスがマップされていない場合、ファイル内の対応するオフセットから読み取ると、EIOが返されます。 (入出力エラー)。たとえば、プロセスの最初のページがマップされることはないため(NULLの逆参照) ポインタは、意図せずに実際のメモリにアクセスするのではなく、クリーンに失敗します)、/proc/$pid/memの最初のバイトを読み取ります 常にI/Oエラーが発生します。

プロセスメモリのどの部分がマップされているかを確認する方法は、/proc/$pid/mapsを読み取ることです。 。このファイルには、マップされた領域ごとに1行が含まれ、次のようになります。

08048000-08054000 r-xp 00000000 08:01 828061     /bin/cat
08c9b000-08cbc000 rw-p 00000000 00:00 0          [heap]

最初の2つの数字は、領域の境界です(最初のバイトと最後から次のバイトのアドレス(16進数))。次の列には権限が含まれています。これがファイルマッピングの場合は、ファイルに関する情報(オフセット、デバイス、iノード、名前)が表示されます。 proc(5)を参照してください 詳細については、manページまたはLinuxの理解/ proc / id/mapsを参照してください。

これは、独自のメモリの内容をダンプする概念実証スクリプトです。

#! /usr/bin/env python
import re
maps_file = open("/proc/self/maps", 'r')
mem_file = open("/proc/self/mem", 'rb', 0)
output_file = open("self.dump", 'wb')
for line in maps_file.readlines():  # for each mapped region
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    if m.group(3) == 'r':  # if this is a readable region
        start = int(m.group(1), 16)
        end = int(m.group(2), 16)
        mem_file.seek(start)  # seek to region start
        chunk = mem_file.read(end - start)  # read region contents
        output_file.write(chunk)  # dump contents to standard output
maps_file.close()
mem_file.close()
output_file.close()

/proc/$pid/mem

[以下は歴史的な興味のためです。現在のカーネルには適用されません。]

カーネルのバージョン3.3以降、/proc/$pid/memにアクセスできます。 通常は、マップされたオフセットでのみアクセスし、トレースする権限がある限り(ptraceと同じ権限) 読み取り専用アクセスの場合)。しかし、古いカーネルでは、いくつかの追加の問題がありました。

memから読み込もうとした場合 別のプロセスの疑似ファイル、それは機能しません:ESRCHを取得します (そのようなプロセスはありません)エラー。

/proc/$pid/memの権限 (r-------- )は、本来あるべきことよりもリベラルです。たとえば、setuidプロセスのメモリを読み取ることができないようにする必要があります。さらに、プロセスの変更中にプロセスのメモリを読み取ろうとすると、リーダーにメモリの一貫性のないビューが表示される可能性があり、さらに悪いことに、古いバージョンのLinuxカーネルをトレースできる競合状態が発生しました(このlkmlスレッドによると、私は詳細はわかりません)。したがって、追加のチェックが必要です:

  • /proc/$pid/memから読み取りたいプロセス ptraceを使用してプロセスにアタッチする必要があります PTRACE_ATTACHを使用 国旗。これは、デバッガーがプロセスのデバッグを開始するときに行うことです。 straceでもあります プロセスのシステムコールに対して行います。リーダーが/proc/$pid/memからの読み取りを終了したら 、ptraceを呼び出してデタッチする必要があります PTRACE_DETACHを使用 フラグ。
  • 監視対象のプロセスが実行されていない必要があります。通常、ptrace(PTRACE_ATTACH, …)を呼び出します ターゲットプロセスを停止します(STOPを送信します シグナル)、ただし競合状態(シグナル配信は非同期)があるため、トレーサーはwaitを呼び出す必要があります (ptrace(2)に記載されています 。
関連:NumLockを常にオンにしますか?

ルートとして実行されているプロセスは、ptraceを呼び出すことなく、任意のプロセスのメモリを読み取ることができます。 、ただし、監視対象のプロセスを停止する必要があります。そうしないと、読み取りは引き続きESRCHを返します。 。

Linuxカーネルソースでは、/procにプロセスごとのエントリを提供するコード fs/proc/base.cにあります 、および/proc/$pid/memから読み取る関数 mem_readです 。追加のチェックはcheck_mem_permissionによって実行されます 。

プロセスにアタッチしてmemのチャンクを読み取るサンプルCコードを次に示します。 ファイル(エラーチェックは省略):

sprintf(mem_file_name, "/proc/%d/mem", pid);
mem_fd = open(mem_file_name, O_RDONLY);
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid(pid, NULL, 0);
lseek(mem_fd, offset, SEEK_SET);
read(mem_fd, buf, _SC_PAGE_SIZE);
ptrace(PTRACE_DETACH, pid, NULL, NULL);

/proc/$pid/memをダンプするための概念実証スクリプトをすでに投稿しました 別のスレッドで。


Linux
  1. Linuxは複数の連続したパスセパレーター(/ home //// username /// file)をどのように処理しますか?

  2. Linux – / proc / pid / smapsからプロセスのメモリ使用量に関する情報を取得しますか?

  3. Unix / Linux でプロセスのパスを取得するにはどうすればよいですか

  1. CからLinuxでPIDによってプロセスのCPU使用率を計算する方法は?

  2. プロセスが実行されているフォルダーを見つける方法は?

  3. Linux で /proc/$pid/mem から読み取るにはどうすればよいですか?

  1. Linux – / proc // exeシンボリックリンクは通常のシンボリックリンクとどのように異なりますか?

  2. Linux – / procからインターフェイスのIpv4アドレスを取得する方法は?

  3. Linux のプロセスごとの swapiness を設定するには?