Вопросы, касающиеся загрузки DLL в адресное пространство процесса

Я прочитал несколько статей Мэтта Питрека о переносимых исполняемых файлах (PE), например:

Вдобавок я прочитал несколько других источников по этому поводу. Либо я не замечаю некоторых частей, либо там нет ответов на вопросы.

Итак, вот вопросы:

Известно, что при загрузке EXE-файла загрузчик Windows считывает список импортированных DLL из таблицы адресов Importa (IAT) и загружает их в адресное пространство процесса.

  1. Адресное пространство процесса - это виртуальное пространство. DLL, возможно, уже загружена в какое-то физическое пространство. Это происходит с библиотеками DLL, такими как KERNEL32.dll или USER32.dll. Какая связь между физическим и виртуальным адресом? Загрузчик просто выделяет страницы и копирует DLL или делает ссылки?

  2. Если DLL не загружена, загрузчик загружает всю DLL или только необходимые функции? Например, если вы использовали функцию foo() из bar.dll, загружает ли загрузчик весь bar.dll в адресное пространство процесса? Или он просто загружает код foo в адресное пространство процесса?

  3. Предположим, ваш EXE-файл использует функцию MessageBox() из USER32.DLL, которая находится в %WINDIR%\system32\user32.dll. Можете ли вы разработать индивидуальный USER32.DLL, поместить его в тот же каталог, что и ваш EXE-файл, и ожидать, что ваш настроенный MessageBox будет вызываться вашим приложением, а не системным MessageBox по умолчанию?


person M.S. Dousti    schedule 16.12.2010    source источник


Ответы (2)


По поводу 1: физические адреса не играют никакой роли, здесь все задействовано в виртуальной памяти. Физический адрес устанавливается только тогда, когда страница виртуальной памяти отображается в ОЗУ, вызванная ошибкой страницы. Многие базовые библиотеки DLL появляются по одному и тому же адресу виртуальной памяти в нескольких процессах, например, kernel32.dll. Процессы просто используют одни и те же страницы кода (не данных).

По поводу 2: фактической «загрузки» не происходит, используется та же функция, которая поддерживает файлы с отображением в память. Основой этих страниц является сам файл DLL, а не файл подкачки. Ничего не загружается, пока сбой страницы не заставит Windows прочитать страницу из файла в ОЗУ. Но да, отображается весь код DLL.

По поводу 3: да, это сработает. Но практически невозможно заставить его работать на практике, так как вам придется писать функции замены для всего экспорта user32, который использует ваша программа. Включая те, которые используют другие функции Win32, вы не можете знать. Перехват API - это типичный метод, который используется, Detours from Microsoft Labs - хороший метод.

Windows Internals edition 5 - отличная книга, чтобы узнать больше о сантехнике.

person Hans Passant    schedule 16.12.2010
comment
Большое спасибо. ... сделать практически невозможно ...: Собственно, хочу заменить WS2_32.DLL. В EXE-файле используются только 5 функций из WS2_32.DLL, поэтому его можно заменить. Фактически, я просто хочу предотвратить подключение EXE к Интернету, поэтому я хочу заменить функцию TCP / IP connect, чтобы она ничего не делала. Это звук? - person M.S. Dousti; 16.12.2010
comment
Это не так, многие библиотеки DLL Windows используют его. И библиотеки DLL, о которых вы не знаете, те, которые загружаются в ваш процесс, когда вы используете диалоги оболочки, такие как GetOpenFileName (). Используйте обходные пути, как я рекомендовал. - person Hans Passant; 16.12.2010

1) Когда вы создаете новый процесс, загрузчик ядра NT выделяет пространство для процесса и отображает все разделы PE в указанное место. Затем загрузчик NT просматривает таблицу импорта, загружает библиотеки DLL в память процесса и при необходимости корректирует указатели (это называется перемещением).

2) Загрузчик загружает всю DLL в адресное пространство процесса.

3) Да, он будет использовать user32.dll из того же каталога, где находится EXE. См. эту ссылку. Но поскольку большинство функций WinAPI, расположенных в user32.dll, ваша пользовательская dll должна экспортировать их много.

person DReJ    schedule 16.12.2010
comment
Исправление №2: вся DLL отображается в адресное пространство процесса, но только фактически используемые страницы будут загружены в ОЗУ (выполняется диспетчером виртуальной памяти при возникновении ошибки страницы). В Windows страницы чаще всего имеют размер 4 КБ каждая. - person Ben Voigt; 16.12.2010
comment
Хоть кто-то что-то сказал про переезды :). Кстати, когда происходит перемещение, эти страницы помечаются как частные / не предназначенные для совместного использования. Таким образом, перемещение требует больших затрат памяти и времени (изменение кода для нового адреса). - person RandomNickName42; 19.03.2011