Раздел: Документация
0 ... 45 46 47 48 49 50 51 ... 102 Листинг 4.20. Функция, определяющая базовый адрес загрузки KERNEL32.DLL путем поиска сигнатур "MZ" и "РЕ" в оперативной памяти
Существует и более элегантный способ определения базового адреса загрузи. KERNEL32.DLL, основанный на РЕВ (Process Environment Block — блок окруженю процесса), указатель на который содержится в двойном слове но адрес-. FS: [00000030h], а сам РЕВ разлагается следующим образом (листинг 4.21). Листинг 4.21. Реализация структуры РЕВ в W2K/XP РЕВ
РЕВ LDR DATA PTR +0Ch РЕВ По смещению OCh в нем содержится указатель на PENLDRDATA, представляющпг собой список загруженных динамических библиотек, перечисленный в порял ке их инициализации (NTDLL.DLL инициализируется первой, следом за ней иде KERNEL32.DLL) (листинг 4.22). Листинг 4.22. Реализация структуры PEB LDR DATA в W2K/XP PFBJ DR DATA STRUC PEB LDR cbsizeDD РЕВ LDR FlagsDD PEB LDR Unknown8DD PE B LDR I nLoadO-derModul eLi stLI ST ENTRY PEB LDR InMemoryDrderModu1eLi stLIST ENTRY PEB LDR InIriit0rderModu1eListLISTJNTRY ЭЕВ LDRDATA ENDS +0C ~DCh -:c.h list entry struc le forward le backward le image base le :mage time list entry dd*forward in the list dd*oackwa rd in the li st ddimagebase of ntdl1.dll ddimagetimestamp OOh 04h 08h 44h Секретыпро /ктвешю. вся идея заключается в том, чтобы, прочитав двойное слово по ад-l-v FS-[00000030ri], преобразовать его в указатель на РЕВ и перейти по адресу, "i который ссылается указатель, лежащий по смещению OCh от его начала — ItilnitOrderModuleList. Отбросив первый элемент, принадлежащий NTDLL.DLL, мы тЯУЧ11М указатель на LISTENTRY, содержащий характеристики KERNEL32.DLL (в частности, базовый адрес загрузки храниться в третьем двойном слове). Впрочем это легче программировать, чем говорить, и все вышесказанное с легкостью уметается в пяти ассемблерных командах. 1алее приведен код, выдранный из червя Love San, до сих пор терроризирующего Интернет (листинг 4.23). Данный фрагмент не имеет никакого отношения к автору вируса, и был им «позаимствован» из сторонних источников. Об этом говорят «лишние» ассемблерные команды, предназначенные для совместимости с Windows 9х (в ней все не так, как в NT), но ведь ареал обитания Love San ограничен исключительно NT-подобными системами, и он в принципе не способен поражать Windows 9х! Листинг 4.23. Фрагмент червя Love San, ответственный за определение базового адреса загрузки KERNEL32.DLL и обеспечивающий червю завидную независимость от версии атакуемой операционной системы data:004046FE 64 А1 30 00 00 data:00404704 85 СО dale:00404706 78 ОС data:00404708 8В 40 ОС data :0040470В 8В 70 1С InlmtOrderModjleList data:0040470E AD data:0040470F 8B 68 08 data:00404712 ЕВ 09 data:00404714: ------------- data:00404714 loc 404714: data .00404714 8B 40 34 data:00404717 8B A8 B8 00 00 data:00404717 data:004047lD loc 4C471D.: CODE XREF: kk get kernel32-16*j Ручной разбор РЕ-формата, несмотря на свое устрашающее название, реализуется элементарно. Двойное слово, лежащее по смещению 3Ch от начала •ювого адреса загрузки, содержит смещение (не указатель!) РЕ-заголовка файла, который, в свою очередь, в 78h своем двойном слове содержит смешение таблицы экспорта, 18h-lBh и 20h-23h байты которой хранят количество кспортируемых ФУНКНИЙ и смещение таблицы экспортируемых имен соот-Ветственно (хотя функции экспортируются также и но ординалам, смеще-,,е таблицы экспорта которых находится в 24h-27h байтах). Запомните эти рачения — 3Ch, 78h, 20h/24h — они будут вам часто встречаться в коде червей эксплонтов, значительно облегчая идентификацию алгоритма последних листинг 4.24). mov еах, large fs:30h test еах. еах js short 1ос 404714 inov еах, [eax+OCh] mov esi. [eax+lCh] lodsd inov ebp [eax+8] jmp short PE3 base -- мы на w9x --> PEB LDR DATA 1й элемент следующий элемент базовый адрес KERNEL32.DLL loc 4047ID CODE XREF: kk yet kernel32+A~j mov eax. [eax-»34h] inov ebp. Leax+0B8h] 6a: Листинг 4.24. Фрагмент червя Love San, ответственный за определение адреса таблицы экспортируемых имен .data-.00404728 .data:004C472C .data:0040472F .data .-00404733 .data:00404735 .data:00404738 .data:C040473B movebp. [esp+arg 4j moveax. [ebp+3Ch] movedx. [ebp+eax+78h] addedx. eop movecx. [edx+18h] movebx. [edx+20hj addebx. ebp базовый адрес загрузк, . на РЕ-заголовокVl3< на таблицу экспорта кол-во экспортируемых функци-на таблицу экспортируемых адрес таблицы экспор имен имен Теперь, отталкиваясь от адреса таблицы экспортируемых имен (в грубом ближеиии представляющей собой массив текстовых ASCIIZ-стпок к-™-, которых соответствует «своей» API-функции), мы сможем найти всенеобх( димое. Однако от посимвольного сравнения лучше сразу отказаться, и вот по чему: во-первых, имена большинства API-функций чрезвычайно тяжеловесны а размер shell-код жестко ограничен, во-вторых, явная загрузка API-функций чрезвычайно упрощает анализ алгоритма shell-кода, что не есть хорошо. Всех этих недостатков лишен алгоритм хеш-сравнения, в общем случае сводящийся к «свертке» сравниваемых строк по некоторой функции f. Подробнее об этом можно прочитать в соответствующей литературе (например, «Искусство программирования» Кнута), здесь же мы просто приведем программный код, снабженный подробными комментариями (листинг 4.25). Листинг 4.25. Фрагмент червя Love San, ответственный за определения индекса функции в таблице : CODE XREF: Kk get proc ad"+36vj : —> ошибка : в ecx кол-во экспорт, функций : смещение конца массива экспорт, фикции : адрес конца массива экспорт. $умцм : F0I := С : сбрасываем ф.-аг чатавлеч/я CDDE XRFE: kk get proc adr+30vj чи-аем очередной символ имени ФУН это конец строк/i? если конец, то прыг ча коней хешируем имя функции на лету-- ...накапливая хеш-сучку в регистр
: CDDE XREF: Kk get proc adr--29 : это xen "нашей" функции? : если нет. продолжить перебор Зная индекс целевой функции в таблице экспорта, легко онреДелМ Это можно сделать, например, таким образом (листинг 4.26). аДР11 0 ... 45 46 47 48 49 50 51 ... 102
|