The Linux proc(5)
halaman manual memberitahu saya bahwa /proc/$pid/mem
“dapat digunakan untuk mengakses halaman memori proses ini”. Tetapi upaya langsung untuk menggunakannya hanya memberi saya
$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error
Mengapa tidak cat
dapat mencetak memorinya sendiri ( /proc/self/mem
)? Dan apa kesalahan "proses seperti ini" yang aneh ketika saya mencoba mencetak memori shell ( /proc/$$/mem
, jelas prosesnya ada)? Bagaimana saya bisa membaca /proc/$pid/mem
?
Jawaban:
/proc/$pid/maps
/proc/$pid/mem
memperlihatkan isi memori $ pid yang dipetakan dengan cara yang sama seperti dalam proses, yaitu byte pada offset x dalam file pseudo sama dengan byte pada alamat x dalam proses. Jika alamat tidak dipetakan dalam proses, bacalah dari offset yang sesuai dalam file yang dikembalikanEIO
(Kesalahan input / output). Sebagai contoh, karena halaman pertama dalam suatu proses tidak pernah dipetakan (sehingga dereferencingNULL
pointer gagal dengan bersih daripada mengakses memori yang sebenarnya), membaca byte pertama/proc/$pid/mem
selalu menghasilkan kesalahan I / O.Cara untuk mengetahui bagian mana dari memori proses yang dipetakan adalah dengan membaca
/proc/$pid/maps
. File ini berisi satu baris per wilayah yang dipetakan, terlihat seperti ini:Dua angka pertama adalah batas wilayah (alamat byte pertama dan byte setelah yang terakhir, dalam heksa). Kolom berikutnya berisi izin, lalu ada beberapa informasi tentang file (offset, perangkat, inode, dan nama) jika ini adalah pemetaan file. Lihat
proc(5)
halaman manual atau Memahami Linux / proc / id / maps untuk informasi lebih lanjut.Berikut ini skrip proof-of-concept yang membuang konten dari ingatannya sendiri.
/proc/$pid/mem
Jika Anda mencoba membaca dari file
mem
pseudo dari proses lain, itu tidak berfungsi: Anda mendapatkanESRCH
kesalahan (Tidak ada proses seperti itu).Izin pada
/proc/$pid/mem
(r--------
) lebih liberal daripada yang seharusnya. Misalnya, Anda seharusnya tidak dapat membaca memori proses setuid. Lebih jauh lagi, mencoba membaca memori suatu proses ketika proses memodifikasi itu dapat memberikan pembaca pandangan yang tidak konsisten dari memori, dan lebih buruk lagi, ada kondisi ras yang dapat melacak versi Linux kernel yang lebih lama (menurut utas lkml ini , meskipun saya tidak tahu detailnya). Jadi diperlukan pemeriksaan tambahan:/proc/$pid/mem
harus dilampirkan ke proses menggunakanptrace
denganPTRACE_ATTACH
bendera. Inilah yang dilakukan para debugger ketika mereka memulai proses debug; itu juga apa yangstrace
dilakukan untuk panggilan sistem suatu proses. Setelah pembaca selesai membaca dari/proc/$pid/mem
, pembaca harus melepaskan dengan memanggilptrace
denganPTRACE_DETACH
bendera.ptrace(PTRACE_ATTACH, …)
akan menghentikan proses target (mengirimkanSTOP
sinyal), tetapi ada kondisi balapan (pengiriman sinyal asinkron), sehingga pelacak harus meneleponwait
(seperti yang didokumentasikan dalamptrace(2)
).Sebuah proses yang berjalan sebagai root dapat membaca memori proses apa pun, tanpa perlu memanggil
ptrace
, tetapi proses yang diamati harus dihentikan, atau pembacaan akan tetap kembaliESRCH
.Dalam sumber kernel Linux, kode menyediakan entri per-proses di
/proc
dalamfs/proc/base.c
, dan fungsi untuk membaca dari/proc/$pid/mem
adalahmem_read
. Pemeriksaan tambahan dilakukan olehcheck_mem_permission
.Berikut ini beberapa contoh kode C untuk dilampirkan ke suatu proses dan membaca sebagian dari
mem
filenya (pengecekan kesalahan dihilangkan):Saya sudah memasang skrip proof-of-concept untuk dibuang
/proc/$pid/mem
di utas lain .sumber
/proc/$pid/mem
langsung (baik dengancat
ataudd
atau apa pun) tidak bekerja. Baca jawabanku./proc/self/mem
. Suatu proses dapat membaca ruang memorinya sendiri dengan baik, itu membaca ruang memori proses lain yang membutuhkanPTRACE_ATTACH
.process_vm_readv()
panggilan sistem (Linux 3.2).ESRCH
kesalahan dalam skenario ini.Perintah ini (dari gdb) membuang memori dengan andal:
Dump bisa besar, gunakan
-o outfile
jika direktori Anda saat ini tidak memiliki cukup ruang.sumber
Ketika Anda menjalankan
cat /proc/$$/mem
variabel$$
dievaluasi oleh oleh bash yang menyisipkan pid sendiri. Ini kemudian mengeksekusicat
yang memiliki pid berbeda. Anda berakhir dengancat
mencoba membaca memoribash
, proses induknya. Karena proses yang tidak istimewa hanya dapat membaca ruang memori mereka sendiri, ini ditolak oleh kernel.Ini sebuah contoh:
Catatan yang
$$
mengevaluasi ke 17823. Mari kita lihat proses mana yang.Ini shell saya saat ini.
Di sini lagi
$$
mengevaluasi ke 17823, yang merupakan shell saya.cat
tidak dapat membaca ruang memori shell saya.sumber
$pid
itu. Seperti yang saya jelaskan dalam jawaban saya, membaca memori dari proses yang berbeda mengharuskan Anda untuk memotongnya.$$
kapan Anda menulis (dan membaca)$pid
?$$
dan menempatkan$pid
di akhir. Saya memindahkannya di kepala saya tanpa menyadarinya. Seluruh jawaban saya seharusnya merujuk$$
, bukan$pid
.Berikut ini adalah program kecil yang saya tulis di C:
Pemakaian:
Program ini menggunakan / proc / $ pid / maps untuk menemukan semua wilayah memori yang dipetakan dari proses, dan kemudian membaca wilayah tersebut dari / proc / $ pid / mem, satu halaman sekaligus. halaman tersebut ditulis ke stdout atau alamat IP dan port TCP yang Anda tentukan.
Kode (diuji pada Android, memerlukan izin pengguna super):
sumber
write to stdout
tepat di atasfwrite(..., stdout)
. Lihat programmers.stackexchange.com/questions/119600/...