Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
| Помогли мы вам |
Анхукинг позволяет снять хук, который был установлен средством защиты. Определить наличие хука несложно. Вот наглядный пример того, как он может выглядеть.
Здесь EDR поставил хук на NtAllocateVirtualMemory(. Эта функция будет последней в User Mode, она вызывается лишь для инициализации системного вызова и выделения памяти путем обращения к ядру. В стоковой конфигурации, когда хука нет, никаких безусловных jmp-переходов быть не должно. Тут мы видим иную ситуацию: переход как раз таки есть, поток управления отдается непонятно кому и непонятно куда. Поэтому нам как атакующим, да и просто чтобы уклониться от обнаружения, нужна операция анхукинга, которая снимет этот хук, и, как следствие, средство защиты потеряет контроль над потоком выполнения программы.
Отмечу лишь, что подобный способ обхода хуков — один из множества. Можно, например, совершать Direct- и Indirect-сисколы, но стоит помнить, что получится обойти только хуки, которые стоят в User Mode. Если средство защиты применяет хуки Kernel Mode (например, SSDT Hooking), то подобные методы окажутся бесполезны. На будущее: SSDT — это специальная таблица, благодаря которой сопоставляются сискол и действие ядра Windows. Есть, конечно, Kernel Patch Protection, который мешает устанавливать подобные хуки, но это уже совсем другая история.
В статье я рассмотрю наиболее популярные способы снятия хуков, от простого к сложному.
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Этот метод можно считать одним из самых простых. Он основан на том, что библиотека ntdll.dll подгружается в память так же, как находится на диске. Причем хуки установлены непосредственно в памяти, на диске образ девственно чист. Поэтому мы должны будем лишь считать библиотеку с диска, достать из нее PE-секцию . (в ней находится код), а после перезаписать секцию . хукнутой библиотеки секцией, считанной с диска.
Мы будем использовать функции ReadFile( и MapViewOfFile(, и EDR может отслеживать их, поэтому есть риск, что наша ntdll., загруженная с диска, будет изменена при попытке подгрузить ее содержимое в программу. Поэтому придется использовать иной способ снятия хука, например тащить ntdll.dll с некоего удаленного сервера. Этот алгоритм реализуем позже. За идею большое спасибо Ральфу.
Итак, сначала нужно считать содержимое библиотеки ntdll.dll. Начнем со стандартной функции ReadFile(. По умолчанию ntdll.dll лежит в системной папке WindowsSystem32. Предлагаю создать функцию, которая будет возвращать буфер с содержимым ntdll.dll.
BOOL ReadNtdllFromDisk(OUT PVOID* ppNtdllBuf) { CHAR cWinPath[MAX_PATH / 2] = { 0 }; CHAR cNtdllPath[MAX_PATH] = { 0 }; HANDLE hFile = NULL; DWORD dwNumberOfBytesRead = NULL, dwFileLen = NULL; PVOID pNtdllBuffer = NULL; if (GetWindowsDirectoryA(cWinPath, sizeof(cWinPath)) == 0) {
printf("[!] GetWindowsDirectoryA Failed With Error : %d n", GetLastError());
goto EndOfFunc; } sprintf_s(cNtdllPath, sizeof(cNtdllPath), "%sSystem32%s", cWinPath, NTDLL); hFile = CreateFileA(cNtdllPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) {
printf("[!] CreateFileA Failed With Error : %d n", GetLastError());
goto EndOfFunc; } dwFileLen = GetFileSize(hFile, NULL); pNtdllBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileLen); if (!ReadFile(hFile, pNtdllBuffer, dwFileLen, &dwNumberOfBytesRead, NULL) || dwFileLen != dwNumberOfBytesRead) {
printf("[!] ReadFile Failed With Error : %d n", GetLastError());
printf("[i] Read %d of %d Bytes n", dwNumberOfBytesRead, dwFileLen);
goto EndOfFunc; } *ppNtdllBuf = pNtdllBuffer;EndOfFunc: if (hFile)
CloseHandle(hFile); if (*ppNtdllBuf == NULL)
return FALSE; else
return TRUE;}Остается проверить, что наш код верно работает. Если ты пишешь в Visual Studio, то открывай пункт «Отладка → Параметры» и ставь две галочки, чтобы можно было видеть содержимое памяти.
|
|
|

