• XSS.stack #1 – первый литературный журнал от юзеров форума

Оцените мой EDR(PoC)

nexslin

CD-диск
Пользователь
Регистрация
05.01.2026
Сообщения
19
Реакции
5
Относительно недавно перешел с ассемблера на Си, изучил базу, подумал что нужно закрепить знания, решил написать собственный PoC-EDR на уровне юзермода.
Написал буквально за день, не судите строго, хукнул ток те функции, которые +- успел.
Корреляционного движка пока-что нет, но я делал IPC-туннель, которая передает все данные в мой инжектор, который непосредственно инжектит edr.dll в процессы.

1) Хук на подозрительные функции, решил поставить на: NtAllocateVirtualMemory, RegSetValueExA, ShellExecuteA, HookRegCreateKeyExA, GetThreadContext, SetThreadContext, AddVectoredExceptionHandler(veh-обработчик)
2) HWDB, аппаратные точки останова(конкретно, регистры dr0-dr3-dr7) которые хранят в себе адрес функций, решил воспользоваться HWDB для детекта NtCreateThreadEx. Еслт процесс не равен текущему И не равен псевдо-хэндлу, - детект.
Из ctx достаю регистр r9 который в структуре равен ProcessHandle:
1768678315146.png

3) Поставил хуки на GetThreadContext/SetThreadContext. Чтобы малварь не могла прочитать аппаратные регистры процессора и понять, что там не нули))) Поставил хук и возвращаю малвари нули, чтобы она думала что регистры чистые:
1768678631430.png

После чего, моментально, с точки зрения создание малвари, малварь должна сразу же вызвать SetThreadContext, чтобы задать значения, тупо на всякий случай задать нули, там ее ловит мой хук и мягко-говоря посылает лесом:
1768678681018.png

Проверяю, пытается ли малварь поменять состояние аппаратных регистров, если да - стопаю процесс. Если все норм - вызываю оригинальную функцию.
4) Также поставил хук на veh-обработчик, чтобы малварь не пытался создать поверх моего обработчика свой, поставить свой в приоритет и обойти HWDB детект:
1768678771865.png

5) И непосредственно внутри своего обработчика реализовал CaptureStackBackTrace с целью понять, вызывается ли код из .text секции или же из кучи, если из кучи - детект т.к оттуда чаще всего вызываются заинжектированные шеллкоды:
1768678843653.png


Жду оценку. Критику и чего можно еще добавить.

Также работоспособность свой edr проверял на своем дроппере. Написан он на ассемблере FASM, мне лень было добавлять весь функционал который детектит edr, я просто сделал UAC-bypass через fodhelper который благополучно детектится моей edr-кой:
Другие функции тоже детектит
1768678981963.png
 

Вложения

  • 1768678721283.png
    1768678721283.png
    17.4 КБ · Просмотры: 16
Последнее редактирование:
Если делать нечего, то хукай только функции из ntdll что бы наверняка (и проверяй в цикле хук сисколов) и плюс код будет компактней и меньше.
 
Если делать нечего, то хукай только функции из ntdll что бы наверняка (и проверяй в цикле хук сисколов) и плюс код будет компактней и меньше.
Сделаю

Касаемо nt
Там же библиотека есть по типу Hells Gate
Поэтому хочу брейкпоинт поставить непосредственно на сам сискол вызов, помочь от прямого вызова сискола должно по сути
 
Последнее редактирование:
Относительно недавно перешел с ассемблера на Си, изучил базу, подумал что нужно закрепить знания, решил написать собственный PoC-EDR на уровне юзермода.
Написал буквально за день, не судите строго, хукнул ток те функции, которые +- успел.
Корреляционного движка пока-что нет, но я делал IPC-туннель, которая передает все данные в мой инжектор, который непосредственно инжектит edr.dll в процессы.

