2012-04-10 23 views
9

मैं एक ऐसा एप्लिकेशन विकसित करने की कोशिश कर रहा हूं जो यह पता लगाता है कि प्रोग्राम वर्चुअल मशीन के अंदर चल रहा है या नहीं।64-बिट विंडोज़ वीएमवेयर पहचान

के लिए 32-बिट विंडोज, वहाँ पहले से ही तरीकों नीचे दिए गए लिंक में विस्तार से बताया है: http://www.codeproject.com/Articles/9823/Detect-if-your-program-is-running-inside-a-Virtual

मैं आभासी पीसी और एक 64-बिट विंडोज ऑपरेटिंग सिस्टम में VMware का पता लगाने के बारे में कोड अनुकूल करने के लिए कोशिश कर रहा हूँ। वीएमवेयर के लिए, कोड एक विंडोज एक्सपी 64-बिट ओएस में सफलतापूर्वक पता लगा सकता है। लेकिन जब मैं इसे मूल प्रणाली (विंडोज 7 64-बिट ओएस) में चलाता हूं तो प्रोग्राम क्रैश हो जाता है।

मैंने कोड को .asm फ़ाइल में रखा है और ml64.exe फ़ाइल के साथ कस्टम बिल्ड चरण को परिभाषित किया है। के लिए 64-बिट Windows एएसएम कोड है:

__try 
{ 
returnValue = IsInsideVM(); 
} 
__except(1) 
{ 
    returnValue = false; 
} 

अग्रिम धन्यवाद:

IsInsideVM proc 

     push rdx 
     push rcx 
     push rbx 

     mov rax, 'VMXh' 
     mov rbx, 0  ; any value but not the MAGIC VALUE 
     mov rcx, 10 ; get VMWare version 
     mov rdx, 'VX' ; port number 

     in  rax, dx ; read port 
         ; on return EAX returns the VERSION 
     cmp rbx, 'VMXh'; is it a reply from VMWare? 
     setz al   ; set return value 
     movzx rax,al 

     pop rbx 
     pop rcx 
     pop rdx 

     ret 
IsInsideVM endp 

मैं की तरह एक cpp फ़ाइल में इस हिस्से कहते हैं।

+1

वैसे हाँ, हार्डवेयर पोर्ट्स तक पहुंचने का प्रयास करना, जो एक विशेषाधिकार प्राप्त ऑपरेशन है, उपयोगकर्ता कोड में फंस जाएगा। आपको एसईएच का उपयोग करके अपवाद पकड़ने की जरूरत है। ऐसा लगता है कि आप कोशिश कर रहे हैं, लेकिन आपने (1) कंपाइलर विकल्प या (2) डीबगर ट्रेस नहीं दिखाया है। –

उत्तर

4

वर्ष लाल गोलीJoanna से काम कर सकते हैं: random backup page of invisiblethings.org blog:

निगल लाल गोली और अधिक या कम निम्नलिखित कोड के बराबर है (गैर रिटर्न शून्य जब मैट्रिक्स में):

int swallow_redpill() { 
    unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3"; 
    *((unsigned*)&rpill[3]) = (unsigned)m; 
    ((void(*)())&rpill)(); 
    return (m[5]>0xd0) ? 1 : 0; 
} 

इस कोड का दिल वास्तव में एसआईडीटी निर्देश (0F010D [addr] के रूप में एन्कोड किया गया है), जो गंतव्य ऑपरेंड में इंटरप्ट डिस्क्रिप्टर टेबल रजिस्टर (आईडीटीआर) की सामग्री संग्रहीत करता है, जो वास्तव में एक स्मृति स्थान है। एसआईडीटी निर्देश के बारे में विशेष और दिलचस्प क्या है कि इसे गैर विशेषाधिकार प्राप्त मोड (रिंग 3) में निष्पादित किया जा सकता है लेकिन यह संवेदनशील रजिस्टर की सामग्री देता है, जो ऑपरेटिंग सिस्टम द्वारा आंतरिक रूप से उपयोग किया जाता है।

