![]() |
Шпионское ПО активно использует различные методы внедрения своих библиотек, чтобы скрыться в легитимных процессах системы. После внедрения удалить такую DLL довольно проблематично, если только не завершить процесс целиком. Однако имеется нюанс, при помощи которого всё-таки можно попытаться "вырезать" вредоносную либу из памяти инфицированного процесса, о чём и пойдёт речь в данной статье. Всё сводится к тому, чтобы найти и сбросить счётчик загрузок DLL в памяти пациента. Первую часть, где обсуждался наоборот инжект, можно найти здесь.
Оглавление: 1. Вводная часть 2. Поиск счётчика LoadCount в структурах РЕВ 3. Сбор информации об активных процессах 4. Несколько слов об интерфейсе программы 5. Заключение 1. Вводная часть - назначение счётчиков Ресурсы системы не безграничны и если не вести над ними контроль, ситуация может уйти в разнос. Катастрофу предотвращают всего несколько счётчиков "Counter", которые можно разделить на 3 основных типа: HandleCount (ведёт учёт открытых дескрипторов), PointerCount (счётчик ссылок на объект), и LoadCount (счётчик загрузок DLL). Эта троица позволяет отслеживать, кто использует объект ядра, сколько ресурсов занято, и когда их можно безопасно освободить. При этом первые два счётчика лежат в компетенции системного менеджера объектов, а третьим LoadCount управляет уже загрузчик образов исполняемых файлов. Тема настолько мутная, что проще объяснить её простым языком - вот байка... 1. HandleCount - это количество гостей в отеле (дескрипторов), которые держат ключ от номера (объекта). Пока хотя бы один гость не сдаст ключ на ресепшн, горничная (система) не может зайти убрать номер. Даже если гость уже выехал, но забыл ключ в кармане (не вызвал CloseHandle) - номер считается занятым. Типичная утечка памяти - это когда гость ушёл через окно, а ключ так и висит на доске ресепшна. 2. PointerCount - этот счётчик считает не только гостей с ключами, но и всех, кто просто посмотрел в сторону номера: горничную, сантехника, полицейского, случайно заглянувшую кошку. Когда счётчик обнуляется - объект действительно мёртв. Другими словами, если HandleCount - это количество рук держащих объект, то PointerCount - количество глаз, которые смотрят на него. 3. LoadCount - работает по принципу "тёщи в гостях", и напрямую зависит от баланса вызовов Код:
LoadLibrary() = FreeLibrary()Код:
LoadLibrary()Код:
FreeLibrary()Таким образом: HandleCount - сколько людей держат дверь, PointerCount - сколько камер следят за дверью, LoadCount - сколько раз вы позвали гостя, но забыли выпроводить. 1.1. Менеджер объектов Процессы и потоки относятся к объектам ядра, и соответственно создаются в его недрах. Cчётчиками Handle и Pointer оперирует системный Object-Manager, который реализован как набор функций из Ntoskrnl.exe с префиксами Ob_xx. Например Код:
ObpIncrementHandleCount()Код:
ObpDecrementHandleCount()Код:
ObReferenceObjectEx()Код:
ObDeferenceObject()К примеру если драйвер ядра хочет создать список всех активных процессов системы, он в цикле обходит все структуры EPROCESS, внутри которой имеется ссылка LIST_ENTRY на сл.структуру в цепочке. Но может получиться так, что пока драйвер приступит к чтению, ничего не подозревающий юзер закроет приложение снаружи и тогда неминуем BSOD. Поэтому перед чтением драйвер увеличивает счётчик PointerCount на 1 вызовом Код:
ObReferenceObject()Код:
ObDeferenceObject()Чтобы было немного наглядней, можно запросить инфу о любом процессе в отладчике WinDbg - пусть это будет калькулятор. Код: Код:
0: kd> !process 0 0 calc.exeКстати начиная с Win8 счётчик LoadCount сменил своё место жительства - в хвост структуры LDR_DATA_TABLE_ENTRY были добавлены новые поля, и счётчик теперь можно найти в доп.структуре LDR_DDAG_NODE. Однако хоть он и переехал, но до сих пор действительная старая прописка осталась, только на ней стоит штамп "Obsolete" (устарело). Код: Код:
struct LDR_DATA_TABLE_ENTRY_W10 ;//<--- sizeof 0x120 bytesТаким образом, если мы хотим выгрузить вредоносную DLL из памяти произвольного процесса, нужно: 1. Найти и прочитать его структуру РЕВ, 2. Используя РЕВ_LDR_DATA, cоздать список загруженных в процесс DLL, 3. Прочитать значение счётчика LoadCount каждой из найденных библиотек, 4. Определить, вредоносная она или нет (можно проверить путь), 5. Если да, используя счётчик в качестве цикла, вызывать Код:
FreeLibrary()6. Как только цикл закончится, загрузчик образов сам отправит либу в топку. На словах всё кажется страшно, а на деле выходит элементарно. Главное здесь найти адрес структуры РЕВ в удалённом процессе. Если в своём достаточно прочитать регистр Код:
FS/GSВ частности Код:
NtQueryInformationProcess()C-подобный: Код:
WINAPIДля перечисления всех активных процессов, Win предлагает несколько своих API, например: Код:
Process32First/Next()Код:
EnumProcesses()Код:
NtQuerySystemInformation()C-подобный: Код:
;Код:
OpenProcess()Код:
ReadProcessMemory()4. Несколько слов об интерфейсе Всё это дело я запихал в форточку, под катом которой работает движок. Разбитый на 5 столбцов элемент "ListView" как нельзя лучше подходит для сброса инфы, но некоторые нюансы хотелось-бы прояснить. Значит список всех активных процессов лежит в раскрывающемся "ComboBox", а при выборе строки в нём, заполняется таблица "ListView" с именами модулей. В самой таблице можно выбрать уже библиотеку, и если в столбце "Счётчик" найдём значение не Код:
0xFFFFЦитата:
Код:
GetFileVersionInfo()Код:
VerQueryValue()Чтобы было понятно о чём речь, вот несколько разных скринов. Как видим, с правами админа и привилегией SeDebug, можно собрать сведения и с процессов в закрытой сессии нуль. https://forum.antichat.xyz/attachmen...2b676ced8b.png Проводник системы - явный чемпион по кол-ву модулей в своей тушке https://forum.antichat.xyz/attachmen...0a40a1bd05.png Счётчик LoadCount может иметь исполинские значения https://forum.antichat.xyz/attachmen...7d0318774d.png 5. Заключение Биологические вирусы появились в результате жёсткой борьбы за существование. Чтобы не добывать пропитание самим, они научились паразитировать на других существах, но со временем медленно притирались друг к другу, образуя различные формы симбиоза. К примеру каждый из нас носит в себе кишечную палочку, можно даже сказать кишит ею, и ничего.. живём припеваючи. Внедрение DLL внешне похоже на паразитирование, но это не так. Когда народ обменивался файлами, таская под мышками дискеты схема работала. Однако с появлением Инета ситуация в корень изменилась - теперь все перешли на централизованную раздачу с официальных серверов по типу общепита, и необходимость паразитировать на других программах отпала сама-собой. Сейчас инжект носит лишь характер маскировки для сокрытия факта своего присутствия в системе - пробравшись на чужую территорию он просто ждёт своего часа, а о захвате ресурсов речь вообще не идёт. С другой стороны кибернетический мир меняется быстро, и мы не можем предугадать, что будет завтра. В скрепку кладу инклуд "ntdll.inc" с описанием структур, исходник программы для сборки ассемблером FASM, а так-же готовый исполняемый файл для тестов. Всем удачи, пока! |
| Время: 06:51 |