Funktionszeiger nicht korrekt in Visual Studio 2005, Code beginnt mit dem 1-Byte-Offset
-
19-08-2019 - |
Frage
Der betreffende Code Haken in explorer.exe wurde aber über den Eintritt in die Callback-Funktion Absturz:
Unhandled exception at 0x60055b50 (redacted.dll) in explorer.exe: 0xC0000005: Access violation writing location 0x548b0cca.
Aufrufhierarchie:
> 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 ergab folgende Zerlegung:
--- 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
und der Speicher um 0x548B0CC4 ist alles ?????? so ist sie nicht Speicher abgebildet, daher auch der Absturz.
Der Maschinencode zu Beginn des myCallWndProcRetCallback ist dies:
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
Aber Visual Studio gibt auch manchmal die folgende Zerlegung für diese Funktion:
--- 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
Das sieht aus wie die richtige Demontage, aber es ist aus 1 Byte später als die Demontage oben! Sie können sehen, die Anweisungen der gleiche von 0x60055B58 sind weiter.
So sieht es aus wie der Linker sagt die Funktion bei 0x60055B50 ist aber der Code tatsächlich beginnt bei 0x60055B51. Ich habe die ehemalige bestätigt der Rückruf in den Windows-Haken gesetzt ist. Also, wenn Windows ruft zurück in die Funktion führt sie schlechten Code.
Die Frage, die ich habe, ist, wie der Linker diese falsch bekommen? Ich habe eine wieder aufzubauen und das Problem ging weg, so scheint es zufällig. Zum Zeitpunkt der / FORCE: MULTIPLE Linker-Option war in der Tat ohne sie jedoch keinen Verbindungsfehler wird für diesen Rückruf berichtet
.Eine späte Zugabe: Könnte dies die Verlagerung oder Rebasieren eine DLL in Beziehung gesetzt werden? Wenn die Verlagerung weg von 1 Byte ist, könnte dies vielleicht das Problem verursachen?
Lösung
Relocations fast nie weg von 1 Byte sein; das DLL-Bild wird von VirtualAlloc wieder in die Granularität der Zuweisungen ausgerichtet werden, die 64k auf den meisten Maschinen sein sollte.
Wie lange hat dieser Code funktioniert? Wenn es zufällig ist dann die / FORCE: MULTIPLE könnte verdächtig sein. Oder Sie könnten IncrediBuild verwenden ...