информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Spanning Tree Protocol: недокументированное применениеПортрет посетителяГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Ростелеком заподозрили в попытке... 
 Линуксовый ботнет, распространяющийся... 
 Конец поддержки Internet Explorer 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / operating systems
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
дык - это старая тема :) 26.08.05 19:29  Число просмотров: 2593
Автор: NKritsky <Nickolay A. Kritsky> Статус: Elderman
<"чистая" ссылка>
Он конечно выгружает длл, но файловые секции остаются закэшироваными в RAM. Но не на уровне объектов типа "dll" а уже на уровне своппера, как физические страницы. Тут z0 может лучше разъяснит :) с упоминанием всех ntdll!ZwXXX и ntdll!IoXXX функций. Тема эта лечится походу только изменением last modification time на файле. утилита touch, или просто F4->F2->Esc в фаре.
<operating systems>
[NT] выгрузить dll из памяти 25.08.05 13:17  
Автор: Woland Статус: Незарегистрированный пользователь
<"чистая" ссылка>
как известно, после вызова FreeLibrary, даже если ни один процесс больше не использует библиотеку, она всё равно "висит" в памяти. есть ли возможность полностью выгрузить одну-единственную dll, так, чтобы при последующем вызове LoadLibrary она в любом случае загружалась из файла?
всё, что нарыл в инете - так это информация о ключе HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AlwaysUnloadDll, параметр default = 1 которого, заставляет систему выгружать ВСЕ неиспользуемые dll. а как быть, если надо выгрузить всего одну?
единственное, что пришло на ум - это занять и освободить весь имеющийся объём свободной физической памяти.
есть ли более гуманные способы?
заранее благодарен за ответы.
всем спасибо, createfile/closehandle замечательно работает... :) 01.09.05 07:11  
Автор: Woland Статус: Незарегистрированный пользователь
<"чистая" ссылка>
вовсе нет 25.08.05 20:05  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка>
> как известно, после вызова FreeLibrary, даже если ни один
> процесс больше не использует библиотеку, она всё равно
> "висит" в памяти

это не так. если ни один процесс не прилинкован к этой длл статически и количество
LoadLibrary == FreeLibrary то длл не "висит" в памяти а полностью выгружается т.е.
ZwUnmapViewOfFile() -> ZwClose(секция) -> ZwClose(файл)

могу показать на примере или смотрите код ntdll!LdrUnloadDll()
по всей видимости, Вы правы. 26.08.05 09:09  
Автор: Woland Статус: Незарегистрированный пользователь
<"чистая" ссылка>
> это не так. если ни один процесс не прилинкован к этой длл

по всей видимости, Вы правы.
специально написал программу, вызывающую из длл функцию типа int test (int Arg) { return (Arg+5);}
после исследования в софтайсе (правил непосредственно в памяти аргумент вызова и константу в возвращаемом значении) выяснилось, что при каждом запуске код в длл возвращался к исходному виду, а код самого ехе - модуля оставался с изменениями. по всей видимости, в этом всё дело.

объясню ситуацию. имеются два процесса - А и В, написанные сторонними разработчиками. процесс В после запуска А проверяет в памяти его целостность (контрольную сумму) и внедряет свою длл через CreateRemoteThread и LoadLibrary. длл при запуске - распаковывается и выполняет кучу разных проверок. после завершения А при его повторном запуске В выдаёт ошибку - "нарушение целостности". я думал, что вся проблема в том, что в памяти остаётся распакованная (соответственно, контрольная сумма другая) внедрённая длл. теперь же склонен считать, что проблема в том, что при повторном запуске сохраняются изменения, сделанные В при внедрении кода (VirtualAllocEx и WriteProcessMemory).
есть какие-нибудь способы избежать этого?
пофиксить багу 26.08.05 14:35  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка>
> есть какие-нибудь способы избежать этого?

поточнее плиз. итак запускается А, он запускает В, затем А внедряет в В некую длл,
которая проверяет в адресном пространстве В нечто и принимает решение

