Ранние версии WinDbg'а от Microsoft не пользовались у хакеров большой популярностью и все дружно налегали на Soft-Ice, но теперь, когда поддержка последнего прекращена и он обречен на медленное, но неотвратимое умирание, возникает вопрос: как дальше жить и чем ломать? Тем временем WinDbg сильно повзрослел, и хотя он и отстой, но по целому ряду характеристик он обгоняет Soft-Ice. Сейчас я покажу, как использовать WinDbg в качестве API- и RPC-шпиона.
API- и RPC-шпионы входят в активный инструментарий хакера. Эти орудия борьбы должны быть всегда остро заточены и стоять наготове к десантированию в тыл врага для сбора информации о вызываемых функциях. Зная, какие функции (и с какими аргументами) вызывает защита, мы можем ставить точки останова, всплывая отладчиком в непосредственной близости от штаб-квартиры врага. Если же этой информации у нас нет, точки останова приходится вставить вслепую, гадая, какой именно API-функцией воспользовалась программа. В частности, одних только функций для чтения текущей даты (необходимой защите для определения периода истечения триала) существует с полдесятка, и без шпиона нет никакой возможности
угадать, какой именно из них воспользовался разработчик.
То же самое относится и к RPC-вызовам (Remote Procedure Calls), своеобразному фундаменту множества служб, к числу которых принадлежит Служба печати, да и, естественно, не только она одна.
В общем, без шпионов ломать становится совсем хреново. Но Soft-Ice не предоставляет таких возможностей, и приходится использовать сторонние средства, большинство из которых способны шпионить только за честными программами. К тому же, неудобно каждый раз выходить из отладчика, чтобы запустить очередную утилу. Намного комфортнее держать весь хакерский арсенал в одном месте. И этим местом постепенно становиться Microsoft Windows Debugger, поддерживающий множество полезных расширений на все случаи жизни и, естественно, позволяющий писать нужные нам расширения самостоятельно.
Преодолевая стойкое убеждение перед продукцией Microsoft, все же скачаем этого зверя и посмотрим, на что он способен.
Первое знакомство с WinDbg
Microsoft Windows Debugger (далее по тексту просто WinDeb) входит в состав множества продуктов: Platform SDK, DDK, WDF, а также поставляется вместе с самостоятельным пакетом «Debugging Tools for Windows», занимающим чуть больше 15 Мб. Причем версия WinDeb из комплекта «Debugging Tools for Windows» обычно самая свежая и содержит наибольшее количество всяких полезных расширений. Скачать ее можно с www.microsoft.com/whdc/devtools/debugging (32-битная и 64-битная версии). Microsoft устроила бесплатную раздачу, не требуя даже проверки подлинности копии Windows. По крайней мере, пока. В любом случае, этот пакет валяется на многих сайтах, но далеко не всегда первой свежести.
Отладчик WinDbg представлен в двух «ипостасях»: i386kd.exe (для 64-битной версии - ia64kd.exe) - консольный kernel-debugger, отлаживающий только драйверы вместе с дампами памяти ядра и требующий как минимум двух машин, связанных com-шнурком или взаимодействующих через сеть. Если двух машин нет, можно воспользоваться VMWare, поддерживающим виртуальные сетевые адаптеры и позволяющим загонять com-порт (виртуальный, естественно) в пайп. Несмотря на то, что i386kd.exe - довольно мощная и хорошая штука (подробно описанная у Шрайбера в его «Недокументированных возможностях Windows 2000»), для наших хакерских целей она не потребуется.
WinDbg.exe - представляет собой типичное GUI-приложение, довольствующееся одним компьютером и позволяющее отлаживать прикладные программы, анализировать дампы памяти, шпионить за событиями, происходящими в системе. А вот для отладки драйверов опять-таки понадобится второй компьютер, соединенный сетью или шнурком, но мы обойдемся и без шнурка.
Много полезной информации содержится в справочном файле debugger.chm, который полезно прочитать до запуска отладчика, чтобы не задавать на форумах глупых вопросов и не ломиться в открытые двери. Возможности WinDbg намного шире, чем это кажется на первый взгляд, просто до них через меню и прочие интерфейсные штучки не добраться!
ОК, начинаем рыть в глубь. В каталогах w2kchk и w2kfre валяются модули расширения для Windows 2000, конструктивно выполненные в виде динамических библиотек. Содержание обоих каталогов идентично, и разница между ними заключается в том, что *chk работает с отладочной версией ядра (checking build), а *fre - с финальной (release).
Посмотрим, что у нас здесь находится:
Модули расширения для WinDbg, предназначенные для Windows 2000
Содержимое папки C:\Program Files\Debugging Tools for Windows\w2kfre
13.08.2005 20:19 <DIR> . 13.08.2005 20:19 <DIR> .. 06.02.2004 01:38 105 499 acpikd.dll 06.02.2004 01:38 179 227 gdikdx.dll 06.02.2004 01:38 302 620 userkdx.dll 06.02.2004 01:38 106 524 vdmexts.dll 11 файлов 3 845 428 байт 2 папок 995 536 896 байт свободно
Назначение большинства модулей можно определить по их названию или, на худой конец, загрузить непонятный модуль в отладчик и вызывать его хелп. Чуть позже мы покажем, как это делается, а пока заглянем в каталог winxp, хранящий расширения, специфичные для Windows XP:
Модули расширения для WinDbg, предназначенные для Windows XP
Содержимое папки C:\Program Files\Debugging Tools for Windows\winxp
13.08.2005 20:19 <DIR> . 13.08.2005 20:19 <DIR> .. 21.01.2004 10:43 73 728 acpikd.dll 28.06.2002 15:47 4 841 default.tmf 24.02.2004 13:01 285 696 exts.dll 19.02.2004 18:19 1 096 192 kdexts.dll 21.01.2004 12:30 66 048 minipkd.dll 21.01.2004 10:26 50 176 wmitrace.dll 21.01.2004 10:37 77 312 wow64exts.dll 17 файлов 2 653 500 байт 2 папок 995 532 800 байт свободно
Как видно, набор расширений для XP намного богаче, но я все равно не изменю своей любимой Windows 2000, под которой сидел, сижу и буду сидеть, а когда же она окончательно одряхлеет, мигрирую на FreeBSD, тем более что расширения, ответственные за шпионов, хранятся в каталоге winext, общем для всех систем.
Модули расширения для WinDbg, предназначенные для осей всех типов
Содержимое папки C:\Program Files\Debugging Tools for Windows\winext
13.08.2005 20:19 <DIR> . 13.08.2005 20:19 <DIR> .. 24.02.2004 13:01 612 864 ext.dll 24.02.2004 13:01 174 592 kext.dll 19.02.2004 18:44 228 864 logexts.dll 13.08.2005 20:19 <DIR> manifest 24.02.2004 13:01 53 760 uext.dll 21.01.2004 12:28 22 528 wdfkd.dll 5 файлов 1 092 608 байт 3 папок 995 524 608 байт свободно
Файл с ничего не говорящим именем logexts.dll - это и есть шпионский компонент (ну, для шпионов маскироваться - вполне нормально и ничего удивительного тут нет).
Теперь - что касается самого WinDeb. Раскладку окон, цвет и гарнитуру шрифтов каждый может настроить под свой вкус, поскольку в конфигурации по умолчанию с отладчиком долго работать невозможно, иначе глаза опустятся куда-то в район хвоста, а для хакеров глаза - второй инструмент после серого мозгового вещества!
Так что первое, что нужно сделать с WinDeb, - это настроить его под свой собственный вкус (а вкусы, как известно, у всех разные).
Техника API-шпионажа
В состав Platform SDK изначально входило какое-то подобие API-шпиона (точнее, пародия на API-шпиона), расположенное в \Microsoft Platform SDK\Bin\WinNT\Apimon.Exe, однако оно выдавало только общую статистку по API-вызовам без учета их хронологии и постоянно падало при попытке загрузить в него что-то более сложное, чем notepad. Короче, для взлома Apimon.exe не годился. Однозначно!
Посмотрим на WinDbg, что же в нем изменилось? Забегая вперед, скажем: абсолютно все! Microsoft предоставила нам сложный и могущественный инструмент, способный решать широкий круг задач и противостоять различным антиотладочным приемам, которыми понапичканы современные защитные механизмами.
Короче, будем считать, что я тебя соблазнил. Приступаем к экспериментам. Первым делом загружаем в отладчик файл, за которым мы будем шпионить, например, все тот же блокнот. Делается это так: «File -> Open executable -> notepad.exe». Или так: нажимаем <CTRL-E>, вбиваем «notepad.exe». В крайнем случае файл можно загрузить из командной строки. Только не нажимай раскрывающуюся папку на панели инструментов - это все равно не поможет, так как она предназначена для работы с исходными текстами и их окружением, которых в нашем распоряжении, естественно, нет.
Неверное определение точки входа при загрузке исполняемого файла в WinDbg
CommandLine: C:\WINNT\NOTEPAD.EXE Symbol search path is: *** Invalid *** Executable search path is: ModLoad: 01000000 01010000 notepad.exe ModLoad: 77f80000 77ffd000 ntdll.dll ModLoad: 76ae0000 76b1e000 C:\WINNT\system32\comdlg32.dll ModLoad: 772c0000 77326000 C:\WINNT\system32\SHLWAPI.DLL ModLoad: 79060000 790c5000 C:\WINNT\system32\ADVAPI32.dll ModLoad: 71710000 71794000 C:\WINNT\system32\COMCTL32.DLL ModLoad: 7ce80000 7d0c6000 C:\WINNT\system32\SHELL32.DLL ModLoad: 777d0000 777ee000 C:\WINNT\system32\WINSPOOL.DRV ModLoad: 79500000 79511000 C:\WINNT\system32\MPR.DLL (510.508): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00071f04 ecx=00000009 edx=00000000 esi=7ffdf000 edi=00071f70 eip=77f9193c esp=0006f984 ebp=0006fc98 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 *** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll - ntdll!DbgBreakPoint: 77f9193c cc int 3
Отладчик послушно загружает файл, отображая все динамические библиотеки, перечисленные в таблице импорта, показывает содержимое регистров и устанавливает точку останова в EntryPoint. На самом деле, это мы думаем, что отладчик устанавливает точку останова в EntryPoint, а в действительности все обстоит не так! Судя по адресу 77F9193Ch, лежащему глубоко внутри NTDLL.DLL, это не совсем EntryPoint, точнее, совсем не EntryPoint, а native-API-функция DbgBreakPoint, которую можно трассировать до конца света, но так ни к чему и не прийти. Приходится выкручиваться и применять всякие недетские извращения (впрочем, для хакеров они вполне типичны).
Загружаем notepad.exe в наш любимый hiew.exe (или любой другой hex-редактор), жмем на <ENTER> для перехода в hex-режим, давим <F8> для отображения заголовка и переходим в истинную точку входа по <F5>, адрес которой (в моем случае равный 1006420h) высвечивается в левом верхнем углу экрана.
Возвращаемся в WinDbg и, находясь в окне команд (такая строчка с деловито мерцающим курсором), пишем «BP 1006420», устанавливая точку останова, после чего жмем <F5> (или даем команду g - в смысле «goto», продолжение выполнения) и ждем развития событий. А события ждать себя не заставляют:
Ручная установка бряка на истинную точку входа
0:000> BP 1006420 0:000> g ModLoad: 75e00000 75e1a000 C:\WINNT\system32\IMM32.DLL ModLoad: 10000000 10005000 C:\WINNT\system32\wmfhotfix.dll Breakpoint 0 hit eax=00000000 ebx=7ffdf000 ecx=00010101 edx=ffffffff esi=0009a0f0 edi=017af640 eip=01006420 esp=0006ffc4 ebp=0006fff0 iopl=0 nv up ei pl zr na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246 notepad+0x6420: 01006420 55 push ebp
Отладчик подгружает еще две динамические библиотеки (одна из которых - wmfhotfix.dll, заплатка от Ильфака), радостно сообщает, что «Breakpoint 0 hit» (сработала точка останова), выводит значения регистров (ну куда же без них) и первую машинную команду, стоящую в точке входа, - push ebp.
Команда u позволит дизассемблировать остальные команды, следующие за ней, помогая убедиться, что мы действительно находимся там, где нужно:
Дизассемблирование окрестностей точки входа
0:000> u notepad+0x6420: 01006420 55 push ebp 01006421 8bec mov ebp,esp 01006423 6aff push 0xff 01006425 6888180001 push 0x1001888 0100642a 68d0650001 push 0x10065d0 0100642f 64a100000000 mov eax,fs:[00000000] 01006435 50 push eax 01006436 64892500000000 mov fs:[00000000],esp
Теперь, когда все подготовительные мероприятия завершены, необходимо подключить модуль расширения. Для этого даем команду !load <name>, где name - имя модуля расширения без «.dll» (в данном случае - logexts). Полностью вся команда выглядит так:
0:000> !load logexts
Отладчик проглатывает ее как ни в чем не бывало, и создается впечатление, что ничего не происходит. Но это не так! Чтобы убедиться, что модуль расширения успешно загружен, вызовем его локальную справку, набрав команду !logexts.help. Мы видим, сколько тут всего, хорошего и разного! С одного захода это даже не разгрызть, но мы все-таки попробуем. Команда !loge [dir] активирует шпионаж за API-функциями, при желании позволяя указать каталог, в котором будет автоматически создана поддиректория LogExts для хранения логов. Логи могут писаться как в текстовом, там и в двоичном формате (формат вывода задается командой !logo), причем имя лога соответствует имени исполняемого файла, за которым он
шпионил (например, noTEPAD.EXE.txt - да-да, вот именно в таком регистре он и записывается).
Вызванная без параметров команда !logo выводит текущий формат лога. Чтобы включить текстовый формат, необходимо набрать «!logo e t», а чтобы включить все 3 параметра, необходимо трижды вызвать !logo с разными ключами. К сожалению, конструкцию «!logo e dtv» отладчик не переваривает. Редиска!
Для сокращения размеров лога и выкидывания заведомо ненужной информации WinDbg поддерживает категории API-вызовов, список которых можно вывести на экран командой !logc:
Просмотр категорий API-функций
0:000> !logc Categories: 1 AdvApi32 Enabled 2 AtomFunctions Enabled 3 AVIFileExports Enabled 4 Clipboard Enabled 5 ComponentObjectModel Enabled 6 DebuggingAndErrorHandling Enabled 7 DeviceFunctions Enabled 8 Direct3D Enabled 9 DirectDraw Enabled ... 25 User32StringExports Enabled 26 Version Enabled 27 WinSock2 Enabled
Как видно, всего имеется 27 категорий, и для просмотра функций, входящих в каждую из категорий, можно воспользоваться командой !logic p #, где # - номер категории, например, 16 - MemoryManagementFunctions.
Просмотр имен API-функций, входящих в категорию MemoryManagementFunctions
0:000> !logc p 16 MemoryManagementFunctions: AllocateUserPhysicalPages KERNEL32.DLL FreeUserPhysicalPages KERNEL32.DLL GetProcessHeap KERNEL32.DLL GetProcessHeaps KERNEL32.DLL … OpenFileMappingA KERNEL32.DLL OpenFileMappingW KERNEL32.DLL UnmapViewOfFile KERNEL32.DLL
Для шпионажа за определенными категориями функций даем команду !logc e # # #, где e - включить (enable) шпионаж, а # - перечень категорий. Ключ ‘d’ (disable), соответственно, означает исключить данную категорию (категории) API-функций из круга подозреваемых и не шпионить за ними. Команда !logc e * включает все категории (и это основной режим шпиона, в котором гоняют его хакеры при первом знакомстве с ломаемой программой).
При желании можно указать перечень динамических библиотек, за которыми следует/не следует следить. Зачастую это намного проще, чем возиться с категориями. Отображением списка текущих поднадзорных библиотек занимается команда !logm:
Просмотр списка динамических библиотек, за которыми осуществляется шпионаж
0:000> !logm Included modules: USER32.DLL GDI32.DLL ADVAPI32.DLL
Просматривая этот список, мы с удивлением обнаруживаем в нем отсутствие KERNEL32.DLL - базовой ядерной библиотеки, содержащей максимум интересующих нас функций. Попытка включить ее в список командой !logm i KERNEL32.DLL приводит к появлению многоэтажного матерного ругательства: мол, KERNEL32.DLL обязательно должна быть исключена и включению не подлежит:
Категорический отказ отладчика шпионить за KERNEL32.DLL
0:000> !logm i KERNEL32.DLL KERNEL32.DLL is mandatory for exclusion so it can't be included. Included modules:
На самом деле, стоит только нажать "F5", как в логе (параллельно выводимом на экран и в файл) появятся перехваченные имена API-функций, принадлежащих KERNEL32.DLL:
Фрагмент шпионского протокола, содержащего всю необходимую нам инфу
Thrd 4c4 010029BD GetProcAddress( NULL "RegisterPenApp") -> NULL [FAIL] Thrd 4c4 77E202F2 LoadLibraryExW("INDICDLL.dll" NULL ALTERED_SRCH_PATH) -> 0x6E380000 Thrd 4c4 77106CF2 GetProcAddress( 0x77F80000 "NtQuerySystemInformation") -> 0x77F889DC Thrd 4c4 77106D0D GetProcAddress( 0x77F80000 "NtOpenFile") -> 0x77F886AC Thrd 4c4 77106D1A GetProcAddress( 0x77F80000 "RtlInitUnicodeString") -> 0x77FABE9C Thrd 4c4 77E202F2 LoadLibraryExW("PDSHELL.DLL" NULL ALTERED_SRCH_PATH) -> 0x00F30000 Thrd 4c4 77E202F2 LoadLibraryExW("SSSensor.dll" NULL ALTERED_SRCH_PATH) -> 0x013B0000 Thrd 4c4 76AE1DAB GetProcAddress( 0x79430000 "GetUserDefaultUILanguage") -> 0x7947106B Thrd 4c4 7CEAAF39 GetProcAddress( 0x77E10000 "GetSystemMetrics") -> 0x77E33277 Thrd 4c4 7CEAAF4A GetProcAddress( 0x77E10000 "MonitorFromWindow") -> 0x77E2920B Thrd 4c4 7CEAAF5B GetProcAddress( 0x77E10000 "MonitorFromRect") -> 0x77E20D54 Thrd 4c4 7CEAAF6C GetProcAddress( 0x77E10000 "MonitorFromPoint") -> 0x77E2A0F2 Thrd 4c4 7CEAAF7D GetProcAddress( 0x77E10000 "EnumDisplayMonitors") -> 0x77E1F61D Thrd 4c4 7CEAAF8E GetProcAddress( 0x77E10000 "EnumDisplayDevicesW") -> 0x77E18A08 Thrd 4c4 7CEAAFAE GetProcAddress( 0x77E10000 "GetMonitorInfoW") -> 0x77E2A07E
В наше распоряжение попадают номера потоков (thrd), адреса вызова API-функций вместе с передаваемыми ими аргументами. По приведенному выше фрагменту лога видно, что, вызвав функцию GetProcAddress(NULL "RegisterPenApp") по адресу 010029BDh, блокнот погрузился в пучину системных библиотек, лежащих далеко за пределами принадлежащей ему области адресов. Но это не главное. Главное то, что шпион от Microsoft работает и успешно шпионит, практически ни в чем не уступая большинству своих конкурентов, а кое в чем их даже и обгоняя!
Техника RPC-шпионажа
RPC-шпионаж осуществляется во всем аналогично API-шпионажу (ну, практически аналогично), только вместо logexts используется расширение rpcexts, загружаемое командой !load rpcexts и выдающее справку по своим ключам командой !rpcexts.help.
Ключи же настолько обширны, что требуют для своего описания целой статьи. Но в большинстве случаев встроенного хелпа вполне достаточно!
Заключение
Мы рассмотрели всего лишь 2 расширения отладчика WinDbg из очень многих! Ну так чего же мы сидим? Чего ждем?! Загружаем все расширения одно за другим, даем команду !name.help, смотрим, курим, читаем, втыкаем, после чего экспериментируем, постигая все новые границы и мысленно сравнивая возможности WinDbg и Soft-Ice. Но, несмотря ни на что, Soft-Ice все-таки жалко. Хороший был отладчик...
|