Baca tumpukan proses lain?

16

Saya mencoba membaca tumpukan proses anak tetapi tidak berhasil. Saya tahu itu mungkin menggunakan ptrace, tetapi ptraceantarmuka memungkinkan Anda untuk membaca hanya satu kata pada suatu waktu, dan saya mencoba untuk memindai bagian yang lebih besar dari tumpukan.

Saya juga mencoba membaca /proc/$pid/memdari batas stack yang diekstraksi dari /proc/$pid/mapsfile setelah terlebih dahulu menggunakan ptrace untuk melampirkannya (seperti yang disarankan di sini ) tetapi pembacaannya tetap gagal (bahkan ketika dijalankan sebagai root) meskipun kode yang sama berhasil ketika dicoba membaca dari berbagai bagian proses (misalnya tumpukan).

Apa yang saya lakukan salah? Apakah ada opsi lain?

pengguna4537
sumber
Apakah Anda menelepon di waitpidantara ptrace(PTRACE_ATTACH,…)dan read(jika tidak, ada kemungkinan kondisi balapan)? Kesalahan apa yang muncul read? Apakah anak melakukan sesuatu yang aneh dengan pemetaan memorinya - dapatkah Anda mencoba kode Anda dengan anak sederhana sleep?
Gilles 'SANGAT berhenti menjadi jahat'
Saya memang menggunakan wait setelah ptrace, dan saya telah memasukkan scanf pada anak untuk memaksanya menunggu.
user4537
Apakah ini hanya di Linux? Solaris juga memiliki sistem file / proc, tetapi sama sekali berbeda dari Linux, bahkan secara filosofis. Banyak "file biner".
Bruce Ediger
lakukan saja sistem ("pstack pid ") dan parsing output ..
vrdhn
Lihat ps: perintah penuh terlalu panjang untuk beberapa contoh
Stéphane Chazelas

Jawaban:

5

ptraceAntarmuka memungkinkan Anda membaca hanya satu kata setiap kali, dan saya mencoba memindai bagian tumpukan yang lebih besar

Nah, cukup gunakan satu lingkaran, lalu. Jujur saya tidak melihat bagaimana itu merupakan masalah dengan ptrace, saya menggunakannya sepanjang waktu untuk proses akses jarak jauh.

Saya menggunakan sesuatu seperti ini:

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 hocevar
sumber
Hai Sam, sementara kode Anda akan melakukan (dan sebenarnya itulah yang saya lakukan saat ini), ia memiliki overhead kinerja yang besar.
user4537
@ user4536: Begitu. Saya memiliki strategi lain yang akan saya posting ketika saya punya waktu untuk menuliskannya. Apa ukuran tumpukan khas Anda?
sam hocevar
Sulit dikatakan sebenarnya karena penelitian saya tidak mengasumsikan ukuran tumpukan tertentu, tetapi demi argumen ini, katakanlah setidaknya beberapa halaman panjangnya. Bisakah Anda memberikan sedikit petunjuk mengenai strategi Anda? Terima kasih atas bantuannya!
user4537
1

Berikut ini adalah strategi lain yang mungkin perlu diubah tetapi harus lebih efisien dengan potongan data yang besar. Idenya adalah untuk menjalankan syscalls dalam proses jarak jauh untuk mengambil isi stack. Ini akan memerlukan kode arsitektur khusus tetapi jika Anda hanya menargetkan x86 / x86_64 itu tidak boleh terlalu merepotkan.

  1. Buat pipa bernama seperti "/tmp/fifo"dalam proses panggilan Anda.
  2. Masuk ke proses yang dilacak sampai kembali dari syscall, gunakan PTRACE_SYSCALLuntuk melangkah, waitpid()untuk menunggu dan PTRACE_GETREGS/ PTRACE_PEEKTEXTuntuk memeriksa opcode yang saat ini dieksekusi.
  3. Cadangkan register proses jarak jauh dan area kecil tumpukannya.
  4. Jalankan syscalls pada proses remote dengan menimpa tumpukan dengan data Anda sendiri: open("/tmp/fifo"), write()isi stack, close()deskriptor.
  5. Pulihkan status proses jauh.
  6. Baca data fifo dari proses panggilan Anda.

Mungkin ada alternatif yang lebih elegan untuk pipa bernama, tapi saya tidak bisa memikirkan apa pun sekarang. Alasan saya hanya menggunakan syscalls adalah karena injeksi kode jarak jauh sangat tidak dapat diandalkan pada sistem modern karena berbagai perlindungan keamanan. Kekurangannya adalah ia akan hang sampai proses jarak jauh melakukan syscall (yang dapat menjadi masalah untuk beberapa program yang sebagian besar melakukan perhitungan).

Anda dapat melihat beberapa kode bebas menerapkan sebagian besar pekerjaan dalam file sumber ini . Umpan balik pada kode ini disambut baik!

sam hocevar
sumber
1

Saran lain.

Ketika / jika diterima di pohon kernel Linux utama, Anda akan dapat menggunakan tambalan Memori Salib Christopher Yeoh . Lihat dokumentasi untuk process_vm_readv misalnya.

sam hocevar
sumber
1

Anda dapat dengan mudah membaca tumpukan proses lain menggunakan sistem file proc (Anda akan memerlukan akses root untuk ini). Sebelum membaca sewenang-wenang dari / proc / pid / mem Anda perlu berkonsultasi dengan / proc / pid / maps. Bacaan sederhana dalam file ini menunjukkan banyak entri. Kami tertarik pada entri yang ditandai sebagai tumpukan. Setelah Anda mendapatkan ini, Anda perlu membaca batas bawah dan atas tumpukan. Sekarang cukup buka file / proc / pid / mem, cari batas bawah tumpukan dan baca ukuran data yang benar.

Ajay Brahmakshatriya
sumber
1
Apakah Anda yakin maksud Anda memsdan tidak maps? (Saya tidak dapat melihat memsentri di /procsistem file saya .) OP telah disebutkan membaca batas stack dari /proc/$pid/maps- apa yang Anda sarankan agar mereka lakukan secara berbeda?
JigglyNaga
Mengedit kesalahan ketik. Saya melakukan persis apa yang saya sebutkan dalam jawaban saya dan membuang 132 KB data tumpukan. Kami memerlukan lebih banyak info tentang kesalahan OP. Mungkin OP dapat membagikan kode yang digunakannya untuk membaca batas stack. Jika dia tidak menjawab, saya akan berbagi milik saya.
Ajay Brahmakshatriya
0

Anda bisa mencoba lsstack . Ini menggunakan ptrace, sama seperti setiap program "baca proses tumpukan lainnya" yang sukses. Saya tidak bisa mendapatkan program menggunakan / proc / $ pid / mem membaca untuk bekerja. Saya percaya bahwa Anda tidak dapat melakukannya dengan cara itu, meskipun, secara logis, Anda harus melakukannya.

Bruce Ediger
sumber