Аннотация:
Это не единственная статья на тему перехвата API-вызовов. Необходимость в ней возникла вследствие того, что в других широко известных статьях и книгах есть небольшие ошибки, которые порой приводят к тому, что перехват не работает. Эта статья избавлена от указанных недостатков :)
Прочитал. Хорошая статья. Но не мешало бы добавить раздел, связанный с
перехватом на уровне 0 кольца (метод Руссиновича, т.е. перехват
обработчика int 2e). Пусть даже в виде компиляции из Шрайбера, например.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Прочитал. Хорошая статья. Но не мешало бы добавить раздел, связанный с PD>перехватом на уровне 0 кольца (метод Руссиновича, т.е. перехват PD>обработчика int 2e). Пусть даже в виде компиляции из Шрайбера, например.
Кто придумал, тот и вОда
Павел, мы (rsdn-team & редакция) будем только рады, если ты за это возьмёшься!
Здравствуйте, Игорь В. Филимонов, Вы писали:
ИВФ>Статья:
ИВФ>Авторы: ИВФ> Игорь В. Филимонов
ИВФ>Аннотация: ИВФ>Это не единственная статья на тему перехвата API-вызовов. Необходимость в ней возникла вследствие того, что в других широко известных статьях и книгах есть небольшие ошибки, которые порой приводят к тому, что перехват не работает. Эта статья избавлена от указанных недостатков
Насчет отсутствия OpenThread в Windows95, Windows98, WindowsNT. Всё реализуемо.
PD>Прочитал. Хорошая статья. Но не мешало бы добавить раздел, связанный с PD>перехватом на уровне 0 кольца (метод Руссиновича, т.е. перехват PD>обработчика int 2e). Пусть даже в виде компиляции из Шрайбера, например.
Ага, та же самая мысль возникла сразу по прочтении. Значит, действительно нужно
Кстати, ощущения после статьи двойственные.. С одной стороны, неплохо, тем более, что — что подобные вопросы часто на форуме WinAPI поднимаются. С другой — иногда попадаются совершенно удивительные с точки зрения русского языка фразы. Например:
Данный метод основан на следующем: если можно перехватить функцию из текущего процесса, то нужно выполнить код перехвата во всех процессах в системе.
О чем хотел сказать автор, я понял только после 2-го прочтения Да и то смутно — как относятся части если и то для меня осталось загадкой.
Наверное, лучше сказать было бы так:
Данный метод использует технику выполнения кода перехвата во всех процессах в системе.
Ну или что то в этом роде. Впрочем, в любом случае — статья полезная.
"... А в приложениях без очереди сообщений (например, консольных) этот способ внедрения вообще не работает."
Насколько я себе это представляю — если у потока нет очереди сообщений (message queue), то она автоматически сделается, при поступлении первого же сообщения потоку. По крайней мере в mdsn так написано. А если речь не о win32 приложении, то вроде как и перехватывать сабж не нужно? Так что это за приложения "без очереди сообщений".
...А отсюда наливаем, когда рецепт написан совсем неразборчиво...
Здравствуйте, Игорь В. Филимонов, Вы писали:
ИВФ>Статья:
ИВФ>Авторы: ИВФ> Игорь В. Филимонов
ИВФ>Аннотация: ИВФ>Это не единственная статья на тему перехвата API-вызовов. Необходимость в ней возникла вследствие того, что в других широко известных статьях и книгах есть небольшие ошибки, которые порой приводят к тому, что перехват не работает. Эта статья избавлена от указанных недостатков
--
В статье совершенно справедливо отмечается, что при перехвате управления путем непосредственной замены кода функции, необходимо:
----- ПРЕДУПРЕЖДЕНИЕ
На момент установки/снятия перехвата нужно останавливать все остальные потоки процесса,
в котором происходит перехват (или удостовериться, что они не могут вызывать перехватываемую функцию).
-----
Однако нужно не просто остановить потоки; но остановить их так, чтобы текущая выполняемая команда любого потока не оказалась внутри перехватываемого участка.
C уважением,
Геннадий Майко.
Re[2]: Методы перехвата API-вызовов в Win32
От:
Аноним
Дата:
21.09.04 04:12
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Однако нужно не просто остановить потоки; но остановить их так, чтобы текущая выполняемая команда любого потока не оказалась внутри перехватываемого участка.
А зачем? Пусть себе выполняется дальше. Даже если уже функция подменена, ничего страшного не произойдет. Адрес возврата в стеке ж не меняеться, так что функция благополучно завершит работу.
Здравствуйте, Аноним, Вы писали:
ГМ>>Однако нужно не просто остановить потоки; но остановить их так, чтобы текущая выполняемая команда любого потока не оказалась внутри перехватываемого участка.
А>А зачем? Пусть себе выполняется дальше. Даже если уже функция подменена, ничего страшного не произойдет. Адрес возврата в стеке ж не меняеться, так что функция благополучно завершит работу.
--
Возьмем, для примера, процессор семейства x86 и функцию, перехватываемый участок которой состоит из 5 однобайтных команд типа MOV R0, R1:
1: mov ax, bx
2: mov cx, dx
3: mov ebx, edx
4: mov ebp, sp
5: mov edi, esi
Предположим, что поток был остановлен после выполнении команды 3 и, следовательно, начнет выполнение с команды 4 после того, как возобновит работу. После замены этой последовательности команд на jmp DetourFunction, на месте байта команды 4 окажется байт из адреса DetourFunction, который будет интерпретирован возобновившим выполнение потоком как начало некоторой, в общем случае — другой команды.
Да действительно можно. Можно и в старшие 2 Гб писать.
Но — недокументированными методами. Возможно, об этом стоило упомянуть
(по-моему, в предварительных вариантах статьи об этом что-то было,
но потом я решил, что рассматривать реализацию недокументированными методами не стоит).
Вообще в Windows на самом деле можно многое из того, что нельзя.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Возьмем, для примера, процессор семейства x86 и функцию, перехватываемый участок которой состоит из 5 однобайтных команд типа MOV R0, R1:
ГМ>1: mov ax, bx ГМ>2: mov cx, dx ГМ>3: mov ebx, edx ГМ>4: mov ebp, sp ГМ>5: mov edi, esi
ГМ>Предположим, что поток был остановлен после выполнении команды 3 и, следовательно, начнет выполнение с команды 4 после того, как возобновит работу. После замены этой последовательности команд на jmp DetourFunction, на месте байта команды 4 окажется байт из адреса DetourFunction, который будет интерпретирован возобновившим выполнение потоком как начало некоторой, в общем случае — другой команды.
Совершенно справедливо. Я это и подразумевал. Понятно, что в своём процессе мы худо-бедно это проконтролировать сможем, а вот при глобальном перехвате — остаётся надеятся на удачу (а то можно загробить чужой процесс).
Конечно, можно остановить чужой поток, проанализировать состояние регистра PC и если он внутри "критической секции" из пяти заменяемых байт, то ResumeThread и остановить его чуть позже. В принципе, это реализуемо, но неслолько усложняет реализацию (особенно в примере с драйвером).
Что-то оно не работает
Решил я попробовать тестовый пример DriveType2.
Менял типы дисков — в программке из архива все работает. Даже более того, она сохраняет все значения типов дисков даже после ее перезапуска — . Но нигде в системе я не обнаружил изменений. Написал тестовую прогу, которая вызывает метод DriveTypeA — и ничего у меня не перехватывается.
Что не так делаю?
Здравствуйте, Михаил, Вы писали:
М>Насколько я себе это представляю — если у потока нет очереди сообщений (message queue), то она автоматически сделается, при поступлении первого же сообщения потоку. По крайней мере в mdsn так написано. А если речь не о win32 приложении, то вроде как и перехватывать сабж не нужно? Так что это за приложения "без очереди сообщений".
Очередь сообщений создается потоком и никем другим. При чем только тогда, когда вызывается одна из функций мудуля user. Если посылать потоку сообщения, то очередь никогда не будет создана.
Здравствуйте, Myk, Вы писали:
Myk>Что-то оно не работает Myk>Решил я попробовать тестовый пример DriveType2. Myk>Менял типы дисков — в программке из архива все работает. Даже более того, она сохраняет все значения типов дисков даже после ее перезапуска — . Но нигде в системе я не обнаружил изменений. Написал тестовую прогу, которая вызывает метод DriveTypeA — и ничего у меня не перехватывается. Myk>Что не так делаю?
Здравствуйте, Myk, Вы писали:
Myk>>Что-то оно не работает Myk>>Решил я попробовать тестовый пример DriveType2. Myk>>Менял типы дисков — в программке из архива все работает. Даже более того, она сохраняет все значения типов дисков даже после ее перезапуска — . Но нигде в системе я не обнаружил изменений. Написал тестовую прогу, которая вызывает метод DriveTypeA — и ничего у меня не перехватывается. Myk>>Что не так делаю?
У меня-то точно всё работает.
Вопрос:
какая операционка и на чём написан пример.
Здравствуйте, Myk, Вы писали:
Myk>У вас всех работает?
Имеется три машины...
win2k sp4(точно не уверен), всё работает...
winXP sp2 — валится StackOverFlow в методе LoadLibraryExW( там грузится в процесс еще одна DT2lib.dll,
и дальше следующий вызов LoadLibraryExW приводит к зацикливанию..)
другая машина с winXP sp2 при попытке хуканья чего-либо из хукнутого метода LoadLibraryExW,
валится случайный набор запущеных приложений)
если не хукать LoadLibrary(все варианты) и GetProcAddress. то работает (но конечно не везде)
вот
Re: Методы перехвата API-вызовов в Win32
От:
Аноним
Дата:
04.10.04 15:23
Оценка:
Здравствуйте, Игорь В. Филимонов, Вы писали:
ИВФ>Статья:
ИВФ>Авторы: ИВФ> Игорь В. Филимонов
ИВФ>Аннотация: ИВФ>Это не единственная статья на тему перехвата API-вызовов. Необходимость в ней возникла вследствие того, что в других широко известных статьях и книгах есть небольшие ошибки, которые порой приводят к тому, что перехват не работает. Эта статья избавлена от указанных недостатков