1) Хук на подозрительные функции, решил поставить на: NtAllocateVirtualMemory, RegSetValueExA, ShellExecuteA, HookRegCreateKeyExA, GetThreadContext, SetThreadContext, AddVectoredExceptionHandler(veh-обработчик)
2) HWDB, аппаратные точки останова(конкретно, регистры dr0-dr3-dr7) которые хранят в себе адрес функций, решил воспользоваться HWDB для детекта NtCreateThreadEx. Еслт процесс не равен текущему И не равен псевдо-хэндлу, - детект.
Из ctx достаю регистр r9 который в структуре равен ProcessHandle:
Посмотреть вложение 112139
3) Поставил хуки на GetThreadContext/SetThreadContext. Чтобы малварь не могла прочитать аппаратные регистры процессора и понять, что там не нули))) Поставил хук и возвращаю малвари нули, чтобы она думала что регистры чистые:
Посмотреть вложение 112140
После чего, моментально, с точки зрения создание малвари, малварь должна сразу же вызвать SetThreadContext, чтобы задать значения, тупо на всякий случай задать нули, там ее ловит мой хук и мягко-говоря посылает лесом:
Посмотреть вложение 112141
Проверяю, пытается ли малварь поменять состояние аппаратных регистров, если да - стопаю процесс. Если все норм - вызываю оригинальную функцию.
4) Также поставил хук на veh-обработчик, чтобы малварь не пытался создать поверх моего обработчика свой, поставить свой в приоритет и обойти HWDB детект:
Посмотреть вложение 112143
5) И непосредственно внутри своего обработчика реализовал CaptureStackBackTrace с целью понять, вызывается ли код из .text секции или же из кучи, если из кучи - детект т.к оттуда чаще всего вызываются заинжектированные шеллкоды:
Посмотреть вложение 112144

Жду оценку. Критику и чего можно еще добавить.

Также работоспособность свой edr проверял на своем дроппере. Написан он на ассемблере FASM, мне лень было добавлять весь функционал который детектит edr, я просто сделал UAC-bypass через fodhelper который благополучно детектится моей edr-кой:
Другие функции тоже детектит
Посмотреть вложение 112145
В последние несколько лет все EDR/XDR-системы перешли в сторону ядра. Например, Falcon практически не работает в пользовательском режиме и выполняет проверки в основном с использованием ядра, из-за чего обход (bypass) либо практически невозможен, либо как минимум не является простым.
Если ты хочешь серьёзно развиваться в этом направлении, лучше двигаться именно в эту сторону.



 
Сделаю
Просто малварь может вин апишные функции тянуть, их тоже лучше контролировать

Касаемо nt
Там же библиотека есть по типу Hells Gate
Поэтому хочу брейкпоинт поставить непосредственно на сам сискол вызов, помочь от прямого вызова сискола должно по сути

Будет она тянуть винапи, и что? Тот же GetThreadContext это просто обертка над NtGetContextThread. Хукнешь NtGetContextThread, GetThreadContext буудет автоматически отлавливаться. Брейкпоинты никак не помогут, от прямых сисколов, для этого можно в сторону instrumentation callback посмотреть.
 
1768741104087.png

Немного усовершенствовал EDR.
Добавил:
1) Проверку нового потока, когда малварь создает новый поток с целью реализации всех вредоносных действий, она наступает на те же грабли, на которые наступила бы в основном потоке.
Реализовал проверку NtAllocateVirtualMemory/NtCreateThreadEx на уровне аппаратных регистров как в основном потоке, только уже в дочерних.
В коде, сохраняю хэндл нового потока в tls указатель *g_pThreadHandleAddr который объявлен с __declspec(thread) чтобы система выделяла блок памяти под него. После чего создаю условную конструкцию, где проверяю, если хэндл не равен нулю, то-есть, новый поток есть. Далее создаю обнуленную структуру ThreadCtxNew, запихиваю в эту структуру аппаратные регистры, начиная от dr0 заканчивая dr7 и через GetThreadContext, принудительно перезаписываю регистры dr0 и dr1, чтобы гарантировать начилие контроля.
1768741582756.png

После чего функцией SetThreadContext записываю в структуру новые данные про регистры.

Вроде норм, мои HWDB хуки в целом будет трудно обойти, т.к самые известные дыры обхода закрыты.
 
Последнее редактирование:
Будет она тянуть винапи, и что? Тот же GetThreadContext это просто обертка над NtGetContextThread. Хукнешь NtGetContextThread, GetThreadContext буудет автоматически отлавливаться. Брейкпоинты никак не помогут, от прямых сисколов, для этого можно в сторону instrumentation callback посмотреть.
Гляну, спасибо.
Касаемо брейкпоинтов, общался вчера с одним типом в дс, он тоже самое говорил.
 
В последние несколько лет все EDR/XDR-системы перешли в сторону ядра. Например, Falcon практически не работает в пользовательском режиме и выполняет проверки в основном с использованием ядра, из-за чего обход (bypass) либо практически невозможен, либо как минимум не является простым.
Если ты хочешь серьёзно развиваться в этом направлении, лучше двигаться именно в эту сторону.



Понятное дело на уровне ядра работают, мне же нужно получить базу на уровне юзермода какую-никакую, чтобы хоть как-то быть подготовлен к кернелу
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх