Для профайлинга вызова API хочу сделать патч на KeFastSystemCall. Подумаль что самый простой способ - поменять адрес по которому находится KeFastSystemCall (7FFE0300) на свой. Так как адрес 7FFE0300 разделен между всеми процессами, сделал VirtualProtect(7FFE0300, 4, PAGE_WRITECOPY). Не работает Собственно, как правильно делать патч на KeFastSystemCall?
Кстати, обнаружил, что просто пропатчить KiFastSystemCall нельзя. Длина этой функции всего 4 байта. Банальным образом нет места для jmp.
Ну и что? Используй короткий джамп. 2 байта до нопов допрыгнуть тебе хватит. later:посмотрел.. не хватит Ближайщее подходящее место через 0xCB байт
Судя по ссылке которую вы указали (7FFE0300) вы решили выполнить перехват изменением адреса KiFastSystemCall в разделяемой ядром памяти, это UserSharedData.FastSystemCall вроде называется, не помню точно. Физический адрес для SP2 этой переменной равен 0FFDF0000h + 300h, в SP1 модель вызова другая. Для такого перехвата следует атомарно(lock xchg..) загрузить новый адрес, а эффективнее уменьшить на пять значение этой переменной(там адрес ntdll!KiFastSystemCall) а перед этой точкой находятся 5 инструкций nop, которые в процессе для которого выполняется перехват заменяются на инструкцию Jmp near KiFastSystemCallHandler. Второй вариант. По адресу KiFastSystemCall первая инструкция - mov edx,esp и она занимает 2 байта. Вместо этой инструкции вписать инструкцию Jmp short Reference, а Reference - это инструкция Jmp near KiFastSystemCallHandler, которая заёмёт 5 байт и разместить её можно сразу за точкой KiFastSystemCallRet, где есть 5 свободных байт для SP2. Там в WindowsVista вместо нопов находятся две инструкции lea esp,dword ptr ss:[esp], которые занимают больше 5 байт, так что можно вписать непосредственно адрес перехода(push KiFastSystemCallHandler/ret). Кстати интересный момент, Vista, код под олей: Код (Text): 008D0F34 KiFastSystemCallRet \$ C3 ret 008D0F35 . 8DA424 00000000 lea esp,dword ptr ss:[esp] 008D0F3C . 8D6424 00 lea esp,dword ptr ss:[esp] 008D0F40 KiIntSystemCall /$ 8D5424 08 lea edx,dword ptr ss:[esp+8] Интересно сравнить опкоды для одинаковых инструкций. Ну это другая тема. Третий вариант. Изменение собственно заглушки. Замена инструкции Call edx для SP1 либо Call dword ptr [edx] для остальных версий. Тут комментарии думаю излишни. Четвёртый вариант. Как ктото и сказал модификация MSR. Пятый вариант. Наиболее эффективен и сложен для реализации. Использование аппаратных точек останова. Установка аппаратной точки останова(DR) на адрес KiFastSystemCall для всех потоков либо для потока в котором следует выполнить перезват. Тут есть один важный момент, а именно использует ли код отладочные регистры помимо этого перехвата. Если нет то думаю стоит это заюзать. Шестой вариант. Механизм исключений. Подобно варианту 5. Запись инструкции которая вызовет исключение по адресу KiFastSystemCall. Для глобальной установки обработчика исключений следует использовать самый низкий хук, а именно той точки откуда поток начнёт выполнятся при возникновении исключения - ntdll!KiUserExceptionDispather. Это имеет смысл и для предыдущего пункта. Ну в общем и всё касательно юзермода, это основные способы перехвата этой точки. Насчёт режима ядра не буду обсуждать, так как раздел Win32. Думаю этого достаточно чтобы вы выбрали оптимальный вариант.
Есть ещё вариант перечислить все экспортируемые функции ntdll и сравнивать их имена примерно так: .if word ptr [eax]=='wZ' ... Call Callback ... .endif 7C90D379 > B8 00000000 MOV EAX,0 7C90D37E BA 0003FE7F MOV EDX,7FFE0300 7C90D383 FF12 CALL DWORD PTR DS:[EDX] 7C90D385 C2 1800 RETN 18 Патчить лучше всего MOV EDX,7FFE0300 на Call XX, обработчик будет примерно таким: SystemServiceHandler proc C ;в Eax номер сервиса, в стэке параметры. return_: mov edx,KUSER_SHARED_DATA.SystemCall[KUSER_SHARED_DATA_ADDRESS] retn 0 SystemServiceHandler endp Если нужна совместимость с win2k, это один из самых оптимальных вариантов. katrus Если не нужна совместимость с win2k то проще и не палевнее всего поменять dword по адресу SystemCall, почему у тебя не получилось не понятно, все должно работать что-то не правильно вызываешь.
Тебе в любом случае будет выдана частная копия страницы, так что не ссы. Даже если поставишь PAGE_READWRITE. Винда не такая тупая, чтобы твои изменения отражались на всех остальных процессах. Чтобы отразились придется наоборот постараться UPD: Хм, у меня не получается ни изменить права доступа, ни записать туда что-то...
Great lock xchg dword ptr ds:[0FFDF0000h + UsSystemCall],eax Сразу во всех процессах изменяется, любая запись в разделяемую память. [Если имеется ввиду юзермод то никак.]
Да из юзермода никак не изменишь, а вообще если изменить то придется во все созданные процессы впихивать хэндлер и ставить нотификацию на создание новых, либо писать код прямо в shared memory, там места достаточно.