Не, по-моему гораздо более напряжный метод чем через драйвер. Драйвер выполняется в крнтексте потока, и это многое упрощает. А так ну внедрил ты dll, поймал исключение - дальше надо узнавать от какого потока ты его получил, потому что для каждого потока свои xmm регстры и т.д. Нашёл ZwGetThreadContext и NtGetThreadContext. Вопрос - на каком IRQL их можно использовать (т.е. можно ли вызывать из обработчика исключения).
cppasm Не вижу разницы - хоть драйвер и работает в контексте текущего потока, тебе все равно надо хранить в памяти отдельный набор регистров для каждого потока в котором работаешь. Разница только в ring0/ring3. Просто, понимаешь, вариант с CALL всегда будет быстрее чем ловить каждый раз exception и обрабатывать его. Оно ж отжирает кучу тактов проца. Кстати, да, а какой нить DosEmu не содержит уже готового эмулятора?
Bochs эмулирует SSE, но он не динамический эмулятор. Т.е. эмулирует тупо весь код - это очень медленно. Разница в том, что так я ничего не проверяя буду записывать/читать виртуальные xmm регистры из контекста потока и всё. А так мне надо будет проверять в каком потоке произошло исключение, и сохранять регистры в зависимости от текущего потока в ту или иную область памяти. Хотя можно точно так же в контекст писать... В общем за исключением того что надо узнать в каком потоке произошло исключение - разница не большая. Просто ещё dll инжектить каждому процессу для которого это надо будет, а так один драйвер на всех
и там только один разница в том, где будет идти обработка теоретически твой вариант будет как минимум не быстрее
Каким таким образом? Он же в r0 ловит exception, его обрабатывает (эмулируя инструкцию) и меняя EIP возвращает управление. Или я чего то не понял? Тут тоже самое, только в r3 но с заменой опкода sse на CALL <наш обработчик>. В смысле первое попадание на SSE код даст exception, но потом exception'ов в данном месте уже не будет. Будем спорить что CALL быстрее exception или даже обычного r3->r0->r3 перехода? Кстати, рулить доступ к памяти из r3 для SSE инструкций проще чем из r0. Один из плюсов, так сказать. Я все к чему - если там не убер хацкерская программа и от себя crc не считает, r3 будет шустрее. Хотя да, возни с inject больше.
Проблема только в том - что это практически ОЧЕНЬ трудно реализуемо. Как например заменить на call команду xorps xmm0,xmm0 (3 байта). call туда просто не влезет. подскажите пожалуйста где есть более-менее детальное описание ZwGetContextThread/NtGetContextThread.
cppasm Угу, я писал что не всегда получится заменить на call. В обычном случае, без замены, будут ловиться exception'ы. Уже в exception будет идти эмуляция. Если можно заменить на CALL, заменяется на CALL и генерится stub который вызывает конкретную функцию эмуляции для конкретного опкода. При правильном проектировании это можно совместить, в плане общий эмулятор и разные точки входа (через exception или через stub). Вобщем, это просто мои 5 копеек. Я бы делал такое в r3 и всего то. Вроде подход называется динамической трансляцией.
Ну у меня тоже мысли есть в R3 сделать. Вопрос как именно. Можно VEH - но это WinXP и выше. А SEH насколько я понял надо для каждого потока устанавливать (если нет - поправьте). Т.е. надо ставить хук на CreateThread или что-то такое. Не охота... Наверное буду всё-таки через VEH делать. А как по-проще заставить виндовый загрузчик загрузить при запуске процесса мою dll (желательно до остальных). Думаю скинуть dll в папку с приложением и добавить в импорт - или так не пойдёт?
Мне не надо так радикально С загрузкой dll вроди разобрался - добавил в импорт. Теперь главное чтобы dll которые подгружаются раньше в своей DllMain не пользовали SSE.
Хукай KiUserExceptionDispatcher. Оно NT-only, но глобальное - 100% получишь exception до любого программного кода.
Сделал пока с AddVectoredExceptionHandler. Вопрос - чем можно заменить VEH чтобы работало под Win2k? Есть мысли сделать через SEH, но поскольку установка идёт в DllMain - в стеке фрейм создавать мне не подходит. Вопрос: 1. можно ли создать SEH фрэйм в куче? 2. SEH для каждого потока отдельно ставить надо? 3. VEH вроди для процесса ставиться и ловит исключения всех потоков, или нет?
В XP SP2 (вроде) нельзя - софтварный DEP рулит Внутрипоточный SEH ес-но. Для всего приложения см. SetUnhandledExceptionFilter
О, SetUnhandledExceptionFilter как раз то что надо. Теперь конкретный вопрос (вроди уже последний). Вот код либы: Код (Text): BOOL WINAPI DllMain(HANDLE hinstDLL,DWORD dwReason,LPVOID lpvReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: MessageBox(0,"DLL: PROCESS_ATTACH","Msg",MB_OK | MB_ICONINFORMATION); BackupHandler=SetUnhandledExceptionFilter(ExceptionHandler); break; case DLL_THREAD_ATTACH: MessageBox(0,"DLL: THREAD_ATTACH","Msg",MB_OK | MB_ICONINFORMATION); break; case DLL_THREAD_DETACH: MessageBox(0,"DLL: THREAD_DETACH","Msg",MB_OK | MB_ICONINFORMATION); break; case DLL_PROCESS_DETACH: MessageBox(0,"DLL: PROCESS_DETACH","Msg",MB_OK | MB_ICONINFORMATION); SetUnhandledExceptionFilter(BackupHandler); break; default: MessageBox(0,"DLL: Unknown reason","Msg",MB_OK | MB_ICONINFORMATION); } return TRUE; } Добавил её в импорт процесса, запускаю - получаю: DLL: PROCESS_ATTACH DLL: THREAD_ATTACH DLL: THREAD_ATTACH DLL: THREAD_ATTACH DLL: PROCESS_DETACH Вопрос - почему несоответствие ATTACH/DETACH? THREAD_DETACH вызывается только при завершении потока если процесс продолжает работать? Т.е. то что выше было получено при завершении всего процесса. И при создании основного потока процесса не приходит THREAD_ATTACH - это нормально?