Получение списка DLL, загруженных в текущий процесс
Сегодня я покажу вам небольшой трюк, с помощью которого вы сможете получить список всех DLL (динамических библиотек), загруженных в ваше приложение. Хитрость заключается в том, что для этого мы вообще не будем использовать никакие API.Сперва немного теории. Каждому процессу в системе соответствует особая структура PEB (Process Enviroment Block), в ней содержится большое количество полезной информации о процессе. Адрес PEB можно узнать из другой структуры - TIB (Thread Information Block), адрес которой, в свою очередь, всегда можно получить по фиксированному адресу [FS:0]. Так вот, одно из полей PEB указывает на массив структур, в которых содержится информация о всех динамических библиотеках, загруженных в адресное пространство процесса. Этот массив называется PEB_LDR_DATA. Перебирая по очереди записи из этого массива, можно получить интересующий нас список DLL, а также адреса загрузки в память и Virtual Address точки входа этих библиотек.
Переходим к программированию. Flat Assembler "из коробки" не знает структур для работы с PEB_LDR_DATA, поэтому придется ему в этом помочь:
Code (Assembler) : Убрать нумерацию
- struct UNICODE_STRING
- Length dw ?
- MaximumLength dw ?
- Buffer dd ?
- ends
- struct LIST_ENTRY
- Flink dd ?
- Blink dd ?
- ends
- struct LDR_DATA_ENTRY
- InMemoryOrderModuleList LIST_ENTRY
- BaseAddress dd ?
- EntryPoint dd ?
- SizeOfImage dd ?
- FullDllName UNICODE_STRING
- BaseDllName UNICODE_STRING
- Flags dd ?
- LoadCount dw ?
- TlsIndex dw ?
- HashTableEntry LIST_ENTRY
- TimeDateStamp dd ?
- ends
Сам код перебора простейший. Для удобства я оставил только сам алгоритм, полезную нагрузку вы можете добавить по своему усмотрению.
Code (Assembler) : Убрать нумерацию
- ; EAX -> PEB
- mov eax,[fs:30h]
- ; EAX -> PEB_LDR_DATA
- mov eax,[eax+0Ch]
- ; EBX -> InInitializationOrderModuleList
- mov ebx,[eax+1Ch]
- @@:
- ; Последняя запись?
- cmp [ebx+LDR_DATA_ENTRY.BaseAddress],0
- ; Остановить обработку
- je @f
- ...
- ...
- ; EBX -> LDR_DATA_ENTRY
- ; Выполнить нужные действия
- ...
- ...
- ; Указатель на следующую запись
- mov ebx,[ebx+LDR_DATA_ENTRY.InMemoryOrderModuleList.Flink]
- jmp @b
- @@:
Ну и, напоследок, ответ на традиционный вопрос "зачем это нужно?". Например, таким способом защитный модуль программы может контролировать, что все используемые системные библиотеки загружены из системной директории. Для взлома некоторых приложений используются так называемые прокси-dll, которые имеют имя одной из системных библиотек, импортируемых приложением, но загружаются из папки с программой, после чего патчат в памяти пару условных переходов ;) Подобная проверка сможет затруднить такой метод взлома. Зная имена загруженных библиотек, приложение может проверить их на предмет модификации, сравнив образ в памяти с файлом на диске. Это затруднит отлом защиты через сплайсинг вызываемых системных функций. Еще приложение может контролировать, чтобы в его адресное пространство не было загружено никаких посторонних библиотек, например, модулей перехвата различных API Monitor'ов. А поскольку код проверки не использует вызовы API, его легко замаскировать или как-нибудь обфусцировать. Ну а реверсерам, в свою очередь, будет полезно знать о таких методах защиты.
В приложении пример программы с исходным текстом, которая последовательно выводит все динамические библиотеки, загруженные в ее процесс.
Просмотров: 3811 | Комментариев: 12
Метки: Assembler
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
pawel97
(27.06.2017 в 18:51):
ManHunter, спасибо! Блин, видел же в какой-то инструкции к лекарству прописывание этой либы в ExcludeFromKnownDlls, но было давно и не думалось, что пригодится в своих целях.
ManHunter
(27.06.2017 в 18:13):
Потому что в WinXP эта dll прописана в ветке реестра
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
и имеет приоритет загрузки из системной папки. В Win7 по дефолту не прописана, поэтому грузится первая попавшаяся.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
и имеет приоритет загрузки из системной папки. В Win7 по дефолту не прописана, поэтому грузится первая попавшаяся.
pawel97
(27.06.2017 в 17:56):
"Например, таким способом защитный модуль программы может контролировать, что все используемые системные библиотеки загружены из системной директории."
Можно вопрос на эту тему?
Почему Win7 и выше подгружают лежащую рядом с процессом version.dll, а xp грузит её только из system32? Это как-то изменяется через реестр? Гуглил про всякие Image File Execution Options + procmon'ом смотрел, не нашёл ничего...
Можно вопрос на эту тему?
Почему Win7 и выше подгружают лежащую рядом с процессом version.dll, а xp грузит её только из system32? Это как-то изменяется через реестр? Гуглил про всякие Image File Execution Options + procmon'ом смотрел, не нашёл ничего...
ManHunter
(22.06.2017 в 15:37):
У меня обычно все ассемблерные исходники в win-1251, а тут что-то прощелкал. Что касается редактора, то я уже давно перешел на Sublime Text 3. На сайте все для этого есть.
DRON
(22.06.2017 в 15:22):
Не по теме: это у меня FASMW.EXE неправильный и при редактировании get_dll_list.asm комменты в UTF8 нормально не показывает или вы чем-то другим пользуетесь?
ManHunter
(22.06.2017 в 06:52):
Ну теперь точно не отвертеться, даже на лень списать не получится :)))) Заменил исходник в архиве на консольный, от себя добавил ожидание нажатия любой клавиши после вывода списка. Спасибо!
DRON
(22.06.2017 в 03:07):
Да дружит консолька с юникодом, чего ей не дружить то:
https://pastebin.com/ykAi6ENF
Редирект в файл (get_dll_list.exe >list) конечно работать не будет, но всяко лучше безумного MessageBox-а: у меня 16 DLL-ок и рука устала давить OK :)
https://pastebin.com/ykAi6ENF
Редирект в файл (get_dll_list.exe >list) конечно работать не будет, но всяко лучше безумного MessageBox-а: у меня 16 DLL-ок и рука устала давить OK :)
ManHunter
(21.06.2017 в 11:08):
Да. Выходит, что проверять лучше BaseAddress. Поправил, спасибо!
Андрей
(21.06.2017 в 10:54):
А у меня после вывода библиотек выводится мусорная строка.
Ссылка на картинку https://yadi.sk/i/aPZOR4cE3KKPs3
Значит проверка не корректна?
Ссылка на картинку https://yadi.sk/i/aPZOR4cE3KKPs3
Значит проверка не корректна?
ManHunter
(21.06.2017 в 08:03):
Консолька с юникодом не очень дружит.
user
(21.06.2017 в 05:48):
Пожалуй, в примере лучше было бы тупо вываливать листинг в стдоут,
тогда это уже была бы вполне себе утилита.
Понятно, что тогда не получилось бы такого компактного исходника, но.
тогда это уже была бы вполне себе утилита.
Понятно, что тогда не получилось бы такого компактного исходника, но.
Добавить комментарий
Заполните форму для добавления комментария
Ничем не отличается от примера, за исключением:
1. win32w.inc вместо win32wx.inc (тут вроде доп. макросы не нужны?)
2. немного по-другому определены данные и секции, в результате размер get_dll_list.exe 1 Кб