В одной библиотеке встретил вызов LoadLibrary для kernel32 и advapi32 в DllMain, далее она получает адреса некоторых функций, но это не важно. Если библиотеку загружать через LoadLibrary и использовать ее функции, то она работает как надо. Но при попытке прохода в user mode(OllyDbg) отладчике - получаю исключение "Неверный хенлд". Это исключение происходит в DllMain библиотеки при вызове CloseHandle для закрытия хендлов двух перечисленных выше библиотек. При проходе того же кода в kernel mode(SoftIce) отладчике - все нормально, никаких исключений. Я прочитал в MSDN что LoadLibrary внутри DllMain безопасен только для kernel32, а для advapi32 уже нет. Помогите разобраться с проблемой, необходима работа именно в OllyDbg, да и вообще надо разобраться почему происходит исключение.
The CloseHandle function closes handles to the following objects: Код (Text): · Console input or output · Event file · File mapping · Mutex · Named pipe · Process · Semaphore · Thread · Token (Windows NT only) Юзай The FreeLibrary function decrements the reference count of the loaded dynamic-link library (DLL) module. When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid.
Меня немного не поняли, сам виноват. Данная библиотека уже написана и работает, и исходный код мне не доступен. Мне необходимо с ней работать под отладчиком, причем очень желателен OllyDbg. Меня интересует, почему код работоспособен при проходе под SoftIce и при обычном запуске, но вызывает исключение при проходе под user mode отладчиком.
techgl Патч на либу, чтобы не вызывала CloseHandle для "хэндлов" DLL. Мало когда-что от этого в системе нарушится. В идеале пропатчить, чтобы вызывалась FreeLibrary заместо CloseHandle.
Какие проблемы если в OllyDbg добавить в Exceptions\Ignore - Add Last Exception или в .ini прописать? [Exceptions] Custom[0]=C0000008,C0000008
bogrus Добавлял в список, но продолжает ловиться. Видимо его нельзя игнорировать. alpet А вот старый добрый патч (забивание nop'ов) сработал. А функции FreeLibrary в импорте нет, и заменить на нее CloseHandle не получится. Но вопрос почему же при работе не в отладчике все нормально пока остается открытым.
Код (Text): ;======================================================== ; testexe.exe ;======================================================== entry $ invoke LoadLibrary,testdll invoke ExitProcess,0 ;======================================================== testdll db 'testdll.dll',0 ;======================================================== ; testdll.dll ;======================================================== proc dll_entry invoke GetModuleHandle,kernel32 invoke CloseHandle,eax ; Exception xor eax,eax inc eax retn 0x0c endp ;======================================================== kernel32 db 'kernel32.dll',0 ;======================================================== Там получается если в OllyDbg игнорировать этот Exception в dll_entry, то LoadLibrary возвращает 0 и testdll.dll выгружается, но если проходить как обычно по F7\F8\F9, без Ignore (SHIFT+F7\F8\F9), то все нормально отрабатывает (testdll.dll загружается), я не понимаю - почему ты не можешь пройти это исключение ... что потом происходит? И вообще какого в проге используется CloseHandle для этого?
Если следовать оригиналу то вот так: Код (Text): ;======================================================== ; testdll.dll ;======================================================== proc dll_entry invoke LoadLibraryA,kernel32 invoke CloseHandle,eax ; Exception xor eax,eax inc eax retn 0x0c endp ;======================================================== kernel32 db 'kernel32.dll',0 ;======================================================== Я получаю исключение и если его пропустить по Shift+F8, то будет возврат нуля и ошибка "Неверный дескриптор" (если после LoadLibrary вызвать GetLastError). Библиотека не загрузится, нельзя будет потом использовать GetProcAddress (именно для этого в обсуждаемой библиотеке используется загрузка kernel32 и advapi32). Игнорировать же у меня не получилось: я добавил это исключение в список, но отладчик все равно останавливается на нем. Попробуй не GetModuleHandle а LoadLibrary. Я не знаю для чего так сделали разработчики, но это явно не ляп. Приследовалась какая-то цель.
1. LoadLibrary выполняется без ошибок, т.ч. kernel32 и advapi32 загружаются, можно использовать их ф-ции 2. Игнорирование исключения (по SHIFT в отладчике) выгружает testdll.dll и возможно пропадают хендлы загруженых библиотек, из-за чего и не хочет работать 3. Не игнорирование, а обычный проход (без SHIFT) позволяет загрузить библиотеку Убери игнорирование и после того как остановится, просто иди дальше (F7\F8\F9)
А вот что можно видеть в MSDN по теме "Writing the Debugger's Main Loop": Код (Text): ... case LOAD_DLL_DEBUG_EVENT: // Read the debugging information included in the newly // loaded DLL. Be sure to close the handle to the loaded DLL with CloseHandle. break; ... Так что программисты не "ошиблись".
Это для хендлов hFile, а не hModule, т.е. отладчик должен вызвать CloseHandle([LOAD_DLL_DEBUG_INFO.hFile]), к чему это делать после LoadLibraryA мне не понятно When a CREATE_PROCESS_DEBUG_EVENT occurs, the debugger application receives a handle to the image file of the process being debugged, a handle to the process being debugged, and a handle to the initial thread of the process being debugged in the DEBUG_EVENT structure. The members these handles are returned in are u.CreateProcessInfo.hFile (image file), u.CreateProcessInfo.hProcess (process), and u.CreateProcessInfo.hThread (initial thread). If the system previously reported an EXIT_PROCESS_DEBUG_EVENT debugging event, the system closes the handles to the process and thread when the debugger calls the ContinueDebugEvent function. The debugger should close the handle to the image file by calling the CloseHandle function. When a LOAD_DLL_DEBUG_EVENT occurs, the debugger application receives a handle to the loaded DLL in the u.LoadDll.hFile member of the DEBUG_EVENT structure. This handle should be closed by the debugger application by calling the CloseHandle function.
Кстати, исключение "invalid handle" возникает по следующей причине: CloseHandle передает управление в ядро (NtClose), ядро определяет что хэндл не является хэндлом объекта ядра, после чего явно определяет, не подключен ли отладчик, и если не подключен, то просто возвращает ошибку, а если подключен, то бросает исключение. Это относится только к отладчикам 3-кольца (случай либо DebugActiveProcess либо CreateProcess(...DEBUG_PROCESS...)). Хэндл DLLки и хэндл объекта ядра - совершенно разные вещи, их видно даже по типу: HMODULE = HINSTANCE для DLL и HANDLE для CloseHandle. Фактически HINSTANCE - указатель на первый быйт DLL, а HANDLE - индекс во внутренней таблице.