क्योंकि केवल एक आईडीटीआर रजिस्टर है, लेकिन कम से कम दो ओएस एक साथ चल रहे हैं (यानी मेजबान और अतिथि ओएस), वीएमएम को अतिथि के आईडीटीआर को एक सुरक्षित स्थान पर स्थानांतरित करने की आवश्यकता है, ताकि यह संघर्ष न करे एक मेजबान का एक। दुर्भाग्यवश, वीएमएम यह नहीं जान सकता कि (और कब) अतिथि ओएस में चल रही प्रक्रिया एसआईडीटी निर्देश निष्पादित करती है, क्योंकि इसे विशेषाधिकार नहीं दिया जाता है (और यह अपवाद उत्पन्न नहीं करता है)। इस प्रकार प्रक्रिया को आईडीटी तालिका का स्थानांतरित पता मिलता है। यह देखा गया कि वीएमवेयर पर, आईडीटी का स्थानांतरित पता 0xffXXXXXX पते पर है, जबकि वर्चुअल पीसी पर यह 0xe8XXXXXX है। यह वीएमवेयर वर्कस्टेशन 4 और वर्चुअल पीसी 2004 पर परीक्षण किया गया था, दोनों विंडोज एक्सपी होस्ट ओएस पर चल रहे थे।

नोट: मैंने इसे स्वयं परीक्षण नहीं किया है लेकिन देखो कि यह एक अप्रतिबंधित दृष्टिकोण का उपयोग करता है। अगर यह पहले x64 के लिए काम नहीं करता है, तो कुछ ट्वीकिंग मदद कर सकती है। Detecting VMM on linux

0

मेरा अनुमान है अपने समारोह रजिस्टरों corrups है जो:

इसके अलावा, बस बाहर है कि आप मदद कर सकते हैं सामग्री के साथ एक सवाल मिल गया।

वास्तविक हार्डवेयर (गैर-वीएम) पर चलने से शायद "रैक्स, डीएक्स" में अपवाद ट्रिगर करना चाहिए। यदि ऐसा होता है तो नियंत्रण आपके अपवाद हैंडलर को पास किया जाता है, जो परिणाम सेट करता है, लेकिन रजिस्टरों को पुनर्स्थापित नहीं करता है। यह व्यवहार कॉलर द्वारा पूरी तरह अप्रत्याशित होगा। उदाहरण के लिए, यह कुछ ईबीएक्स/आरबीएक्स रजिस्टर में सहेज सकता है, फिर अपना एएसएम कोड कॉल करें, आपका एएसएम कोड "mov आरबीएक्स, 0" करता है, यह निष्पादित करता है, अपवाद पकड़ता है, परिणाम सेट करता है, रिटर्न देता है - और फिर कॉलर सुस्त रूप से महसूस करता है कि उसका सहेजा गया डेटा अब ईबीएक्स/आरबीएक्स में नहीं है!अगर ईबीएक्स/आरबीएक्स में कुछ पॉइंटर संग्रहीत किया गया था - तो आप कड़ी मेहनत करने जा रहे हैं। कुछ भी हो सकता है।

निश्चित रूप से, आपका एएसएम कोड रजिस्टरों को बचाता/पुनर्स्थापित करता है, लेकिन ऐसा तब होता है जब कोई अपवाद नहीं उठाया जाता है। अर्थात। यदि आपका कोड वीएम पर चल रहा है। फिर आपका कोड इसका सामान्य निष्पादन पथ करता है, कोई अपवाद नहीं उठाया जाता है, रजिस्टरों को सामान्य रूप से बहाल किया जाएगा। लेकिन अगर अपवाद है - आपके पीओपी छोड़ दिए जाएंगे, क्योंकि निष्पादन अपवाद हैंडलर को पास कर दिया जाएगा।

सही कोड संभवतः अंदर/अंदर ब्लॉक को छोड़कर/निकालने के बाहर पुश/पीओपी करना चाहिए।

+0

शायद 'setjmp' और' longjmp' का उपयोग जबरन रजिस्टरों और स्टैक पॉइंटर को संरक्षित करने के लिए किया जा सकता है (परिणामस्वरूप ग्लोबल वैरिएबल का उपयोग लंबे समय तक जीवित रहने की अनुमति देने के लिए किया जा सकता है) –

+0

हो सकता है कि आप त्रुटि को पकड़ने के लिए SetUnhandledExceptionFilter का उपयोग कर सकें, PEXCEPTION_POINTERS के साथ फ़िल्ड करें 'जारी रखें' पता समायोजित करें, फिर EXCEPTION_CONTINUE_EXECUTION वापस करें। –

संबंधित मुद्दे