я так понял после завершения В и последующего завершения А производится перезапуск
А который в свою очередь перезапускает В, снова внедряет в В длл которая принимает
на этот раз некорректное решение, так? а если между этими событиями машину ребутнуть
то все Ок?

в этом случае скорее всего речь идет о баге в длл, конкретно в процедуре принятия
решения. исправляйте или жалуйтесь разработчику
всё немного не так. 26.08.05 17:54  
Автор: Woland Статус: Незарегистрированный пользователь
<"чистая" ссылка>

> поточнее плиз. итак запускается А, он запускает В, затем А
> внедряет в В некую длл,
> которая проверяет в адресном пространстве В нечто и
> принимает решение

если А и В поменять местами - то всё верно.... :)

> А который в свою очередь перезапускает В, снова внедряет в

В (который у Вас в данном случае А :) ) ничего не перезапускает. он сидит и ждёт, когда другой процесс будет запущен.

> событиями машину ребутнуть
> то все Ок?

ребутить не обязательно. можно запустить несколько копий фотошопа, например, хорошо ещё помогает нечто вроде:
MEMORYSTATUS mst;
GlobalMemoryStatus(&mst);
PVOID pvMem = VirtualAlloc(NULL, mst.dwTotalPhys,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(pvMem, mst.dwTotalPhys);
VirtualFree(pvMem, NULL, MEM_RELEASE);

> в этом случае скорее всего речь идет о баге в длл,

как я уже говорил, в тестовой программе (да и в любой другой) после изменения её дебагером (по крайней мере, в секции с кодом, с данными не проверял), и последующего перезапуска - загрузится именно изменённая копия. т.е., если пофиксить условный переход в проверке вида
bool a = true;
if (a == true) return 2; else return 3; , то при следующем запуске (уже без отладчика) процедура вернёт 3.
так что не думаю, что речь идёт о баге в длл.
дык - это старая тема :) 26.08.05 19:29  
Автор: NKritsky <Nickolay A. Kritsky> Статус: Elderman
<"чистая" ссылка>
Он конечно выгружает длл, но файловые секции остаются закэшироваными в RAM. Но не на уровне объектов типа "dll" а уже на уровне своппера, как физические страницы. Тут z0 может лучше разъяснит :) с упоминанием всех ntdll!ZwXXX и ntdll!IoXXX функций. Тема эта лечится походу только изменением last modification time на файле. утилита touch, или просто F4->F2->Esc в фаре.
точно 29.08.05 17:55  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка>
> Он конечно выгружает длл, но файловые секции остаются
> закэшироваными в RAM. Но не на уровне объектов типа "dll" а
> уже на уровне своппера, как физические страницы. Тут z0
> может лучше разъяснит :) с упоминанием всех ntdll!ZwXXX и
> ntdll!IoXXX функций. Тема эта лечится походу только
> изменением last modification time на файле. утилита touch,
> или просто F4->F2->Esc в фаре.

спасибо хоть ты объяснил о чем идет речь

это действительно проблема и проблема иногда не имеющая решения, сам недавно
наступал на нее. смысл такой - если на странице памяти стоит атрибут READ-ONLY, то
изменения этой страницы под отладчиком (в данном случае речь идет именно о
kernel-mode отладчике - ну например софтайсе) не приводят к соответсвующему
сигналу в кеш что страница изменена (dirty) поэтому кеш будет считать что страница
никогда не изменялась и будет ее подсовывать без перезагрузки из файла.

для юзер-моде страниц решение весьма простое - VirtualProtect с протектом 4 или 40 и
все Ок, а вот для kernel-mode страниц придется поизвращаться поскольку ZwVirtualProtect
НЕ экспортируется ntoskrnl.exe

в данном конкретном случае изменение файла dll может помочь. ну например убедившись
что ссылок на длл нет CreateFile(GENERIC_READ | GENERIC_WRITE) и CloseHandle
речь как раз не об отладчике 30.08.05 15:49  
Автор: Woland Статус: Незарегистрированный пользователь
<"чистая" ссылка>
> спасибо хоть ты объяснил о чем идет речь

