مؤشر الدالة غير صحيح في Visual Studio 2005، يبدأ الرمز عند إزاحة 1 بايت

StackOverflow https://stackoverflow.com/questions/468147

سؤال

يتم ربط الكود المعني بـ explorer.exe ولكنه يتعطل عند الدخول إلى وظيفة رد الاتصال:

Unhandled exception at 0x60055b50 (redacted.dll) in explorer.exe: 0xC0000005: Access violation writing location 0x548b0cca.

مكدس المكالمات:

>     redacted.dll!myCallWndProcRetCallback(int nCode=0x00000000, unsigned int wParam=0x00000000, long lParam=0x015afa58)  Line 799  C++
      user32.dll!_DispatchHookW@16()  + 0x31 bytes    
      user32.dll!_fnHkINLPCWPRETSTRUCTW@20()  + 0x5e bytes  
      user32.dll!___fnDWORD@4()  + 0x24 bytes   
      ntdll.dll!_KiUserCallbackDispatcher@12()  + 0x13 bytes      
      user32.dll!_NtUserMessageCall@28()  + 0xc bytes 
      user32.dll!_SendMessageW@16()  + 0x49 bytes     
      explorer.exe!CTaskBand::_FindIndexByHwnd()  + 0x21 bytes    
      explorer.exe!CTaskBand::_HandleShellHook()  + 0x48 bytes    
      explorer.exe!CTaskBand::v_WndProc()  + 0x660 bytes    
      explorer.exe!CImpWndProc::s_WndProc()  + 0x3f bytes   

أعطى Visual Studio 2005 التفكيك التالي:

--- c:\projects\redacted.cpp -------------------------
//------------------------------------------------------------------------------
LRESULT CALLBACK myCallWndProcRetCallback(int nCode, WPARAM wParam, LPARAM lParam) {
60055B50  inc         dword ptr [ebx+548B0CC4h] 
60055B56  and         al,18h 
60055B58  mov         eax,dword ptr [g_callWndProcRetHook (600B9EE8h)] 
60055B5D  push        esi  

والذاكرة حول 0x548B0CC4 كلها ؟؟؟؟؟؟لذلك لم يتم تعيين الذاكرة، وبالتالي الحادث.

رمز الجهاز في بداية myCallWndProcRetCallback هو:

0x60055B50:  ff 83 c4 0c 8b 54 24 18 a1 e8 9e 0b 60 56 52 57 50 ff 15 8c a6 09 60 5f 5e 83 c4 08 c2 0c 00 cc 8b 4c 24 04 8b 01 8b 50 

لكن Visual Studio يقدم أحيانًا التفكيك التالي لهذه الوظيفة:

--- c:\projects\redacted.cpp -------------------------
60055B51  add         esp,0Ch 
    if ( nCode == HC_ACTION && lParam != NULL) {
60055B54  mov         edx,dword ptr [esp+18h] 
60055B58  mov         eax,dword ptr [g_callWndProcRetHook (600B9EE8h)] 
60055B5D  push        esi  

يبدو أن هذا هو التفكيك الصحيح ولكنه متأخر بمقدار 1 بايت عن التفكيك أعلاه!يمكنك رؤية التعليمات هي نفسها بدءًا من 0x60055B58 فصاعدًا.

لذا، يبدو أن الرابط يقول أن الوظيفة عند 0x60055B50 لكن الكود يبدأ فعليًا عند 0x60055B51.لقد أكدت أن الأول هو رد الاتصال الذي تم تعيينه في خطاف Windows.لذلك عندما يتصل Windows مرة أخرى بالوظيفة، فإنه ينفذ تعليمات برمجية سيئة.

السؤال الذي لدي هو كيف يمكن للرابط أن يخطئ في هذا؟لقد قمت بإعادة البناء وانتهت المشكلة، ويبدو أنها عشوائية.في ذلك الوقت كان خيار الرابط /FORCE:MULTIPLE ساري المفعول ولكن بدونه لم يتم الإبلاغ عن أي خطأ في الارتباط لرد الاتصال هذا.

إضافة متأخرة:هل يمكن أن يكون هذا مرتبطًا بنقل DLL أو إعادة تحديد موقعه؟إذا تم إيقاف النقل بمقدار بايت واحد، فربما يكون هذا هو سبب المشكلة؟

هل كانت مفيدة؟

المحلول

لن يتم إيقاف عمليات النقل أبدًا بمقدار بايت واحد؛يجب أن تتم محاذاة صورة .dll مع دقة التخصيصات التي يتم إرجاعها بواسطة VirtualAlloc والتي يجب أن يكون حجمها 64 كيلو بايت على معظم الأجهزة.

كم من الوقت عمل هذا الرمز؟إذا كان عشوائيًا، فإن /FORCE:MULTIPLE قد يكون مشبوهاً.أو يمكنك استخدام Incredibuild ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top