![]() |
eXeL@B —› Программирование —› Выгрузка либы |
Посл.ответ | Сообщение |
|
Создано: 22 мая 2009 05:54 · Личное сообщение · #1 Есть лист из либы: Code:
как правильно выгрузить данную либу? Заранее спс ![]() |
|
Создано: 22 мая 2009 06:52 · Личное сообщение · #2 |
|
Создано: 22 мая 2009 07:00 · Личное сообщение · #3 |
|
Создано: 22 мая 2009 08:11 · Личное сообщение · #4 Выгружаю либу, только непонятно вот тут: FreeLibrary (Ca); FreeLibrary (Ca); FreeLibrary (Ca); ![]() ![]() |
|
Создано: 22 мая 2009 11:27 · Поправил: zeppe1in · Личное сообщение · #5 |
|
Создано: 22 мая 2009 20:40 · Личное сообщение · #6 FreeLibrary прекрасно подходит, но, как говорил Рихтер, тут есть одно но - т.к. количество потоков в приложении, в которое данная либа была внедрена, не всегда (далеко не всегда) равно нулю, это приводит к тому, что для выгрузки из адресного пространства такого процесса данной библиотеки код, её выгружающий, должен выполниться столько раз, сколько потоков имеет процесс. Т.е. проверяем через GetModuleHandle, присутствует ли либа, если возвращается валидный хэндл, то выполняем FreeLibrary, и так столько раз, сколько будет нужно. Так проще, т.к. не нужно вычислять, сколько на данный момент потоков у процесса. ----- Stuck to the plan, always think that we would stand up, never ran. ![]() |
|
Создано: 23 мая 2009 00:05 · Личное сообщение · #7 ARCHANGEL Потоки непричём. Существует счётчик загрузок(LDR_DATA_TABLE_ENTRY.LoadCount). Это значение увеличивается каждый раз при вызове функций загружающих модуль и уменьшается при попытках выгрузить соответственно. Если значение станет равным нулю модуль быдет выгружен. Тоесть туда нужно единицу запихать а потом уже выгружать(для статически прилинкованных не прокатит). ![]() |
|
Создано: 23 мая 2009 00:11 · Личное сообщение · #8 |
|
Создано: 23 мая 2009 03:52 · Личное сообщение · #9 |
|
Создано: 23 мая 2009 09:03 · Личное сообщение · #10 |
|
Создано: 23 мая 2009 09:08 · Поправил: 50Hz_220B_1200W · Личное сообщение · #11 |
|
Создано: 23 мая 2009 12:04 · Поправил: only · Личное сообщение · #12 |
|
Создано: 26 мая 2009 12:39 · Личное сообщение · #13 Внимательно прочитав Рихтера, нашёл: На самом деле LoadLibrary и LoadLibraryEx лишь увеличивают счетчик числа поль- зователей указанной библиотеки, a FreeLibrary и FreeLibraryAndExitThread его умень- шают. Так, при первом вызове LoadLibrary для загрузки DLL система проецирует об- раз DLL-файла на адресное пространство вызывающего процесса и присваивает еди- ницу счетчику числа пользователей этой DLL. Если поток того же процессу вызывает LoadLibrary для той же DLL еще раз, DLL больше не проецируется; система просто увеличивает счетчик числа ее пользователей — вот и все. Чтобы выгрузить DLL из адресного пространства процесса, FreeLibrary придется теперь вызывать дважды: первый вызов уменьшит счетчик до 1, второй — до О. Обна- ружив, что счетчик числа пользователей DLL обнулен, система отключит ее. После этого попытка вызова какой-либо функции из данной DLL приведет к нарушению доступа, так как код по указанному адресу уже не отображается на адресное простран- ство процесса. Система поддерживает в каждом процессе свой счетчик DLL, т. е. если поток процесса А вызывает приведенную ниже функцию, а затем тот же вызов делает поток в процессе В, то MyLib.dll проецируется на адресное пространство обоих процессов, а счетчики числа пользователей DLL в каждом из них приравниваются 1. HINSTANCE hinstDll = LoadLibrary("MyLib.dllT1); Если же поток процесса В вызовет далее: FreeLibrary(hinstDll); счетчик числа пользователей DLL в процессе В обнулится, что приведет к отключе- нию DLL от адресного пространства процесса В. Но проекция DLL на адресное про- странство процесса А не затрагивается, и счетчик числа пользователей DLL в нем остается прежним. Чтобы определить, спроецирована ли DLL на адресное пространство процесса, поток может вызвать функцию GetModuleHandte; HINSTANCE GetModuleHandle(PCTSTR pszModuleName); • Например, следующий код загружает MyLib.dll, только если она еще не спроеци- рована на адресное пространство процесса: HINSTANCE hinstDll = Get Mod uleH arid le( "MyLib"); // подразумевается расширение .dll if (hinstDll == NULL) { hinstDll = LoadLibraryC'MyLib"); // подразумевается расширение .dll Так что не стоит использовать какие-то не очень документированные структуры, когда документированные просты и понятны. ----- Stuck to the plan, always think that we would stand up, never ran. ![]() |
|
Создано: 26 мая 2009 13:34 · Личное сообщение · #14 |
|
Создано: 27 мая 2009 12:14 · Личное сообщение · #15 |
|
Создано: 27 мая 2009 13:36 · Личное сообщение · #16 |
|
Создано: 27 мая 2009 15:28 · Поправил: Clerk · Личное сообщение · #17 > Система поддерживает в каждом процессе свой счетчик DLL, т. е. если поток процесса А вызывает приведенную ниже функцию, а затем тот же вызов делает поток в процессе В, то MyLib.dll проецируется на адресное пространство обоих процессов, а счетчики числа пользователей DLL в каждом из них приравниваются 1. Полнейший бред, написанный кемто не понимающим что есть поток и процесс. Адресное простнаство не зря называется виртуальным, изолированность это главное требование безопасности. > NtUnmapViewOfSection Проекция модуля перестанет существовать в памяти, ссылки на неё останутся, все будут думать что модуль есть, код не выполнит необходимые действия например при выгрузке. В конце концов приведёт к эксцепшину и краху в простейшем случае лоадера. ![]() |
|
Создано: 27 мая 2009 15:54 · Поправил: Smon · Личное сообщение · #18 ARCHANGEL пишет: На самом деле LoadLibrary и LoadLibraryEx лишь увеличивают счетчик числа поль- зователей указанной библиотеки, a FreeLibrary и FreeLibraryAndExitThread его умень- шают. Так, при первом вызове LoadLibrary для загрузки DLL система проецирует об- раз DLL-файла на адресное пространство вызывающего процесса и присваивает еди- ницу счетчику числа пользователей этой DLL. Если поток того же процессу вызывает LoadLibrary для той же DLL еще раз, DLL больше не проецируется; система просто увеличивает счетчик числа ее пользователей — вот и все. Чтобы выгрузить DLL из адресного пространства процесса, FreeLibrary придется теперь вызывать дважды: первый вызов уменьшит счетчик до 1, второй — до О. Обна- ружив, что счетчик числа пользователей DLL обнулен, система отключит ее. После этого попытка вызова какой-либо функции из данной DLL приведет к нарушению доступа, так как код по указанному адресу уже не отображается на адресное простран- ство процесса. Истена, файло отдельно проецируется на адресное пространство каждого процесса, иначе завалились бы при первом же сплайсе, счётчики количества LoadLibrary/FreeLibrary реально есть - только что проверил ради интереса, для каждого процесса свой счётчик, считал ранее что для получения адреса загруженной библиотеки не обязательно юзать GetModuleHandleA, можно обойтись и LoadLibrary, а там вон какая фишка ![]() ----- "Пусть видят, что мы не шутим. Стволы для понта, ножи для дела" Lock, Stock & Two Smoking Barrels ![]() |
|
Создано: 27 мая 2009 16:21 · Личное сообщение · #19 Clerk Проекция модуля перестанет существовать в памяти, ссылки на неё останутся, все будут думать что модуль есть, код не выполнит необходимые действия например при выгрузке. В конце концов приведёт к эксцепшину и краху в простейшем случае лоадера. скорее всего это верно только для модуля который статически прилинкован. если иначе, то какие такие необычные ссылки могут быть на модуль(с учетом например того, что все хуки в коде и данных, возможно установленные и данным модулем, сняты, и ссылка на модуль удалена из области памяти лоадера)? может конечно имеются ввиду потоки которые быть созданы кодом из модуля и могли исполнять код модуля в момент удаления его проекции тогда можно ловить все без разбора исключения для данного процесса и удалять потоки в контексте которых eip указывает на область памяти модуля хотя и свои потоки могли оказаться в таком же положении (тоже ведь можно придумать что-то - они все-таки "свои") ![]() |
|
Создано: 27 мая 2009 17:26 · Личное сообщение · #20 |
|
Создано: 27 мая 2009 19:49 · Поправил: Clerk · Личное сообщение · #21 only > какие такие необычные ссылки могут быть на модуль Запись в лдр. Любая функция из Ldr* юзает проверку валидности хидера к примеру, RtlImageNtHeader(), хотя и заключена в сех чтоб не упала, но это общее состояние загрузчика нарушит. Как же импорт/экспорт - другие модуля будут обращаться в никуда, а внутренние хэши, нотификаторы и пр. ![]() |
![]() |
eXeL@B —› Программирование —› Выгрузка либы |