:))

> речь идет именно о
> kernel-mode отладчике - ну например софтайсе) не приводят к

речь как раз не об отладчике. по всей видимости, если один процесс меняет содержимое памяти другого через WriteProcessMemory - получаем ту же самую картину. другого объяснения я не вижу.

> что ссылок на длл нет CreateFile(GENERIC_READ |
> GENERIC_WRITE) и CloseHandle

ок. спасибо. если это действительно единственное решение в данной ситуации - будем пробовать..
[UPD]MSDN/CreateFileMapping 30.08.05 16:00  
Автор: Killer{R} <Dmitry> Статус: Elderman
Отредактировано 30.08.05 19:13  Количество правок: 1
<"чистая" ссылка>
Цитата из ремарок:
A mapped file and a file accessed by means of the input and output (I/O) functions (ReadFile and WriteFile) are not necessarily coherent.
Так что это документировано.. Если я конечно понял то о чем речь в этом тредею
[UPD]
Соответственно чтобы чтото записать в файл, который был когдато промаплен в память (а длл именно мапится), так чтобы изменения отразились, полагаю надо просто открыть мапу с PAGE_READWRITE на этот файл и записать в нее.
Не экспортируется потому, что такой функции нет в ядре 30.08.05 11:47  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> для юзер-моде страниц решение весьма простое -
> VirtualProtect с протектом 4 или 40 и
> все Ок, а вот для kernel-mode страниц придется
> поизвращаться поскольку ZwVirtualProtect
> НЕ экспортируется ntoskrnl.exe

lkd> x nt!zw*virtual*
8050bc4e nt!ZwQueryVirtualMemory = <no type information>
8050c40a nt!ZwWriteVirtualMemory = <no type information>
8050b672 nt!ZwLockVirtualMemory = <no type information>
8050b4a6 nt!ZwFlushVirtualMemory = <no type information>
8050c32e nt!ZwUnlockVirtualMemory = <no type information>
8050b4e2 nt!ZwFreeVirtualMemory = <no type information>
8050bcee nt!ZwReadVirtualMemory = <no type information>
8050afba nt!ZwAllocateVirtualMemory = <no type information>
8050b91a nt!ZwProtectVirtualMemory = <no type information>

---

Более того, kernel32!VirtualProtect() - просто stub для kernel32!VirtualProtectEx(), а тот в свою - stub для ntdll!NtProtectVirtualMemory(), который в свою очередь является просто гейтом в nt!NtProtectVirtualMemory()

Это все легко видно в отладчике.
ну блин совсем уже нету? 01.09.05 18:15  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка>
> Более того, kernel32!VirtualProtect() - просто stub для
> kernel32!VirtualProtectEx(), а тот в свою - stub для
> ntdll!NtProtectVirtualMemory(), который в свою очередь
> является просто гейтом в nt!NtProtectVirtualMemory()
>
> Это все легко видно в отладчике.

ну это правильно, а дальше-то что? что ж ты дальше не посмотрел?
ntdll!NtProtectVirtualMemory (или Zw* что одно и тоже) что вызывает?
правильно, уходит в ядро в функцию какую-то неэкспортируемую
подгрузи символы и увидишь ее название - _ZwProctectVirtualMemory
и не говори после этого что ее нет в ядре

такие все блин грамотные пошли, ну как ядро может в принципе жить без такой
функции подумай, а что MS-девелоперы не экспортировали ее - это свинство и здорово
ограничивает возможности драйверов по управлению useraddressspace

