निर्धारित करें कि क्या एक विशिष्ट प्रक्रिया 32- या 64-बिट है


14

एक 2.6.x या नए लिनक्स कर्नेल और मौजूदा यूज़रलैंड को देखते हुए, जो ELF32 और ELF64 बायनेरिज़ (यानी अच्छी तरह से अतीत दोनों को चलाने में सक्षम है) मुझे कैसे पता चलेगा कि मेरा सीपीयू लिनक्स के तहत 64 बिट ऑपरेटिंग सिस्टम का समर्थन करता है? अगर मैं किसी निर्धारित प्रक्रिया को कैसे निर्धारित कर सकता हूं ? PID द्वारा) 32- या 64-बिट मोड में चल रहा है?

भोला समाधान चलाने के लिए होगा:

file -L /proc/pid/exe | grep -o 'ELF ..-bit [LM]SB'

लेकिन क्या वह जानकारी /procबिना भरोसा किए सीधे उजागर हो जाती है libmagic?

जवाबों:


21

यदि आप खुद को ELF डिटेक्शन तक सीमित रखना चाहते हैं, तो आप खुद का ELF हेडर पढ़ सकते हैं /proc/$PID/exe। यह काफी तुच्छ है: यदि फ़ाइल में 5 वीं बाइट 1 है, तो यह 32-बिट बाइनरी है। यदि यह 2 है, तो यह 64-बिट है। अतिरिक्त संन्यास जाँच के लिए:

  1. यदि पहले 5 बाइट्स हैं 0x7f, "ELF", 1: यह एक 32 बिट ईएलएफ बाइनरी है।
  2. यदि पहले 5 बाइट्स हैं 0x7f, "ELF", 2: यह 64 बिट ईएलएफ बाइनरी है।
  3. अन्यथा: यह अनिर्णायक है।

आप भी उपयोग कर सकते हैं objdump, लेकिन यह आपकी libmagicनिर्भरता को दूर ले जाता है और इसे एक के साथ बदल देता है libelf

दूसरा तरीका : आप /proc/$PID/auxvफ़ाइल को पार्स भी कर सकते हैं । के अनुसार proc(5):

इसमें ईएलएफ दुभाषिया जानकारी शामिल है जो प्रक्रिया के समय निष्पादित की जाती है। प्रारूप एक अहस्ताक्षरित लंबी ID है और प्रत्येक प्रविष्टि के लिए एक अहस्ताक्षरित लंबी मान है। अंतिम प्रविष्टि में दो शून्य हैं।

unsigned longकुंजियों के अर्थ में हैं /usr/include/linux/auxvec.h। तुम चाहते हो AT_PLATFORM, जो है 0x00000f। उस पर मुझे उद्धृत न करें, लेकिन ऐसा लगता है कि मूल्य को char *प्लेटफॉर्म के स्ट्रिंग विवरण को प्राप्त करने के लिए व्याख्या किया जाना चाहिए ।

आपको यह StackOverflow प्रश्न उपयोगी लग सकता है।

फिर भी एक और तरीका : आप गतिशील लिंकर ( man ld) को निष्पादन योग्य के बारे में जानकारी डंप करने का निर्देश दे सकते हैं । यह मानक आउटपुट को डिकोड किए गए AUXV संरचना को प्रिंट करता है। चेतावनी: यह एक हैक है, लेकिन यह काम करता है।

LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1

यह कुछ इस तरह दिखाएगा:

AT_PLATFORM:     x86_64

मैंने इसे 32-बिट बाइनरी पर आज़माया और इसके i686बजाय मिला ।

यह कैसे काम करता है: LD_SHOW_AUXV=1निष्पादन योग्य चलाने से पहले डीकोड किए गए एयूएक्सवी संरचना को डंप करने के लिए डायनामिक लिंकर को निर्देश देता है। जब तक आप वास्तव में अपने जीवन दिलचस्प बनाने के लिए चाहते हैं, तो आप से बचना चाहते हैं वास्तव में चल रहा निष्पादन कहा। लोड करने और गतिशील रूप से लिंक करने का एक तरीका वास्तव में अपने main()फ़ंक्शन को कॉल किए बिना ldd(1)उस पर चलना है। नकारात्मक पक्ष: LD_SHOW_AUXVशेल द्वारा सक्षम किया गया है, इसलिए आपको इसके लिए AUXV संरचनाओं के डंप मिलेंगे: सबस्क्रिप्शन ldd, और आपका लक्ष्य बाइनरी। तो हम grepAT_PLATFORM के लिए, लेकिन केवल अंतिम पंक्ति रखते हैं।

पार्सिंग ऑक्सव : यदि आप auxvसंरचना को खुद को पार्स करते हैं (डायनेमिक लोडर पर निर्भर नहीं), तो इसमें थोड़ी गड़बड़ी है : संरचना auxvउस प्रक्रिया के नियम का पालन करती है, इसलिए sizeof(unsigned long)32-बिट प्रक्रियाओं के लिए 4 और 64 के लिए 8 होगी -बिट प्रक्रियाएं। यह काम हम अपने लिए कर सकते हैं। 32-बिट सिस्टम पर काम करने के लिए, सभी कुंजी कोड 0xffffffffकम या ज्यादा होने चाहिए । 64-बिट सिस्टम पर, सबसे महत्वपूर्ण 32 बिट्स शून्य होगा। इंटेल मशीन थोड़े एंडियन हैं, इसलिए ये 32 बिट्स मेमोरी में कम से कम महत्वपूर्ण हैं।

जैसे, आपको बस इतना करना है:

1. Read 16 bytes from the `auxv` file.
2. Is this the end of the file?
3.     Then it's a 64-bit process.
4.     Done.
5. Is buf[4], buf[5], buf[6] or buf[7] non-zero?
6.     Then it's a 32-bit process.
7.     Done.
8. Go to 1.

मैप्स फ़ाइल को पार्स करना : यह गिल्स ने सुझाया था, लेकिन काफी काम नहीं किया। यहाँ एक संशोधित संस्करण है जो करता है। यह /proc/$PID/mapsफ़ाइल को पढ़ने पर निर्भर करता है । यदि फ़ाइल 64-बिट पतों को सूचीबद्ध करती है, तो प्रक्रिया 64 बिट्स है। अन्यथा, यह 32 बिट्स है। समस्या यह है कि कर्नेल 4 के समूहों में हेक्स पतों से अग्रणी जीरो को अलग करके आउटपुट को सरल करेगा, इसलिए लंबाई हैक काफी काम नहीं कर सकता है। awkबचाव के लिए:

if ! [ -e /proc/$pid/maps ]; then
    echo "No such process"
else
    case $(awk </proc/$pid/maps -- 'END { print substr($1, 0, 9); }') in
    *-) echo "32 bit process";;
    *[0-9A-Fa-f]) echo "64 bit process";;
    *) echo "Insufficient permissions.";;
    esac
 fi

यह प्रक्रिया के अंतिम मेमोरी मैप के शुरुआती पते की जांच करके काम करता है। वे की तरह सूचीबद्ध हैं 12345678-deadbeef। इसलिए, यदि प्रक्रिया एक 32-बिट है, तो वह पता आठ हेक्स अंक लंबा होगा, और नौवां एक हाइमेन होगा। यदि यह 64-बिट वाला है, तो उच्चतम पता इससे अधिक लंबा होगा। नौवां वर्ण हेक्स अंक होगा।

ध्यान रखें: पहले और आखिरी तरीकों को लिनक्स कर्नेल 2.6.0 या नए की जरूरत है, क्योंकि auxvफ़ाइल पहले नहीं थी।


1
हम्म, मुझे आश्चर्य है कि अगर ईएलएफ हेडर में है /proc/[pid]/auxv: "ईएलएफ दुभाषिया जानकारी निष्पादन समय पर प्रक्रिया के लिए पारित कर दिया। प्रारूप एक अहस्ताक्षरित लंबी आईडी है और प्रत्येक प्रविष्टि के लिए एक अहस्ताक्षरित लंबी कीमत है" ( man proc)।
गोल्डीलॉक्स

1
हेडर ही नहीं है। मैं सिर्फ hdएक एड करता हूं और इसमें मैजिक नंबर की कमी है। वहाँ कुछ प्रासंगिक जानकारी हो सकती है, लेकिन मुझे लगता है कि यह स्वयं ELF हैडर की तुलना में अधिक लगातार परिवर्तनों के अधीन होगा। इसे 2.6.0 में भी पेश किया गया था, इसलिए यह उतना सर्वव्यापी नहीं है जितना कि /proc/PID/exe। लेकिन यह करता है वास्तुकला जानकारी नहीं है। मैं अपना जवाब अपडेट करूंगा।
एलेक्सिओस

ऑक्सव मुझे पता था कि ट्रिकियर की तुलना में बदल गया है - sizeof(unsigned long)8 64 बिट पर 4 या 32 बिट पर 4 है जिसका मतलब है कि इसे सही ढंग से व्याख्या करने के लिए आपको यह जानना होगा कि क्या प्रक्रिया 64 बिट या 32 बिट के साथ शुरू होती है!
फ्लेक्सो

आप बिल्कुल सही कह रहे है। यह बहुत कष्टप्रद है। त्वरित अनुमानी: यदि बाइट्स 16x + y (4≤y )7) फ़ाइल में सभी शून्य हैं, तो आप 64-बिट निष्पादन योग्य देख रहे हैं। यह एक कीचड़ है: मैं थोड़ा एंडियन मशीन मान रहा हूं, और यह कि सभी auxvकुंजी कोड एक 32-बिट फिट करते हैं unsigned long, इसलिए 64-बिट बॉक्स पर सबसे महत्वपूर्ण 32-बिट शून्य होगा।
एलेक्सिस

6

में देखो /proc/$pid/maps। पता श्रेणी 32-बिट पते (8 हेक्साडेसिमल अंक) या 64-बिट पते (16 हेक्साडेसिमल अंक) से अधिक हैं। यह किसी भी प्रकार के निष्पादन योग्य के लिए काम करता है, चाहे कोई भी प्रारूप हो। आप केवल उसी उपयोगकर्ता के रूप में चलने वाली प्रक्रियाओं के बारे में जानकारी प्राप्त कर सकते हैं (जब तक आप रूट नहीं होते हैं)।

if ! [ -e /proc/$pid/maps ]; then
  echo No such process
elif grep -q '^........[^-]' /proc/$pid/maps; then
  echo 64-bit
elif grep -q . /proc/$pid/maps; then
  echo 32-bit
else
  echo Insufficient permissions
fi

यदि आपके पास इस फ़ाइल तक पहुंचने की कोई अनुमति नहीं है, तो मुझे लगता है कि एकमात्र तरीका निष्पादन योग्य का विश्लेषण करने का प्रयास करना है। (जब आप हमेशा पढ़ सकते हैं /proc/$pid/stat, तो अलग-अलग उपयोगकर्ताओं के रूप में चलने वाली प्रक्रियाओं के लिए दिखाए जाने वाले क्षेत्रों में से कोई भी प्रक्रिया के बिट आकार को प्रकट नहीं करता है।) आप प्रक्रिया के निष्पादन योग्य होने का अच्छा अनुमान लगा सकते हैं ps -o comm=, और इसे देख सकते हैं PATH- लेकिन इस प्रक्रिया से सावधान रहें। एक अलग के साथ लॉन्च किया गया हो सकता है PATH, या फिर से लिखा जा सकता है argv[0]। फिर आप निष्पादन योग्य का विश्लेषण कर सकते हैं - यदि आप ईएलएफ ग्रहण करने के इच्छुक हैं, तो 5 वीं बाइट को देखें


मैंने आपकी रेसिपी का परीक्षण किया है और यह विफल रहा। OpenSuSE 12.2, x86-64, कर्नेल 3.4.63-2.44-डिफ़ॉल्ट, / बिन / बैश। बाइनरी और पहले हीप के लिए / proc / $ pid / मैप्स लाइनें 32-बिट शैली में लिखी गई हैं, लेकिन अन्य सभी 64-बिट शैली में हैं। संभवतः वे "% 08x" का उपयोग करके मुद्रित होते हैं, लेकिन वैसे भी यह नुस्खा समायोजित किया जाएगा।
Net

मुझे उन सभी बॉक्सों पर 8, 12 और 16-नायब वैल्यू का मिश्रण मिल रहा है, जिनके साथ मैंने इसकी कोशिश की थी। स्रोत की जाँच किए बिना, मेरा अनुमान है कि कर्नेल प्रत्येक पंक्ति के लिए एड्रेस रेंज की तुलना में सबसे कम 16-बिट्स के पैडिंग को समायोजित करता है, इसलिए आपको हेक्स वर्णों का सबसे लंबा अनुक्रम खोजना होगा, फिर जाँच करें।
एलेक्सिस

लेकिन, के बाद से vsyscallनक्शे को हमेशा सर्वोच्च है, तो आप यहां से मात्र में बदलाव के साथ मिल सकता है headकरने के लिए tail- जो, दुर्भाग्य से, काम क्योंकि proc को लागू नहीं करता है नहीं seek(2), तो यह, कुछ भद्दा होने के लिए की तरह होगाawk /proc/self/maps -- 'END { print substr($1, 0, 9); }'
Alexios

@ वास्तव में, मैंने बेवकूफी से vsyscall और स्टैक लाइनों को देखा और निष्पादन योग्य के मानचित्रण पर ध्यान नहीं दिया। धन्यवाद, मैंने किसी भी गैर-32-बिट लाइन को देखने के लिए अपडेट किया है। दया, यह बदसूरत है, लेकिन यह सबसे विश्वसनीय है (कम से कम यह x86 पर निश्चित रूप से आग है, मैंने अन्य दोहरे आर्किटेक्चर जैसे स्पार्क और आर्म के साथ जांच नहीं की है)।
गिलेस एसओ- बुराई को रोकना '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.