Всегда ли kernel32 загружается из System32?

  • Скопируйте kernel32.dll из System32 (или SysWOW64, если вы тестируете 32-битное приложение) в каталог, содержащий ваш EXE-файл.
  • Запустите EXE файл
  • Process Monitor показывает, что он даже не потрудился сначала проверить локальную папку на наличие kernel32.dll

Кажется, это противоречит тому, что я всегда считал поведением DLL по умолчанию, то есть сначала загружать из локального каталога приложения, а если его нет, загружать из переменной среды PATH. Однако для некоторых DLL, таких как ntdll или kernel32, Windows всегда сначала проверяет System32. Это ожидаемое поведение? Можно ли отменить это?

(Я понимаю, что игнорировать это было бы плохой практикой, но хочу знать, возможно ли это на самом деле для науки!)


person tomysshadow    schedule 30.03.2017    source источник
comment
32-битные приложения на самом деле имеют перенаправление system32 на 32-битный аналог, поэтому он даже не пытается загрузить 64-битную DLL в качестве первого выбора.   -  person Paul Stelian    schedule 30.03.2017
comment
И эти DLL в значительной степени уже кэшированы, и загрузка из другого места неприятна. Важные для системы библиотеки DLL всегда будут внедряться с пути по умолчанию.   -  person Paul Stelian    schedule 30.03.2017
comment
Я знаю, что Windows при необходимости перенаправляет System32 на SysWOW64, я не об этом прошу. Я также понимаю, что переопределять эти библиотеки DLL - плохая практика, но я все же хотел бы знать, возможно ли это. После дальнейших исследований мне кажется, что я должен добавить в каталог файл .local, но это все равно не имеет никакого эффекта.   -  person tomysshadow    schedule 30.03.2017
comment
Тогда я думаю, что они не могут быть переопределены из-за поведения кэширования Windows (библиотеки DLL живут только один раз в реальной оперативной памяти, а не один раз для каждого отдельного процесса)   -  person Paul Stelian    schedule 30.03.2017
comment
Это known dll поддержка в Windows.   -  person josh poley    schedule 30.03.2017


Ответы (2)


Функция KnownDLL в Windows, как предполагается, помогает быстрее загружать общие библиотеки DLL, но также заставляет все библиотеки DLL в списке загружаться из system32.

Кроме того, kernel32.dll и ntdll.dll обрабатываются особым образом в большинстве версий Windows и загружаются на раннем этапе внутри CreateProcess, поскольку реальная точка входа процесса пользовательского режима находится в одном из этих модулей.

Вы можете использовать .local и явное перенаправление для отмены некоторых из них.

person Anders    schedule 30.03.2017

После дополнительных исследований я обнаружил, что некоторые библиотеки DLL, такие как kernel32.dll или user32.dll, обычно не могут быть переопределены, потому что они являются известными библиотеками DLL. В Windows есть список таких часто используемых библиотек DLL, которые автоматически по умолчанию для версий System32, а не по умолчанию, когда сначала проверяется папка приложения.

Если вы хотите обойти это, например, создать прокси DLL, вам необходимо включить два файла в каталог приложения: applicationName.exe.local и applicationName.exe.manifest , где applicationName - имя вашего EXE-файла.

Это должно быть содержимое файла манифеста:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity version="1.0.0.0" name="redirector" type="win32" />
    <file name="kernel32.dll" />
</assembly>

Тег assemblyIdentity предназначен для предоставления информации о номере версии и имени вашего приложения, но мы можем просто игнорировать его. Важной частью является тег файла, который указывает файл для локальной загрузки. Замените kernel32.dll библиотекой DLL, которую нужно загрузить локально.

Кроме того, Windows обновляет содержимое файлов .manifest только при перезапуске или при изменении файла EXE, поэтому вы можете просто открыть файл EXE в каком-нибудь шестнадцатеричном редакторе, стереть первый символ, добавить его обратно и сохранить ... и т. Д. ., чтобы обновить файл манифеста. Сделайте это, если ваш файл манифеста игнорируется.

  • В Windows 2000 и ниже добавления файла .local будет достаточно, чтобы убедить его загрузить локальную версию kernel32.dll.
  • В Windows XP и более поздних версиях вам необходимо использовать файл .manifest.
  • Приложение может иметь встроенный файл .manifest. В этом случае вы можете удалить ресурс с помощью такого инструмента, как Stud_PE.
person tomysshadow    schedule 30.03.2017