Низкоуровневое программирование для Дzenствующих

Вид материалаДокументы

Содержание


2.6 NTDLL.DLL – Windows Loader
3. 64-bit PE-files
True : false
IDA вполне готова, HIEW
Подобный материал:
1   ...   5   6   7   8   9   10   11   12   ...   42

2.6 NTDLL.DLL – Windows Loader


Также необходимо разобраться, что же происходит при загрузке exe/dll в память. Сразу оговорюсь, что процесс этот не будет рассмотрен вообще – не любим повторов.

Для начала необходимо достаточно четко представлять себе архитектуру распределения памяти в Win NT+. Думается, что лучше, чем это сделал Джеффери Рихтер в своей книге "Windows для профессионалов" это не объяснил никто. Такое понимание сильно облегчает жизнь. Например, если вы встречаете нечто вроде адреса 7xxxxxxх, то можете не сомневаться – это адрес какой-нибудь API функции из системных библиотек. Не плохо бы представлять себе и границу стека. ПРИБЛИЗИТЕЛЬНО регион стека в любом вьювере адресного пространства легко опознать по атрибуту страницы PAGE_GUARD. Приблизительно потому, что этот атрибут страницы смещается по стеку во время выполнения.

Загляните в MSDN - статья Q147314 – описание флагов Session Manager. Среди них есть и такой, который требует от NTDLL.dll "озвучивать" свои действия, т.е. выдавать сообщения в окно отладчика (WinDBG, отладчика VS и т.п.). Для того чтобы не морочить себе голову запоминанием флагов, MS создала утилиту GFlags.exe, которая поставляется вместе с комплектом отладочных утилит с сайта MS. Скачать это дело можно совершенно свободно. Мы бы порекомендовали активировать флаг "озвучивания" действий лоадера, т.к. это будет исключительно полезно, например, в тех случаях, когда сдампленная программа не запускается, а лоадер говорит: "Application failed to initialize properly". В этом случае вы сможете быстро найти ту функцию ntdll.dll, которая отказалась "принять" файл и, зная алгоритм ее работы, у вас уже будет какой-то ключик. Это адова работа, но в некоторых случаях такая методика помогает.

Учтите, что ntdll.dll автоматически проецируется на адресное пространство любого Windows-приложения.

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

Поверхностно алгоритм работы лоадера расписан на ссылка скрыта. Так же алгоритм работы можно приблизительно уяснить из исходных кодов Wine и ReactOS (ссылка скрыта - своеобразный аналог Wine, только цели чуть другие). Во всем этом деле полезным будет справочник по Native API - ссылка скрыта. Также многие функции лоадера, например RtlImageHeader и т.п., прокомментированы на более высоком уровне в MSDN – библиотека imagehlp.dll.

Для облегчения анализа обязательно сгрузите себе файлы символов – pdb/dbg.

mdsl.microsoft.com

Современные утилиты (VS. NET 2003/Driver Studio 2.7+) имеют специальные средства, которые облегчают нам жизнь при копании в недрах Windows. Раньше приходилось топать на ссылка скрыта, и сливать символы ручками, конвертировать их ручками и т.п. Теперь все достаточно просто. В состав DS 2.7 и старше входит утилита Symbol Retriever, которая позволяет сливать символы со специального сервера MS. ссылка скрыта. Естественно, что и VS .NET 2002/2003 способна обращаться к этому серверу (еще бы!). Достаточно задать в переменных окружения _NT_SYMBOL_PATH, и присвоить ей значение типа
SRV*\\Symbols\Symbols* ссылка скрыта. Более подробно - MSDN - статьи Джона Роббинса.

Самое главное при дизассемблировании лоадера – начинать плясать от определения структур данных. При дизассемблировании файла в IDA вставьте структуры winnt.h (метод описан выше), и начинайте превращать код из неудобоваримого:

mov ax, [edi+4]

в

mov ax, [edi+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName]

Удачи! :)

3. 64-bit PE-files


Ну, не так страшен черт, как его малюют. PE файлы изначально проектировались очень разумно, поэтому изменения, связанные с переходом на 64-битную архитектуру, минимальны. С другой стороны – то же все не слишком безоблачно, в первую очередь, из-за типа int64. Но давайте по порядку.

Итак, 64-bit PE файлы еще называются как PE32+. Отличить их от обычного файла можно по сигнатуре. Сигнатура расположена в поле OptionalHeader.Magic и равна

#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b //PE

#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b //PE32+

Для определения типа файла можно использовать эту функцию, которой необходимо передать адрес на проекцию файла:


/***********************

* Return value: TRUE если файл 64-х битный, FALSE если файл 32-х битный

* Parameters: pMem - возвращаемое значение от CreateFileMapping,

* либо от GetModuleHandle

************************/


BOOL IsPEPlus(LPVOID m_Map)

{

PIMAGE_NT_HEADERS pNT;

pNT = ImageNtHeader(m_Map);

if(pNT)

return pNT->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ?

TRUE : FALSE;

else

return FALSE;

}


Различий же в строении самих структур (т.е. секций, директорий и т.п.) нет. Естественно, что DWORD заменяется на ULONGLONG, т.е. unsigned int64 (ха-ха!). Разумеется, добавлены новые типы флагов для совместимости, например, с AMD64 и т.п. В директории импорта теперь появляется структура IMAGE_THUNK_DATA64 с типами ULONGLONG, изменения коснулись и ресурсов.

Особо останавливаться на этом не будем.

Такие модули начнут попадаться все чаще и чаще, однако особой паники, думается нам, в этом нет. IDA вполне готова, HIEW грустно говорит об "Unknown header magic" и редактировать поля более не позволяет, LordPE и PE Tools на высоте.

Единственное, что смущает во всем этом деле – так это сам тип int64, а, вернее, его полное отсутствие на 32-битных машинах. Компиляторы просто-напросто эмулируют int64 путем помещения двух DWORD в стек, причем, понятия unsigned int64 пока нет вообще! Словом, у MS ещё не все ладно с поддержкой самого типа. А в будущем… Конечно, проблему решат. Например, переходом на Windows IA-64.