Max Так как у меня все подряд (в том числе и секции данных) было PAGE_NOACCESS, то туда наверняка указывал первый и единственный параметр функции Я же говорю - пробовал (на win2K), не работает. P.S. Кстати, умные люди советовали под NT вместо PAGE_NOACCESS использовать PAGE_GUARD. Но к тому времени, как я увидел этот совет, желание писать свой монитор у меня уже пропало
я вот тут решил заставить систему обращаться к странице с PAGE_NOACCESS... ну, думаю, щас поставлю PAGE_NOACCESS на fs:[0] и вызову исключение... fs:[0] есть 0x7FFDE000. так вот вызов VirtualProtect на этот адрес с флагами PAGE_NOACCESS или PAGE_GUARD система не пропускает. в тоже время PAGE_EXECUTE_READWRITE проходит. умная зараза
вообщем тут по синьке я немного поэкспериментировал, и вот что получилось... 1. устанавливаем dr0 на fs:[0] (по чтению/записи) 2. вызываем исключение. по идее, должно произойти обращение к fs:[0] системой, с целью определения цепочки обработчиков... так вот, получается, что процесс-отладчик сначала получает уведомление о эксепшене, который я вызвал... ...а потом идет поток эксепшенов (~1200 штук) внутри ZwSetIoCompletion, после чего отлаживаемый процесс нестандартно сносится с уведомлением EXIT_PROCESS_DEBUG_EVENT. sorry, на большее меня пока не хватило.... з.ы. ZwSetIoCompletion пахнет уже железнячеством, в котором я не силен
Добрый день. Одна проблема разрешилась, но другая - ни в какую. Если вкратце - я поступаю следующим образом: Вылавливаю в секции кода все инструкции типа: 1) Код (Text): mov dword ptr fs:[00000000h],esp - регистрация нового фрейма; 2) Код (Text): mov dword ptr fs:[00000000h],ecx - удаление последнего фрейма. Вместо этих вещей я ставлю F1,mov dword ptr fs:[0000h],eXX, т.е. длина кода не изменяется. В своем же обработчике, если это исключение не EXCEPTION_ACCESS_VIOLATION, а EXCEPTION_SINGLE_STEP я проверяю, что это - регистрации или удаление и делаю так, чтобы в регистрируемом фрейме вместо оригинального обработчика появился мой, а если происходит удаление, то, чтобы в оставшемся последним обработчике вместо оригинального появился мой. Все работает ну "ура"... Поначалу. Смысл заключается в том, что оригинальный исходник очень любит всякие try/catch и иже с ними... Прога проходит несколько исключений связанных, с этой шнягой (генерится сишное исключение с кодом E..., я, естественно, передаю управление оригинальному обработчику), но на n-ном этапе после обработки такого исключения прога тихо идет на завершение. Передаю управление оригинальному через jmp с восстановлением всех регистров и прочей муры. Такой трюк срабатывает с обычными исключениями, но вот с сишными - плохо. В чем может быть проблема? Из-за сишных наворотов над SEH? И как ее можно попытаться разрешить?
Проблема, скорее всего, не в сишных обработчиках, а в том, что некоторые API-функции ставят свой обработчик. Если ты отлавливаешь "инструкции типа" только в секции кода exe-файла, то любая DLL-ка может тебе изрядно подпортить здоровье. Не говоря уж о запакованных exe-файлах. Как решать - все-таки попробуй устанавливать break on write.
RobinFood, фича в том, что, как для тестирования и простоты я убираю всю PAGE_NOACCESS при запуске проги. Остаются только феньки с F1 в коде проги. На всем, что рантаймы не юзает, хотя и возится с сехами работает отлично. Поведение упакованной падающей проги до последней генерации исключения, после которого она идет на завершение ничем не отличается от поведения неупакованной.
обработчики всяких try/catch вполне могут находиться не в коде проги, а в какой-нибудь DLL-ке, например, msvcrt.dll. В таком случае может получиться, что ты "поймаешь" установку обработчика, но "прозеваешь" его снятие. Далее, ты смотрел "функции", установки/снятия обработчика? Ведь не исключено, что для установки обработчика вместо mov dword ptr fs:[00000000h],esp использовано "агромадное" извращение наподобие xor eax,eax mov dword ptr fs:[eax],0 а для снятия вместо mov dword ptr fs:[00000000h],ecx - извращение поменьше, вроде pop dword ptr fs:[0] IMHO, слишком много разных нюансов возможно, чтобы твой способ с F1 можно было запускать в промышленное производство
RobinFood, я подробно разобрал все проги... Там в длл-ки все переходы осуществляются так в плохом случае: Код (Text): mov eax,OFFSET_STRUCTUREx jmp msvcrt!__CxxFrameHandler с остальными же обработчиками все проще - они внутри кода проги. Но, похоже, решилась у меня уже проблема. Я просто указатель на __CxxFrameHandler перенаправляю. По поводу извратной установки сеха все проверил, вроде все чисто. ЗЫ Теперь я понимаю, почему армадилловцы пошли таким громоздким путем=)
> Теперь я понимаю, почему армадилловцы пошли таким громоздким путем=) Не громоздким а единственно верным
MoonShiner ты наверное разобрался а то игде болше ничего нет инфо про CxxFrameHandler. что на входе и выходе и зачем в eax эта фигня и сколько она длжна занимать байт ?
Скажите а кто как смотрит на идею, которую коротко можно назвать "понатыкать везде хеши" Собственно перед тем как что либо шифровать, запускаем прогу в тестовом режиме, расставив Guard'ы так как они будут в конечной версии. В этом режиме мы будем только смотреть с каких адресов происходит обращение, и брать хеши к примеру с адреса вызова +- 40 байт. После такого тестового запуска у нас будут хеши всех мест откуда было обращение к Guard'ам. В конечной версии проги мы шифруем участки именно тем хешем, который будет взят с места обращения. Что это дает? 1. Мы нигде не храним ключи. 2. Мы контролируем места которые обращаются к нашей проге (я имею ввиду загрузчик который запустит прогу), причем коварный контроль получается , т.к. если потом исследователь будет считывать защищенную область памяти наша прога ничего ему не расшифрует т.к. ей попадут неверные хеши. 3. Собственно за счет пункта 2, вываливаются еще и бряки установленные как 0xCC в вызывающий код. А DR можно перед этим забить как следует Ну вобщем то и вся идея.