Живучий код Крис Касперски aka мыщъх Спецвыпуск Xakep, номер #045, стр. 045-064-4 je l3 add edi,4 inc eax loop l4 jmp ecx l3: pop esi mov edx,dword ptr [esi+24h] add edx,ebx shl eax,1 add eax,edx xor ecx,ecx mov cx,word ptr [eax] mov eax,dword ptr [esi+1Ch] add eax,ebx shl ecx,2 add eax,ecx mov edx,dword ptr [eax] add edx,ebx pop esi mov edi,esi xor ecx,ecx ;Get 3 Addr mov cl,3 call loadaddr add esi,0Ch Главный недостаток этого способа – в его чрезмерной громоздкости, ведь объем shell-кода ограничен, но, к сожалению, ничего лучшего пока не придумали. Поиск базового адреса можно и оптимизировать (что мы сейчас продемонстрируем), но от разбора экспорта никуда не уйти. Это дань, выплачиваемая за мобильность. Огонь прямой наводкой – PEB Из всех способов определения базового адреса наибольшей популярностью пользуется анализ PEB (Process Environment Block – блок окружения процесса) – служебной структуры данных, содержащей, кроме прочей полезной информации, базовые адреса всех загруженных модулей. Эта популярность необъяснима и незаслужена. Ведь PEB – это внутренняя кухня операционной системы Windows NT, которой ни документация, ни включаемые файлы делиться не собираются, и лишь Microsoft Kernel Debugger обнаруживает обрывки информации. Подобная недокументированность не может не настораживать. В любой из последующих версий Windows структура PEB может измениться, как это уже неоднократно происходило, и тогда данный прием перестанет работать, а работает он, кстати говоря, только в NT. Линейка 9x отдыхает. Так что задумайтесь: а так ли вам нужен этот PEB? Единственное его достоинство – предельно компактный код: Определение базового адреса KERNEL32.DLL путем анализа PEB 00000000: 33C0 xor eax,eax ; eax := 0 00000002: B030 mov al,030 ; eax := 30h 00000004: 648B00 mov eax,fs:[eax] ; PEB base 00000007: 8B400C mov eax, [eax][0000C] ; PEB_LDR_DATA 0000000A: 8B401C mov eax, [eax][0001C] ; 1-й элемент InInitOrderModuleList 0000000D: AD lodsd ; следующий элемент 0000000E: 8B4008 mov eax, [eax][00008] ; базовый адрес KERNEL32.DLL Раскрутка стека структурных исключений Обработчик структурных исключений, назначаемый операционной системой по умолчанию, указывает на функцию KERNEL32!_except_handler3. Выяснив ее адрес, мы определим положение одной из ячеек, гарантированно принадлежащей модулю KERNEL32.DLL. Останется округлить её адрес до величины, кратной 1.0000h, и заняться поисками PE-сигнатуры по методике, изложенной выше, с той лишь разницей, что проверять доступность указателя перед обращением к нему не нужно, так как теперь он заведомо доступен. Практически все приложения используют свои обработчики структурных исключений, и потому текущий обработчик не совпадает с назначенным операционной системой, а shell-коду потребуется раскрутить цепочку обработчиков, добравшись до самого конца. Последний элемент списка и будет содержать адрес KERNEL32!_except_handler3. Достоинство этого приема в том, что он использует только документированные свойства операционной системы, работая на всех ОС семейства Windows исключая, разумеется, Windows 3.x, где все не так. К тому же, он довольно компактен. |