Дерево процессов
Обычно, малварь создает свой собственный процесс (реже— внедряется в чужие), при этом у нее возникает вполне естественное желание скрыть этот процесс, убрав его из "Диспетчера Задач" и прочих системных утилит. Как это она делает? Для предоставления информации о процессах NT поддерживает два механизма: набор документированных процедур TOOLHELP32 (доставшийся в "наследство" от 9x), реализованных в KERNEL32.DLL, и недокументированная функция NtQuerySystemInformation, экспортируемая NTDLL.DLL, и представляющую собой тонкую "обертку" вокруг системного сервиса 97h, реализованного в NTOSKRNL.EXE. На самом деле, главная функция TOOLHELP32 — CreateToolhelp32Snapshot — полностью опирается на NtQuerySystemInformation, так что фактически механизм у нас один, только интерфейсы разные.
Малварь может легко перехватить процедуры Process32First/Process32Next
из TOOLHELP32, только это ей ничего не даст, поскольку, практически все утилиты ("Диспетчер Задач", FAR и даже примитивный tlist.exe из SDK) работают исключительно через NtQuerySystemInformation
(что легко подтверждается установкой точки останова в soft?ice). Однако, перехватить NtQuerySystemInformation
с прикладного уровня ничуть не сложнее, чем процедуры из набора TOOLHELP32! Существует множество путей как это сделать:
q модифицировать NTDLL.DLL на диске, установив в начало функции NtQuerySystemInformation
команду перехода на свой обработчик (расположенный где-нибудь в свободном месте внутри NTDLL.DLL), и "вычищающий" из выдаваемой ею информации всякое упоминание о себе. способ простой как барабан, но грязный и легко обнаруживаемый путем дизассемблирования NTDLL.DLL или сравнением ее с оригиналом; так же малвари придется противостоять SFC и установке ServicePack'ов некоторые из которых обновляют NTDLL.DLL;
q модифицировать NTDLL.DLL!NtQuerySystemInformation в памяти; поскольку NT поддерживает механизм copy-on-write, автоматически "расщепляющий" страницы памяти при записи, модификация NTDLL.DLL приобретает локальный характер, ограниченный контекстом процесса-писателя.
то есть, чтобы воздействовать на "Диспетчер Задач", в него прежде необходимо внедриться! вот один из возможных сценариев: малварь создает свою DLL и прописывает ее в следующую ветку системного реестра: HKLM\Software\Microsoft\Windows NT\CurrentVersion\windows\AppInit_DLLs, в результате чего эта DLL после будет отображаться на _все_ процессы. для большей скрытности можно модифицировать NTDLL.DLL только в контексте тех процессов, которые используются для вывода списка задач (taskmng.exe, far.exe, tlist.exe и т. д.). в этом случае, заглянув отладчиком внутрь NtQuerySystemInformation, мы не найдем никаких следов малвари! можно, конечно, проверить AppInit_DLLs, но это не единственный способ внедрения, так что задача выявления малвари резко усложняется;
q модифицировать таблицу импорта taskmng.exe ("Диспетчер Задач"), proclist.dll (плагин FAR'а, ответственный за вывод списка процессов), tlist.exe на диске (или в памяти), подменив вызовов NtQuerySystemInformation
своей собственной функций оберткой. такой перехват легко обнаруживается путем сравнения исполняемых файлов с их образом памяти, который может быть получен путем снятия дампа утилитой типа PE?TOOLS или старым добрым Procdump'ом, к тому же малвари придется дополнительно перехватывать GetProcAddress, чтобы отслеживать динамическую загрузку NTDLL.DLL;
При наличии прав администратора, малварь может проникнуть в NTOSKRNL.EXE и подменить сервис 97h своим собственным обработчиком. Тогда с прикладного уровня обнаружить зловредный процесс уже не удастся и придется спускаться на уровень ядра, подробно рассмотренное в разделе. "восстановление SST".
Soft-Ice – единственная из всех известных мыщъх'у программ, которая не использует NtQuerySystemInformation и для отображения списка процессов самостоятельно разбирает базовые структуры операционной системы, а потому легко выявляет скрытые процессы.
Допрос потоков
В последнее время все чаще и чаще малварь не создает для себя отдельный процесс (который очень легко заметить), а предпочитает внедряться в один из уже существующих. Для этого используются два механизма. В первом малварь выделяет в целевом процессе блок памяти функцией VirtualAllocEx, копирует себя через WriteProcessMemory
и создает удаленный поток посредством CreateRemoteThread. Второй механизм начинается так же, как и первый, только вместо создания удаленного потока, малварь останавливает текущий поток процесса, и изменяет регистр EIP
функцией SetThreadContext
(естественно, предварительно сохранив его оригинальное значение через GetThreadContext), передавая управление своей собственной процедуре, вызывающей CreateThread, восстанавливающей EIP и "размораживающей" ранее остановленный поток. Первый механизм работает только на NT, второй— на всех 32-разядных системах семейства Windows.
Как обнаружить такой метод вторжения? Естественно, количество потоков атакуемого процесса увеличивается на единицу, однако, это еще не показатель. Никогда и никогда не может сказать точно сколько у приложения должно быть потоков. Даже его непосредственный разработчик! Проведем простой эксперимент. Запустим "Блокнот" и, переключившись на Диспетчер Задач, увидим один-единственный поток. Теперь зайдем в меню "файл" и скажем "открыть". Количество потоков внезапно подскакивает аж по пяти! Закрываем окно открытия файла — один поток исчезает, остаются четыре. Что это за ерунда такая?! Оказывается, все дело в динамических библиотеках SHLWAPI.DLL, RPCRT4.DLL и OLE32.DLL, "обслуживающих" окно и порождающих свои собственные, дочерние, потоки. Некоторые драйвера так же могут порождать потоки в чужих приложениях (как правило, с целью вызова прикладных API). Нам необходимо как-то научиться отличать "легальные" потоки от "нелегальных", иначе наша борьба с малварью обречена.
Вот идея, простая как 3х дюймовая дискета: стартовый адрес легального потока лежит в пределах страничного имиджа (в секции .code и .text), а нелегального — в куче, т. е. области динамической памяти, выделенной функцией VirtualAllocEx.
Чтобы разоблачить нелегалов, нам, прежде всего, понадобится карта адресного пространства. soft-ice отображает ее не в самом наглядном виде и лучше воспользоваться OllyDbg или PE-TOOLS.
В OllyDbg в меню "file" выбираем "attach" и указываем процесс, чьи потоки мы будем исследовать. После успешного присоединения к процессу говорим "view" à "memory" или давим <ALT-M>. Получаем карту следующего вида:
Контрразведка с soft-ice в руках
крис касперски ака мыщъх, no-email
антивирусы (даже со всеми апдейтами) далеко не всегда распознают малварь и опытные хакеры доверяют только своим собственному хвосту, отладчику soft-ice и другому низкоуровневому инструментарию, позволяющему пробурить нору до самого ядра и разоблачить зловредные программы, где бы они ни скрывались!
функция ZwQuerySystemInformation
Когда происходит вызов прерывания, процессор автоматически переключается с прикладного уровня (ring 3) в режим ядра (ring 0), передавая управление функции KiSystemService, реализованной внутри NTOSKRNL.EXE и опирающейся на Таблицу Системных Дескрипторов, она же SDT (System Descriptor Table). Собственно, дескрипторов в ней всего два — один для системных вызовов, другой — для драйвера win32k.sys, куда упрятали весь графический интерфейс. На серверах добавляется и третий дескриптор — IIS, назначение которого ясно из его названия.
исходный код демонстрационной
Компилируем, запускаем, заходим в soft-ice, даем команду "THREAD -x" (вывод детальной информации о потоках) и смотрим полученный результат:
:THREAD -x
Extended Thread Info for thread 374
KTEB 873CFDA0 TID: 374 Process: va_thread(11C)
Start EIP: KERNEL32!SetUnhandledExceptionFilter+001A (77E878C1)
User Stack: 00030000 - 00130000 Stack Ptr: 0012FD24
Extended Thread Info for thread 238
KTEB: 82007020 TID: 238 Process: va_thread(11C)
Start EIP: KERNEL32!CreateFileA+00C3 (77E92C50)
User Stack: 00420000 - 00520000 Stack Ptr: FFFFFFFF
Extended Thread Info for thread 30C
KTEB: 82007AC0 TID: 30C Process: va_thread(11C)
Start EIP: KERNEL32!CreateFileA+00C3 (77E92C50)
User Stack: 00530000 - 00630000 Stack Ptr: FFFFFFFF
информация о потоках, сообщенная soft-ice (приводится в сокращенном виде)
Вот так номер! soft-ice не смог определить истинные стартовые адреса потоков, заблудившись в недрах KERNEL32.DLL. Что ж, попробуем другой инструмент — Process Explorer от Марка Руссиновича, весьма нехило разбирающегося во внутренностях операционных систем от Microsoft (и даже участвующим в написании книги "Windows NT Internals". Скачиваем (совершенно бесплатно) Process Explorer, запускаем, наводим курсор на "va_thread.exe", далее в контекстом меню выбираем пункт "Properties" и в открывшемся диалоговом окне переходим к вкладке "Threads".
информация о четырех потоках, выданная OllyDbg
Стартовый адрес (entry) определен только для одного из потоков — 50Ch да и тот, вероятно, служит для связки отлаживаемого процесса с OllyDbg. Стартовые адреса остальных потоков выставлены в ноль, но ведь это же не так!!!
Щелкам мышью по потоку c идентификатором 558h (естественно, при следующем запуске программы, идентификаторы потоков будут другими) и получаем код следующего содержания, который (судя по карте памяти), принадлежит страничному имиджу, следовательно, это — легальный поток.
401000 55 PUSH EBP
401001 8B EC MOV EBP,ESP
401003 B8 01000000 MOV EAX,1
401008 85C0 TEST EAX,EAX
40100A 74 02 JE SHORT va_threa.0040100E
40100C EB F5 JMP SHORT va_threa.00401003
код потока 558h, находящегося в пределах страничного имиджа
Переходим к окну стека, перемещая ползунок на самый низ. На дне стека видим аргумент, переданный потоку (второе двойное слово, в данном случае равное — 999h) и… стартовый адрес потока, лежащий в третьем двойном слово, и в данном случае равный 401000h, что полностью согласуется с листингом 1. (На самом деле, в зависимости от способа создания потока стартовый адрес может лежать как в третьем, так и во втором слове, поэтому автоматические утилиты и путаются).
51FFDC FFFFFFFF End of SEH chain
51FFE0 79481F54 SE handler
51FFE4 79432B08 KERNEL32.79432B08
51FFE8 00000000
51FFEC 00000000
51FFF0 00000000
51FFF4 00401000 va_threa.00401000 ; ß стартовый адрес потока 558h
51FFF8 00000999 ; ß
аргумент, переданный потоку
51FFFC 00000000 ; ß дно пользовательского стека потока
на дне пользовательского
Переходим к следующему потоку — 55Ch. Код выглядит точно так как и раньше (ведь мы запустили два экземпляра одной и той же функции!), а вот содержимое дна стека слегка изменилось:
62FFDC FFFFFFFF End of SEH chain
62FFE0 79481F54 SE handler
62FFE4 79432B08 KERNEL32.79432B08
62FFE8 00000000
62FFEC 00000000
62FFF0 00000000
62FFF4 00520000 ; ß стартовый адрес потока 55Сh
62FFF8 00000666 ; ß
аргумент, переданный потоку
62FFFC 00000000 ; ß дно пользовательского стека потока
на дне пользовательского
Как мы помним, 666h – это аргументы, переданные "нечестной" копии потока, а 520000h – его стартовый адрес, принадлежащий (если верить карте памяти) блоку памяти, выделенному функцией VirtualAlloc:
Address Size Owner Section Contains Type Access Initial
400000 1000 va_threa PE header Imag R RWE
401000 4000 va_threa .text code Imag R RWE
405000 1000 va_threa .rdata imports Imag R RWE
406000 2000 va_threa .data data Imag R RWE
410000 2000 Map R R
51E000 1000 Priv RW Guar RW
51F000 1000 stack of thr Priv RW Guar RW
520000 1000 Priv RWE RWE
62E000 1000 Priv RW Guar RW
карта памяти процесса
Последний поток — 578h представляет собой основной поток программы и хранит своей стартовый адрес _не_ в третьем, а во втором (!) двойном слове:
12FFE0 FFFFFFFF End of SEH chain
12FFE4 79481F54 SE handler
12FFE8 79432B18 KERNEL32.79432B18
12FFEC 00000000
12FFF0 00000000
12FFF4 00000000
12FFF8 00401405 va_threa.<ModuleEntryPoint>
; ß
стартовый адрес потока 578h
12FFFC 00000000 ; ß дно пользовательского стека потока
поток 578h хранит свой стартовый адрес не в третьем, а во втором двойном слове!
Свершилось! Мы научились быстро и просто определять стартовые адреса потоков, надежно отличая "левых" от "правых". Кстати, чтобы каждый раз не сверяться с картой памяти можно использовать следующий трюк. Если при нажатии стартового адреса в контекстом меню OllyDbg присутствует строчка "Follow in Disassembler" – он принадлежит страничному имиджу (т. е. легальному потоку) и, соответственно, наоборот.
протокол работы с soft-ice, демонстрирующий получение адреса системного сервиса 97h
Как мы видим, в данном случае, функция NtQuerySystemInformation никем не перехвачена, что очень хорошо!
Чтобы просмотреть содержимое SST в soft-ice достаточно дать команду "NTCALL". На "стерильной" машине _все_ вызовы указывают внутрь NTOSKRNL.EXE, а если это не так, то их кто-то перехватил. Это может быть как зловредная малварь, так и вполне безобидный драйвер какого-нибудь защитного механизма или, например, брандмауэр.
Для восстановления SST можно использовать ее копию, хранящуюся внутри NTOSKRNL.EXE, правда, найти ее на диске значительно сложнее, чем в памяти. Проще всего использовать отладочные символы (которые можно бесплатно сгрузить с сервера http://msdl.microsoft.com/download/symbols с помощью библиотеки dbghelp.dll, входящей в состав бесплатного пакета Debugging Tools). Адресу SST соответствует метка _KiServiceTable
и в моей версии системы она располагается по адресу 4704D8h (в файле):
.data:004704D8 BF B3 4A 00 _KiServiceTable dd offset _NtAcceptConnectPort@24
.data:004704DC 6B E8 4A 00 dd offset _NtAccessCheck@32
.data:004704E0 F3 DE 4B 00 dd offset _NtAccessCheckAndAuditAlarm@44
копия таблицы системных вызовом, хранящаяся внутри NTOSKRNL.EXE
А если отладочных символов нет? Тогда находим все перекрестные ссылки к KeServiceDescriptorTable
(т. е. просто ищем ее адрес, записанный с учетом обратного порядка байт на x86, задом наоборот). Одна из них ведет к инструкции типа "mov [mem], imm32" и представляет собой смещение оригинальной SST (imm32), записываемой в KeServiceDescriptorTable[0]. Как нетрудно убедиться дизассемблером, изначально SDT пуста и инициализируется на стадии загрузки ядра не экспортируемой функцией KiInitSystem.
.data:0046AB80 ; Exported entry 516. KeServiceDescriptorTable
.data:0046AB80 public _KeServiceDescriptorTable
.data:0046AB80 _KeServiceDescriptorTable dd 0
неинициализированная SDT-таблица, хранящаяся в NTOSKRNL.EXE
Ниже, в качестве примера, продемонстрирован поиск SST в hiew'e:
просмотр IDT в soft-ice
В дополнение к этому, малварь может устанавливать в начало (или даже середину!) некоторых ядерных функций jump на свой обработчик, контролирующий целостность перехваченной SST/IDT. Для выявления такого способа перехвата, необходимо сравнить образ ядра с файлом NTOSKRNL.EXE, что можно осуществить при помощи утилиты PE-TOOLS с плагином eXtreme Dumper или сдампить ядро непосредственно из самого soft-ice (что намного надежнее) с установленным расширениями IceExt или IceDump.
поиск файлов, созданных
Конечно, чем позже мы спохватимся, тем сложнее отличить "легальные" файлы от "нелегальных", особенно если на компьютер ставится большое количество самого разнообразного программного обеспечения. Но все файлы, устанавливаемые инсталлятором (где он их не размещал — в Program Files, WINNT или System32), имеют одну и ту же дату создания с небольшим разбросом по времени (ведь файлы создаются не параллельно, а последовательно), поэтому их стразу можно исключить из списка подозреваемых. А оставшиеся — подвергнуть тщательному допросу (см. врезку "признаки вредоносных файлов").
soft-ice показывает процесс sysrtl, отсутствующий в "Диспетчере Задач"
Теоретически, малварь может внедриться в soft-ice и перехватить любую из его команд (например, команду "PROC"), действуя по той же схеме, что и IceExt/IceDump (благо, что обе утилиты распространяются в исходных текстах), но в живой природе такие "монстры" пока что не встречались. Можно надеяться, что IceExt, скрывающий soft-ice от большинства защит, скроет его и от малвари, однако, при этом остается угроза сигнатурного поиска отладчика в памяти; к тому же на хакерских форумах не первый год обсуждается гипотетический алгоритм скрытия, перехватывающий функции переключения контекста и "вытирающий" себя в промежутках между ними. Однако, реализация такого проекта упирается в непреодолимые практические трудности. Формат процессорных структур непостоянен и меняется от одной версии системы к другой, к тому же с ними взаимодействуют множество недокументированных функций, вызываемых в разное время из различных мест и малварь, пытающаяся замаскироваться, постоянно обрушивает систему в BSOD, чем сразу себя и разоблачает.
Таким образом, будем считать, что связки из soft-ice + IceExt для просмотра всех процессов (включая скрытые) вполне достаточно.
карта памяти "Блокнота", отображенная отладчиком OllyDbg
Регионы, помеченные как "Priv" (сокращение от "private") принадлежат блокам динамической памяти, "map" (сокращение от "mapping") – проекциям файлов, созданных функциями CreateFileMapping/MapViewOfFile), "Imag" (сокращение от "imaging") – страничным имиджам исполняемых файлов или динамических библиотек.
В PE-TOOLS для той же цели необходимо выделить процесс и в контекстом меню выбрать "dump region", при этом на экране появится диалоговое окно с картой памяти — не такой подробное как у OllyDbg, но для нашей задачи вполне удовлетворительное.
исследование даты создания файлов при помощи FAR'а
Естественно, дата создания файла элементарно изменяется средствами win32-API и малвари при желании ничего не стоит замаскироваться. Однако, на NTFS-разделах каждый файл обладает множеством "невидимых" атрибутов, до которых нельзя дотянуться через API. В частности, атрибут 30h ($FILE_NAME) помимо стандартных времен создания/модификации/последнего обращения, хранит время последней модификации данной записи MFT (Master File Table – специального мастерфайла, содержащего информацию обо всех остальных объектах файловой системы). У "честных" файлов время создания и время последней модификации MFT всегда совпадает, а если это не так — мы имеем дело с подделкой. Еще существует атрибут 10h ($STANDARD_INFORMATION), так же хранящий информацию о времени создания/модификации/последнего доступа файла и времени последней модификации MFT, однако, в отличии, от атрибута 30h, здесь время последней модификации MFT автоматически обновляется всякий раз, когда файлу выделяется новая порция кластеров, а потому со временем его создания оно может и не совпадать.
Существует не так уж и много утилит, отображающих содержимое MFT в удобочитаемом виде. Одна из них — NtExplorer от Runtime Software. Грубо говоря, это Norton Disk Editor, но только под NTFS. К сожалению, NtExplorer не поддерживает ни плагинов, ни скриптов, поэтому, быстро вывести список файлов с поддельными датами создания не получается и каждый из них приходится перебирать "руками", что очень сильно напрягает, но… NTFS совсем несложная (по нынешним меркам) файловая система, а все ее основные структуры давным-давно реконструированы, документированы и выложены в Сеть: http://linux-ntfs.sourceforge.net. Создание программы, выполняющий автоматизированный поиск "поддельных" файлов у не займет много времени, тем более, что подробное описание NTFS можно найти в моей книге "la technique de la restitution des données". В общем, дорогу осилит идущий!
карта памяти "Блокнота", отображенная утилитой PE-TOOLS
Для дальнейший экспериментов нам понадобится программа, создающая пару потоков — "честным" и "нечестным" путем. Исходный код (с опущенной обработкой ошибок и других исключительных ситуаций) может выглядеть так:
#include <stdio.h>
#include <windows.h>
// код потока, который ничего не делает, а только мотает цикл
thread(){while(1);}
main()
{
void *p; // переменная многоцелевого назначения
// создаем "честный" поток
CreateThread(0,0,(void*)&thread,0x999,0,&p);
// создаем "нечестный" поток так, как это делает malware:
// выделяем блок памяти из кучи, копируем туда код потока
// и вызываем CreateThread
p = VirtualAlloc(0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(p,thread,0x1000);CreateThread(0,0,p,0x666,0,&p);
// ждем нажатия на ENTER
gets(&p);
}
Process Explorer от Марка
Что мы видим? Адреса двух потоков определены верно. Первый: va_thread.exe+0x1405, судя по адресу, представляет основной поток (адрес совпадает с точкой входа, что легко проверить в hiew'е). Второй: va_thread.exe+0x1000 — это "честно" созданный поток (что опять-таки проверяется по адресу в hiew'е), а вот третий – KERNEL32.DLL+0xB700 – это "нечестный" поток (а чем он еще может быть?!), только его стартовый адрес определен неправильно!
Призываем на помощь OllyDbg и пытаемся разобраться в ситуации самостоятельно, без всех этих прелестей автоматизации и прочих чудес технического прогресса. Подключившись к процессу va_thread.exe, в меню "view" выбираем пункт "thread" и… обнаруживаем не три (как ожидалось), а целых четыре потока!
Ident Entry Data block Last error Status Priority
050C 7943B700 7FFDB000 ERROR_SUCCESS Active 32 + 0
0558 00000000 7FFDC000 ERROR_SUCCESS Suspended 32 + 0
055C 00000000 7FFDE000 ERROR_SUCCESS Suspended 32 + 0
0578 00000000 7FFDD000 ERROR_SUCCESS Suspended 32 + 0
содержимое дна стека
На самом деле, праздновать победу еще рано. Умная малварь может нас легко обмануть. Самое простое — подменить истинный стартовый адрес так, чтобы он указывал внутрь страничного имиджа целевого процесса (но в этом случае он должен совпадать с началом какой-нибудь процедуры, иначе мы тут же разоблачим обман). Более умная малварь использует хитрый способ внедрения — находит в целевом процессе функцию по стандартному прологу PUSH EBP/MOV EBP, ESP
(55h/8Bh ECh), вставляет в ее начало jump на выделенный из кучи блок, где размещено ее тело, создает новый поток, начинающийся с jump, и тут же восстанавливает оригинальное содержимое хакнутой функции убирая jump и возвращая стандартный пролог. Еще остается вариант загрузить внутрь процесса динамическую библиотеку, принадлежащую малвари и запустить внутри нее новый поток.
Во всех этих случаях анализ стартового адреса не даст никакого результата и внедрение зловредного кода останется незамеченным и чтобы быть уверенным на все 100% необходимо трассировать каждый из потоков на предмет проверки его лояльности. Потоки, порожденные малварью, либо шпионят за клавиатурой, либо открывают backdoor, либо рассылают спам. Проблема в том, что потоков (легальных) очень много, а современная малварь пишется уже не на ассемблере, а черт знает на чем (DELPHI, Visual BASIC) и полный анализ требует уймы времени, однако, как говорилось выше, умная малварь — большая редкость и подделкой стартовых адресов потоков никто не занимается.
механизм реализации системных вызовов
Дескриптор, отвечающий за системные вызовы, указывает на System Service Table (Таблица Системных Вызовов), представляющую собой простой массив указателей на функции, которые _очень_ легко изменить (естественно, делать это нужно либо из режима ядра, либо с прикладного уровня, обратившись к псевдоустройству PhysicalMemory). Найти таблицу системных вызовов в памяти очень просто. "Скармливаем" NTOSKRNL.EXE функции LoadLibrary
и, используя возвращенный ей дескриптор, определяем адрес экспортируемой переменной KeServiceDescriptorTable через GetProcAddress (или разбираем таблицу экспорта вручную). Первое же двойное слово содержит указатель на SST, поэтому эффективный адрес требуемого системного сервиса по его "магическому" номеру определяется так: addr == *(DWORD *)(KeServiceDescriptorTable[0] + N*sizeof(DWORD)), где N – номер сервиса, а addr – его эффективный адрес.
Продемонстрируем эту технику на примере soft-ice:
:dd
:d KeServiceDescriptorTable
0008:8046AB80 804704D8 00000000 000000F8 804708BC ..G...........G.
:d 804704D8
0008:804704D8 804AB3BF 804AE86B 804BDEF3 8050B034 ..J.k.J...K.4.P.
0008:804704E8 804C11F4 80459214 8050C2FF 8050C33F ..L...E...P.?.P.
0008:804704F8 804B581C 80508874 8049860A 804FC7E2 .XK.t.P...I...O.
:u *(804704D8 + 97*4)
ntoskrnl!NtQuerySystemInformation
0023:804BF933 PUSH EBP
0023:804BF934 MOV EBP, ESP
0023:804BF936 PUSH FF
0023:804BF938 PUSH 804043A0
0023:804BF93D PUSH ntoskrnl!_except_handler3
поиск SST в файле NTOSKRNL.EXE по перекрестным ссылкам
Если лень восстанавливать SST вручную, можно воспользоваться бесплатной утилитой "Win2K/XP SDT Restore" от Tan Chew Keong, результат работы которой продемонстрирован ниже:
и результат ее работы на зараженной малварью машине
Пользуясь SDT Restore, следует иметь ввиду, что уже появились rootkit'ы, способные ее обходить. Во-первых, для поиска оригинальной SST, утилита SDT Restore использует простой, но ненадежный способ, обращаясь к KeServiceDescriptorTable[0], которую зловредная малварь может и подменить (см. http://hi-tech.nsys.by/35/), во-вторых, само восстановление SST происходит с прикладного уровня через псевдоустройство PhysicalMemory, отображаемое в память посредством native-API функции NtMapViewOfSection, легко перехватываемую как с прикладного, так и с ядреного уровней, после чего перехватчику остается проверить: не вызывается ли NtMapViewOfSection с дескриптором PhysicalMemory
и если да, то либо заблокировать доступ, либо имитировать восстановление, не производя его в действительности (см. http://www.rootkit.com/newsread.php?newsid=200).
Так же следует учитывать, что некоторые защиты "вешаются" на вектора прерываний, описанные в таблице IDT, и проверяют перехваченные сервисы, например, каждый тик таймера. В правильной IDT (просмотреть которую можно одноименной командой в soft-ice) все вектора указывают внутрь NTOSKRNL.EXE или HAL.DLL.
:IDT
Int Type Sel:Offset Attributes Symbol/Owner
IDTbase=80036400 Limit=07FF
0000 IntG32 0008:804625E6 DPL=0 P ntoskrnl!Kei386EoiHelper+0590
0001 IntG32 0008:80462736 DPL=3 P ntoskrnl!Kei386EoiHelper+06E0
0002 IntG32 0008:0000144E DPL=0 P
0003 IntG32 0008:80462A0E DPL=3 P ntoskrnl!Kei386EoiHelper+09B8
Восстановление SST
Для сокрытия своего присутствия в системе, малварь нередко внедряется в ядро системы и перехватывает один или несколько сервисов, например, функции NtQuerySystemInformation, про важность которой мы уже говорили. Ловить малварь на такой системе все равно, что бороться с ком. партией под ее руководством.
Дизассемблирование NTDDLL.DLL показывает, что большинство низкоуровневых функций реализованы как "переходники" к функциям ядра, интерфейс с которым осуществляется либо посредством прерывания INT2Eh (NT, W2K), либо машинной командой SYSENTER (XP и выше).
.text:77F95BBD public ZwQuerySystemInformation
.text:77F95BBD ZwQuerySystemInformation proc near
.text:77F95BBD arg_0 = byte ptr 4
.text:77F95BBD
.text:77F95BBD B8 97 00 00 00 mov eax, 97h ; NtQuerySystemInformation
.text:77F95BC2 8D 54 24 0 lea edx, [esp+arg_0]
.text:77F95BC6 CD 2E int 2Eh
.text:77F95BC8 C2 10 00 retn 10h
.text:77F95BC8 ZwQuerySystemInformation endp
Время тоже оставляет отпечатки
Чаще всего малварь копирует свою тушу в новый файл со случайным или фиксированным названием, реже— внедряется в уже существующие (что требует не только знания устройства PE-формата, но и определенных привилегий, в частности, из-под пользовательского аккаунта системные файлы просто так не заразишь). При этом подавляющее большинство malware-писателей забывают скорректировать дату/время создания файла, выдавая себя с головой.
Допустим, мы запустили файл сомнительного происхождения и хотим узнать – не натворил ли он чего в системе? Пуск à Найти à
Файлы и Паки à
Параметры Поиска à
Файлы созданные за xxx последних дней (в нашем случае за один). Все изменения, произошедшие за последние сутки в системе становятся видны как на ладони! Как вариант: в FAR'е устанавливаем режим сортировки по дате создания (<CTRL-F8>) и заходим во все "злачные" каталоги типа WINNT, System32 и т. д. Файлы, созданные последними, будут в самом верху. Прием простой, как паровой котел, но чрезвычайно эффективный!
>>> Врезка ссылки на программы, упомянутые в статье
q NtExplorer:
o http://www.runtime.org/gdbnt.zip;
q OllyDbg:
o http://www.ollydbg.de;
q Process Explorer:
o http://www.sysinternals.com/Utilities/ProcessExplorer.html;
q IceExt:
o http://stenri.pisem.net;
q IceDump:
o http://programmerstools.org/system/files?file=icedump6.026.zip;
q PE-TOOLS (base):
o http://www.wasm.ru/baixado.php?mode=tool&id=124;
q PE-TOOLS (updates):
o http://neox.iatp.by;
q eXtremeDumper:
o http://neox.iatp.by/eXtremeDumper.zip;
q SDT Restore:
o http://www.security.org.sg/code/sdtrestore.html;
была обычном делом. Количество исполняемых
Во времена MS-DOS ручная чистка компьютера — была обычном делом. Количество исполняемых файлов измерялось десятками, и существовало не так уж и много мест, пригодных для внедрения малвари (под малварью — от английского malware — здесь и далее по тексту подразумевается вредоносное программное обеспечение — вирусы, черви, шпионы и т. д.). С приходом Windows все изменилось. Из крохотного поселка операционная система превратилась в огромный, стремительно разрастающийся мегалополис, среди сотен тысяч файлов которого может спрятаться и слонопотам.
Обнаружить качественно спроектированную и грамотно заложенную закладку усилиями одного человека за разумное время — навряд ли возможно. Намного проще (да и быстрее) переустановить Windows с нуля. К счастью, качественная малварь — огромная редкость, практически не встречающая в живой природе и в основном приходится сталкиваться с пионерскими поделками, оставляющими после себя кучу следов и легко различимыми с помощью soft-ice и сопутствующих ему утилит.
Весь вопрос в том — как правильно ими пользоваться. Ну, установили мы soft-ice, нажали <CTRL-D>, увидели черный экран… Дальше-то что?! А вот дальше на сцене появился мыщъх и, плюхнувшись в кресло (предварительно подтолкнув под себя хвост), начинает делиться хакерскими секретами.
Вот два основных пути проникновения
Вот два основных пути проникновения малвари на компьютер— файлы, запускаемые самим пользователем и дырявое программное обеспечение (последнее преимущественно относится к IE и линейке NT). И если первое еще можно как-то предотвратить (не открывать никаких потенциально опасных вложений, полученных по почте; пользоваться приложениями только от проверенных поставщиков; не скачивать crack'и написанные непонятно кем и неизвестно для чего), то от дыр никуда не уйти. Даже если пересесть с IE на Lynx, останутся дефекты оси, коих в NT ну просто до фига и постоянно обнаруживаются все новые, ранее неизвестные. То есть, это _нам_ они неизвестные, а кому-то очень даже хорошо известные и эксплуатируемые.
Никто не может чувствовать себя в безопасности, если не будет регулярно проверять все закоулки системы своими руками, хвостом, ну и конечно, могучим soft-ice со всей его свитой.