раз ты так все хорошо видишь в отладчике то посмотри как загружается в каждый
новый процесс ntdll.dll - кое что новое узнаешь
Что значит "дальше не посмотрел"? Дальше (после... 02.09.05 12:28  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 02.09.05 12:29  Количество правок: 1
<"чистая" ссылка>
> > Более того, kernel32!VirtualProtect() - просто stub
> для
> > kernel32!VirtualProtectEx(), а тот в свою - stub для
> > ntdll!NtProtectVirtualMemory(), который в свою очередь
> > является просто гейтом в nt!NtProtectVirtualMemory()
> >
> > Это все легко видно в отладчике.

> ну это правильно, а дальше-то что? что ж ты дальше не
> посмотрел?

Что значит "дальше не посмотрел"? Дальше (после nt!NtProtectVirtualMemory) валидирование аргументов и уход в nt!MiProtectVirtualMemory(). Только это уж точно к делу не относится. Или надо смотреть ЕЩЕ дальше?

> ntdll!NtProtectVirtualMemory (или Zw* что одно и тоже) что
> вызывает?
> правильно, уходит в ядро в функцию какую-то
> неэкспортируемую
> подгрузи символы и увидишь ее название -
> _ZwProctectVirtualMemory
> и не говори после этого что ее нет в ядре

Название этой функции я написал выше. Это nt!NtProtectVirtualMemory() (она не экспортируется, но речь то не о ней, ты ее вообще не упоминал), а функции ZwVirtualProtect() ни в ядре, ни в юзерспейсе действительно нет.

> такие все блин грамотные пошли, ну как ядро может в
> принципе жить без такой

Давай не будем меряться письками, скажи просто в чем проблема?

> функции подумай, а что MS-девелоперы не экспортировали ее -
> это свинство и здорово
> ограничивает возможности драйверов по управлению
> useraddressspace

Во-первых это очень редко нужно, во-вторых эту функцию ОЧЕНЬ легко найти, если уж СИЛЬНО захочется.

> раз ты так все хорошо видишь в отладчике то посмотри как
> загружается в каждый
> новый процесс ntdll.dll - кое что новое узнаешь

Не понял о чем ты. Просвети уж
да конечное Nt а не Zw чего-то я перепутал извини 06.09.05 17:44  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка>
Не так. Просто ты назвал эту функцию вообще неправильно (а не только префикс перепутал) 09.09.05 01:19  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Если же тебя интересует как найти эту самую nt!NtProtectVirtualMemory, то рекомендую обратить внимание на экспортируемую nt!KeServiceDescriptorTable
Номер сервиса можно или вбить в код или искать например по ntdll-ному stub-у
Даже если "забить" всю память это не поможет. 25.08.05 18:45  
Автор: leo <Леонид Юрьев> Статус: Elderman
<"чистая" ссылка>
Даже если "забить" всю память это не поможет.

Пока dll подгружена хотя-бы одним процессом, она отображена на память, dll-файл открыт и его неполучится удалить или изменить. Чтобы это было возможно dll не должна иметь разделяемых секций, например иметь одну не-константную секцию с кодом/данными. Простейший способ - упаковать dll каким-нибудь exe-упаковщиком.

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

Но лучше "просто" отобразить dll в свою память, сделав работу загрузчика.
В библиотеке COM есть специальная функция для этого, что-то... 25.08.05 18:06  
Автор: Neznaika <Alex> Статус: Member
<"чистая" ссылка>
В библиотеке COM есть специальная функция для этого, что-то вроде "CoFreeUnusedLibraries".
Можно аккуратно посмотреть, что она делает -- далее по аналогии.

Удачи!
Еще вариант 25.08.05 19:23  
Автор: Neznaika <Alex> Статус: Member
<"чистая" ссылка>
Если надо сделать так, чтобы в любом случае Dll загружалась из файла - то можно каждый раз перед LoadLibrary переименовывать файл на диске. Или даже получать уникальное имя, копировать в %Temp%, и далее загружать библиотеку из %Temp%
Если не ошибаюсь, то CoFreeUnusedLibraries() просто... 25.08.05 18:31  
Автор: leo <Леонид Юрьев> Статус: Elderman
<"чистая" ссылка>
Если не ошибаюсь, то CoFreeUnusedLibraries() просто выгружает (посредством FreeLibrary()) все загруженные (посредством LoadLibrary()) dll-COM-серверы для которых нет активных объектов. Другими словами, просто чистится кэш.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2022 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach