Неверный указатель на функцию в 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 linker, но без нее для этого обратного вызова не сообщается об ошибке ссылки.

Позднее дополнение:Может ли это быть связано с перемещением или перебазированием библиотеки DLL?Если перемещение было отклонено на 1 байт, возможно, это могло вызвать проблему?

Это было полезно?

Решение

Перемещения почти никогда не будут отклоняться на 1 байт;.образ dll должен быть выровнен с детализацией выделений, возвращаемых VirtualAlloc, которая должна составлять 64 кб на большинстве компьютеров.

Как долго работает этот код?Если это случайно, то /FORCE:МНОЖЕСТВЕННЫЙ мог бы будьте подозрительны.Или вы могли бы использовать Incredibuild...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top