एक और प्रक्रिया का ढेर पढ़ें?


16

मैं एक बच्चे की प्रक्रिया के ढेर को पढ़ने की कोशिश कर रहा हूं, लेकिन भाग्य से नहीं। मुझे पता है कि इसका उपयोग करना संभव है ptrace, लेकिन ptraceइंटरफ़ेस आपको एक बार में केवल एक शब्द पढ़ने की अनुमति देता है, और मैं स्टैक के एक बड़े हिस्से को स्कैन करने की कोशिश कर रहा हूं।

मैंने इसे संलग्न करने के लिए पहली बार ptrace का उपयोग करने के बाद फ़ाइल /proc/$pid/memसे निकाले गए स्टैक की सीमाओं से पढ़ने की भी कोशिश की /proc/$pid/mapsहै (जैसा कि यहाँ सुझाव दिया गया है ) लेकिन यह पढ़ने में विफल रहता है (रूट के रूप में चलने पर भी) हालांकि एक ही कोड तब सफल होता है जब कोशिश की जाती है प्रक्रिया के विभिन्न भागों से पढ़ना (जैसे ढेर)।

मैं क्या गलत कर रहा हूं? क्या कोई और विकल्प है?


आप कॉल किया था waitpidके बीच ptrace(PTRACE_ATTACH,…)और read(एक संभव रेस स्थिति अन्यथा वहाँ)? क्या त्रुटि readवापस आती है? क्या बच्चा अपनी मेमोरी मैपिंग के साथ कुछ अजीब कर रहा है - जैसे आप एक साधारण बच्चे के साथ अपना कोड आज़मा सकते हैं sleep?
गिलेस एसओ- बुराई को रोकना '

मैंने ptrace के बाद वेट का उपयोग किया है, और मैंने इसे प्रतीक्षा करने के लिए मजबूर करने के लिए बच्चे में एक स्कैनफ़ डाल दिया है।
यूजर 4537

क्या यह केवल लिनक्स पर है? Solaris में एक / proc फाइलसिस्टम भी है, लेकिन यह लिनक्स से पूरी तरह अलग है, दार्शनिक रूप से। "बाइनरी फाइल" के बहुत सारे।
ब्रूस एडिगर

बस एक सिस्टम ("pstack pid ") करें और आउटपुट पार्स करें ..
vrdhn

जवाबों:


5

ptraceका इंटरफ़ेस आपको एक बार में केवल एक शब्द पढ़ने की अनुमति देता है, और मैं स्टैक के एक बड़े हिस्से को स्कैन करने की कोशिश कर रहा हूं

ठीक है, बस एक लूप का उपयोग करें, फिर। मैं ईमानदारी से यह नहीं देखता कि यह किस तरह की समस्या है 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;
}

हाय सैम, जबकि आपका कोड करेगा (और वास्तव में यही वह है जो मैं वर्तमान में कर रहा हूं), इसमें एक बड़ा प्रदर्शन ओवरहेड है।
user4537

@ user4536: मैं देख रहा हूं। मेरे पास एक और रणनीति है जिसे मैं उस समय पोस्ट करूँगा जब मेरे पास इसे लिखने का समय होगा। आपके विशिष्ट स्टैक आकार क्या हैं?
सैम होसेवर

वास्तव में यह कहना कठिन है क्योंकि मेरा शोध एक विशिष्ट स्टैक आकार नहीं मानता है, लेकिन इस तर्क के लिए कम से कम दो पृष्ठों का कहना है कि क्या आप अपनी रणनीति के बारे में एक संकेत छोड़ सकते हैं? फिर भी सहायता के लिए धन्यवाद!
उपयोगकर्ता 4537

1

यहां एक और रणनीति है जिसे ट्विक करने की आवश्यकता हो सकती है लेकिन डेटा के बड़े हिस्से के साथ अधिक कुशल होना चाहिए। स्टैक सामग्री को पुनः प्राप्त करने के लिए दूरस्थ प्रक्रिया में syscalls को निष्पादित करने का विचार है। इसके लिए विशिष्ट आर्किटेक्चर कोड की आवश्यकता होगी, लेकिन यदि आप केवल x86 / x86_64 को लक्षित करते हैं, तो यह बहुत अधिक परेशानी नहीं होनी चाहिए।

  1. "/tmp/fifo"अपनी कॉलिंग प्रक्रिया में एक नामित पाइप बनाएं ।
  2. ट्रेस प्रक्रिया में PTRACE_SYSCALLकदम रखें, जब तक कि यह एक syscall से वापस नहीं आता है, कदम का उपयोग करते हुए , waitpid()प्रतीक्षा करने और PTRACE_GETREGS/ PTRACE_PEEKTEXTवर्तमान में निष्पादित ओपेक की जांच करने के लिए।
  3. दूरस्थ प्रक्रिया के रजिस्टरों और इसके ढेर के एक छोटे से क्षेत्र का बैकअप लें।
  4. अपने खुद के डेटा के साथ अपने ढेर अधिभावी द्वारा दूरस्थ प्रक्रिया पर syscalls निष्पादित करें: open("/tmp/fifo"), write()ढेर सामग्री, close()वर्णनकर्ता।
  5. दूरस्थ प्रक्रिया की स्थिति को पुनर्स्थापित करें।
  6. अपनी कॉलिंग प्रक्रिया से डेटा को पढ़ें।

नामित पाइप के लिए अधिक सुरुचिपूर्ण विकल्प हो सकते हैं, लेकिन मैं अभी किसी के बारे में नहीं सोच सकता। कारण है कि मैं केवल syscalls का उपयोग करता हूं, क्योंकि विभिन्न सुरक्षा सुरक्षा के कारण रिमोट कोड इंजेक्शन आधुनिक प्रणालियों पर काफी अविश्वसनीय है। दोष यह है कि यह तब तक लटका रहेगा जब तक कि दूरस्थ प्रक्रिया एक syscall (जो कुछ कार्यक्रमों के लिए एक समस्या हो सकती है जो ज्यादातर कम्प्यूटेशन करते हैं)।

आप इस स्रोत फ़ाइल में अधिकांश काम को लागू करने वाले कुछ मुफ्त कोड देख सकते हैं । कोड पर प्रतिक्रिया का स्वागत है!


1

एक और सुझाव।

जब / अगर यह मुख्य लिनक्स कर्नेल ट्री में स्वीकार किया जाता है, तो आप क्रिस्टोफर येओह के क्रॉस मेमोरी अटैच पैच का उपयोग कर पाएंगे । उदाहरण के लिए process_vm_readv के लिए दस्तावेज़ देखें ।


1

आप खरीद फाइल सिस्टम का उपयोग करके किसी अन्य प्रक्रिया के स्टैक को आसानी से पढ़ सकते हैं (आपको इसके लिए रूट एक्सेस की आवश्यकता होगी)। / Proc / pid / mem से मनमाने ढंग से पढ़ने से पहले आपको / proc / pid / मैप से परामर्श करना होगा। इस फ़ाइल में एक सरल रीडिंग बहुत सी प्रविष्टियाँ दिखाती है। हम स्टैक के रूप में चिह्नित प्रविष्टि में रुचि रखते हैं। एक बार जब आप इसे प्राप्त करते हैं तो आपको स्टैक के निचले और ऊपरी सीमा को पढ़ने की आवश्यकता होती है। अब बस / proc / pid / मेम फ़ाइल खोलें, स्टैक के निचले हिस्से की तलाश करें और डेटा का सही आकार पढ़ें।


1
क्या आप सुनिश्चित हैं कि आपका मतलब memsऔर नहीं है maps? (मैं memsअपने /procफाइल सिस्टम के तहत कोई भी एंट्री नहीं देख सकता ।) ओपी ने पहले से ही स्टैक सीमाओं को पढ़ने का उल्लेख किया है /proc/$pid/maps- आप क्या सुझाव दे रहे हैं कि वे अलग तरीके से करते हैं?
JigglyNaga

टाइपो को संपादित किया। मैंने अपने उत्तर में ठीक वही किया है और इसने 132 KB स्टैक डेटा डंप किया। हमें अधिक जानकारी की जरूरत है कि ओपी ने क्या गलत किया। हो सकता है कि ओपी स्टैक की सीमाओं को पढ़ने के लिए इस्तेमाल किए गए कोड को साझा कर सकता है। अगर वह जवाब नहीं देता है, तो मैं उसे साझा करूंगा।
अजय ब्रह्मक्षत्रिय

0

आप lsstack की कोशिश कर सकते हैं । यह ptrace का उपयोग करता है, हर दूसरे सफल की तरह "अन्य प्रक्रिया के स्टैक को पढ़ें" प्रोग्राम। मुझे काम करने के लिए / proc / $ pid / मेम रीडिंग का उपयोग करके प्रोग्राम नहीं मिल सका। मेरा मानना ​​है कि आप इसे इस तरह से नहीं कर सकते, हालांकि, तार्किक रूप से, आपको करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.