Ну или, если говорить более общо, можно ли раз в N секунд проверять, что RWX-страницы приложения остались неизменны?
nagva27, Перехватить DllMain() одной из существующих либ и получать уведомления о создании новых потоков в процессе (DLL_THREAD_ATTACH). В обработчике проверять, какому модулю принадлежит точка входа нового потока.
Интересно, но насколько знаю, есть такие методы инжекта, при которых фактически не происходит присоединения нового модуля, а просто добавляются RWX-страницы, и в этом случае DLL_THREAD_ATTACH не произойдёт.
Но новый поток все равно же как-то создается? На него и будет уведомление. Но, разумеется, это не универсальный метод, который подойдет для любых способов инжекта.
Я так понимаю, поток может создаваться и самой программой, и тут отдельная задача понять, кто его создаёт и зачем. А нельзя просто задетектить изменение размера памяти, выделенной под код приложения? Или этот размер может и просто так меняться?
Ну, это тривиальная задача. Можно при старте собрать инфу по существующим модулям и проверять, принадлежит ли новый поток им (также перехватить LoadLibrary() и пополнять список "легитимных" модулей).
rmn, а как считаете, можно ли полагать, что обязательным следствием даже самого хитрого инжекта является изменение таблицы импорта программы?
Ну да, логично. А вот смотрите, я нашёл сэмпл защиты от сплайсинга: https://gist.github.com/HoShiMin/c78585dac9a65dab1d1d Я правильно понимаю, что в принципе это не только "защита от сплайсинга", но и в принципе этот код может отлавливать любые изменения RWX-pages?
Вижу, что не совсем так: код этот детектит и запрещает изменение только исполняемых страниц (что делает сплайсинг), а инжекты могут и не менять их. Но я думаю, можно оттуда просто взять хук virtualProtect, и если этот хук срабатывает, то скорее всего кто-то пытается влезть в нашу память, верно? Т.е. можно ли сказать, что любой инжект подразумевает вызов virtualProtect?
Понятно.. тогда попробую сузить задачу. Я не хочу, чтобы другое приложение hook-ало winapi-функции, которые вызывает моя программа. Происходить это может, как я понимаю, только с помощью инжекта в мою программу и установки хука (экзотические сложные способы не берём). Могу ли я просто проверять длину hook-chain, чтобы понять, что перехват начал происходить?
nagva27, Смотря как происходит инжект. Обычно либа загружается из памяти, в обход штатных механизмов загрузки из секций/диска. > можно ли раз в N секунд проверять, что RWX-страницы приложения остались неизменны? Система реализует монитор рабочего набора - working set watch. Любая подгрузка или аллокация памяти логгируется и вы в любой момент можите запросить этот лог.
> просто добавляются RWX-страницы, и в этом случае DLL_THREAD_ATTACH не произойдёт. По нормальному создаётся отображение RW-RX. Это два раза спроецированная секция, одна проекция пишется, другая исполняется. > Я правильно понимаю, что в принципе это не только "защита от сплайсинга", Нет там никакого принципа, обычный сервисный фильтр. Если хотите залочить память от изменений - сделайте её проекцией RX, тогда открыть доступ на запись в эту память из юм невозможно, без смены типа региона памяти.
nagva27, > Могу ли я просто проверять длину hook-chain, чтобы понять, что перехват начал происходить? Это бессмысленно всё. Сейчас эти методы хуков deprecated. Ваше приложение может быть запущено под визором и никаких изменений в памяти не будет, хотя каждая инструкция вашего приложения контролируется.
nagva27, Вот пример как находить изменения в рабочем наборе. Данный код используется в локальном визоре для быстрого скана памяти - изменения рабочего набора отслеживаются, таким образом выполняется быстрая проверка памяти перед обращением к ней.
Indy_, несколько вопросов: -не знаю, что такое визор. По какому слову погуглить? -я хочу скомпилировать этот .asm в .dll, чтобы инжектить её в программу, которую хочу "защищать" от инжектов (да, поручик знает толк)). Исходников "защищаемой" проги у меня соответственно нет. Эта мысль кажется вам бредовой или норм?
nagva27, Визор это надстройка над кодом, цикл эмуляции/исполнения, каждой инструкции и при этом невозможен выход из этого цикла. Обычно используется термин взятие", так как код взят под слой визора. При этом приложение никак не изменяется. Вы не обнаружите в памяти изменения или хуки", между тем доступна совершенно любая сервисная обработка. Фактически это руткит, который исполняет ваш код. Визоры разделяются на виды - супер, гипер и локал, Последний может быть интегрирован в ваш код. > -я хочу скомпилировать этот .asm в .dll, чтобы инжектить её в программу, которую хочу "защищать" от инжектов Я не дал готовое решение. Его нет, просто привёл пример монитора WS. Это очень обширная тема - защита, очень обширная, нужен весьма большой масштаб знаний что бы понимать это всё. Зачем вам это ?