Başka bir işlemin yığınını mı okudunuz?


16

Bir alt sürecin yığınını okumaya çalışıyorum ama şanssız. Bunu kullanarak mümkün olduğunu biliyorum ptrace, ama ptrace's arayüzü bir kerede sadece bir kelime okumak için izin verir, ve ben yığın daha büyük bir bölümünü taramaya çalışıyorum.

Ben de ( burada önerildiği gibi ) eklemek için ptrace kullandıktan sonra dosyadan ayıklandığı /proc/$pid/memgibi yığının sınırlarını okuma denedim ama aynı kod denendiğinde başarılı olmasına rağmen (kök olarak çalışırken bile) okuma başarısız tutar sürecin farklı bölümlerinden okuma (örn. yığın)./proc/$pid/maps

Neyi yanlış yapıyorum? Başka seçenek var mı?


Eğer aradın waitpidarasında ptrace(PTRACE_ATTACH,…)ve read(Aksi orada olası bir yarış durumu)? Hangi hata readgeri dönüyor? Çocuk bellek eşlemesiyle kendine özgü bir şey yapıyor sleepmu? Kodunuzu basit bir çocukla deneyebilir misiniz ?
Gilles 'SO- kötü olmayı kes'

Ben ptrace sonra beklemek kullandım ve çocuğu beklemeye zorlamak için bir scanf koydum.
user4537

Bu sadece Linux'ta mı? Solaris ayrıca bir / proc dosya sistemine sahiptir, ancak felsefi olarak Linux'tan tamamen farklıdır. Çok sayıda "ikili dosyalar".
Bruce Ediger

sadece bir sistem ("pstack pid ") yapın ve çıktıyı ayrıştırın ..
vrdhn

Bkz. Ps: tam komut bazı örnekler için çok uzun
Stéphane Chazelas

Yanıtlar:


5

ptrace'ın arayüzü bir kerede sadece bir kelime okumak için izin verir ve ben yığının daha büyük bir bölümünü taramaya çalışıyorum

O zaman bir döngü kullanın. Dürüst olmak gerekirse bunun nasıl bir sorun oluşturduğunu görmüyorum ptrace, süreçlere uzaktan erişmek için her zaman kullanıyorum.

Böyle bir şey kullanıyorum:

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

Merhaba Sam, kodunuz yapsa da (ve şu anda yaptığım şey budur), büyük bir performans yükü vardır.
user4537 13:30

@ user4536: Anlıyorum. Aklıma başka bir stratejim daha var. Tipik yığın boyutlarınız nelerdir?
sam hocevar

Araştırmam belirli bir yığın boyutu üstlenmediği için gerçekten zor, ancak bu argüman uğruna en az birkaç sayfa uzunluğunda diyelim. Stratejinizle ilgili bir ipucu bırakabilir misiniz? Yardımlarınız için teşekür ederim!
user4537

1

İşte ince ayar gerektirebilecek, ancak büyük veri yığınlarıyla daha verimli olması gereken başka bir strateji. Fikir, yığın içeriğini almak için uzak süreçte sistem çağrılarını yürütmektir. Belirli bir mimari kod gerektirecektir, ancak yalnızca x86 / x86_64'ü hedeflerseniz çok fazla güçlük çekmemelidir.

  1. "/tmp/fifo"Arama işleminiz gibi adlandırılmış bir kanal oluşturun .
  2. Şu anda yürütülen op kodunu beklemek ve / kontrol etmek PTRACE_SYSCALLiçin adım adım kullanarak bir sistem çağrısından geri dönünceye kadar izlenen işleme adım atın .waitpid()PTRACE_GETREGSPTRACE_PEEKTEXT
  3. Uzak işlemin kayıtlarını ve yığının küçük bir alanını yedekleyin.
  4. Kendi verilerle etrafa geçersiz kılarak uzak süreci hakkında syscalls yürütün: open("/tmp/fifo"), write()yığın içeriği, close()tanımlayıcısı.
  5. Uzak işlemin durumunu geri yükleyin.
  6. Çağrı sürecinizden fifo verilerini okuyun.

İsimli boruya daha zarif alternatifler olabilir, ancak şu anda herhangi bir şey düşünemiyorum. Sadece syscalls kullanmamın nedeni, çeşitli güvenlik korumaları nedeniyle modern sistemlerde uzaktan kod enjeksiyonunun oldukça güvenilmez olmasıdır. Dezavantajı, uzak işlem bir sistem çağrısı yapana kadar askıda kalmasıdır (bu, çoğunlukla hesaplama yapan bazı programlar için bir sorun olabilir).

Bu kaynak dosyadaki çalışmaların çoğunu uygulayan bazı ücretsiz kodları görebilirsiniz . Kod hakkında geri bildirim bekliyoruz!



1

Proc dosya sistemini kullanarak başka bir işlemin yığınını kolayca okuyabilirsiniz (Bunun için root erişimine ihtiyacınız olacaktır). / Proc / pid / mem öğesinden keyfi olarak okumadan önce / proc / pid / haritalarına başvurmanız gerekir. Bu dosyada basit bir okuma çok sayıda girdi gösterir. Yığın olarak işaretlenen girdiyle ilgileniyoruz. Bunu aldıktan sonra, yığının alt ve üst sınırlarını okumalısınız. Şimdi / proc / pid / mem dosyasını açın, yığının alt sınırını arayın ve doğru veri boyutunu okuyun.


1
Kastettiğinden emin memsdeğil mapsmisin? ( Dosya sistemim memsaltında herhangi bir girdi göremiyorum /proc.) OP zaten yığın sınırlarını okurken bahsetti /proc/$pid/maps- farklı bir şekilde ne yapmayı öneriyorsunuz?
JigglyNaga

Yazım hatası düzenledi. Cevabımda tam olarak söylediğim şeyi yaptım ve 132 KB'lık yığın verisi döktü. OP'nin neyi yanlış yaptığı hakkında daha fazla bilgiye ihtiyacımız var. Belki OP yığın sınırlarını okumak için kullandığı kodu paylaşabilir. Cevap vermezse, benimkini paylaşacağım.
Ajay Brahmakshatriya

0

Sen lsstack deneyebilirsiniz . Diğer başarılı "başka bir sürecin yığınını oku" programı gibi ptrace kullanır. Çalışmak için / proc / $ pid / mem okuma kullanarak bir program alamadım. İnanıyorum ki, bu şekilde yapamazsınız, ancak mantıklı olarak yapmalısınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.