Перехват API-функций в Windows NT/2000/XP
От: Аноним Тихомиров В.А.  
Дата: 11.11.02 17:27
Оценка: 221 (8) +1
Статья:
Перехват API-функций в Windows NT/2000/XP
Автор(ы): Тихомиров В.А.
Дата: 11.11.2002


Авторы:
Тихомиров В.А.

Аннотация:
С переходом на Windows использование системных ресурсов программистами в большом объеме стало осуществляться через функции API, и у многих «сиспрогов» стал возникать вопрос: «существуют ли в Windows технологии перехватов этих системных функций?» Особый интерес это вызывает применительно к высокозащищенным ОС, выполненным на ядре NT. Данная статья подробнейшим образом, с действующими примерами покажет практическую реализацию такой технологии (предполагается, что читатель знаком с принципами системного программирования в Windows и умеет применять в своей работе Visual C++).
В статье мимимум одна грубая ошибка.
От: sherp  
Дата: 20.11.02 04:16
Оценка: 1 (1) +2
Складывается впечатление, что в статье есть по меньшей мере одна одна грубая ошибка. Что произойдёт, если таблица импорта будет расположена не в секции .idata? Кстати, случай, встречающийся довольно часто. Или же, скажем, секции .idata не будет совсем?Полагаться на то, что имена секций соответствуют информации, находящейся в ней, довольно наивно. Если нужно найти адрес данных, то в "необязательном" заголовке в конце есть поле DataDirectory[]. Именно оттуда необходимо выбирать информацию о том, где находятся таблицы, в том числе и импорта.
У Рихтера лучше
От: Demon Россия  
Дата: 14.03.03 13:56
Оценка: 3 (1)
Если это гениально, то почему не просто??? Господин автор не читал книгу "Windows для профессионалов" Рихтера (ISBN 5-272-00384-5), которая на русский была переведена аж в 2000 году? Или считает внедрение с использованием ассемблера признаком крутизны? У Рихтера "Внедрение 1" сделано гораздо проще и никакими машинными кодами там и не пахнет.
Re: push + ret vs jmp
От: Alter_ Украина http://alter.org.ua
Дата: 02.04.05 19:38
Оценка: 1 (1)
Здравствуйте, Sergey Ten, Вы писали:

ST>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


На новых процах push + ret рассинхронизирует кеш адресов возврата со стеком. Шаманы утверждают, что потери производительности просто потрясающие.
На каждом последующем ret'е данные подчитываются из памяти.
Ну а преимущество конечно в том, что не нужно относительных адресов вычислять
--
Alter, http://alter.org.ua
push + ret vs jmp
От: Sergey Ten http://www.fastalgo.com
Дата: 12.11.02 17:27
Оценка:
А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?
Спасибо
От: Sandman  
Дата: 15.11.02 07:30
Оценка:
Классная статья.Спасибо В.А. :)
А как насчет сложных функций, типа вывода текста.
От: null  
Дата: 17.11.02 14:48
Оценка:
Например, TextOut и т.п. Основная особенность всех перехватов, что все авторы методов (а я их перепробовал очень много — как-то очень было нужно) в качестве примеров используют MessageBox, который прекрасно работает, но никогда не работает вышеприведенная функция. Почему?
Re: А как насчет сложных функций, типа вывода тек
От: Sergey Ten http://www.fastalgo.com
Дата: 18.11.02 06:34
Оценка:
Только что проверил TextOut — работает как из пушки. Два момента, на которые есть смысл посмотреть:

1. Функция экспортируется из gdi32.dll и называется TextOutA (не-Unicode версия, Unicode, соответственно, TextOutW)

2. Убедитесь, что прототип ее перехватчика объявлен как stdcall.

Все должно заработать.
Работает, вот только...
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 29.11.02 11:47
Оценка:
... в загрузчике (attach.exe) явно не хватает приведения пути к dll к абсолютному. Всю голову свернул :), пока понял, что просто имя dll или путь относительно текущего каталога не проходят — только полный путь.
Wincmd
От: null  
Дата: 15.01.03 01:44
Оценка:
Странная вещь — не получается перехватить API в программе Windows Commander и еще некоторых. В функции, которая занимается перехватом, я вствил вызовы OutputDebugString,
и обнаружил, что поле OriginalFirstThunk Всегда равно 0.
.idata
От: Валиев Рустам  
Дата: 21.01.03 09:41
Оценка:
Очевидно, что метод №2 более правилен нежели №1 при работе с многопотоковыми приложениями. Но здесь есть проблема. Дело в том, что секции .idata в подавляющем большинстве программ НЕТ, для release-версий линкеры смешивают эту секцию с другими, обычно с .rdata, об этом сказано в MSDN см. например, http://msdn.microsoft.com/msdnmag/issues/02/03/pe2/default.aspx,
(комментарий к Figure 1 Section Names)

"... It has become common practice (either explicitly, or via linker default behavior) to merge the .idata section into another section, typically .rdata. By default, the linker only merges the .idata section into another section when creating a release mode executable. ... "

Вопрос — как разыскать в таком случае таблицу импортируемых функций ?

------------
И еще мелочь — не совсем понятно зачем в методе №1 использовать вызов функции через указатель
....
//Вызываем оригинальную функцию через указатель
((BOOL (__stdcall*)(HWND, char*, char*, UINT))adr_MessageBoxA)(hwnd, str, hdr, utype);
....

почему бы просто не вызвать через MessageBox ? — "нормальный" адрес ведь восстановлен ...
Re: .idata
От: Валиев Рустам  
Дата: 28.01.03 11:03
Оценка:
Вот нашел немного времени разобраться.

В качестве критики к статье хотел бы сказать, что поиск указателя на функцию не обязательно делать через .idata, это даже не совсем хорошо — примерно как удалять гланды через ухо.

Как правильно сказал sherp "...адрес данных, то в "необязательном" заголовке в конце есть поле DataDirectory[]. Именно оттуда необходимо выбирать информацию о том, где находятся таблицы, в том числе и импорта. ...", точнее, этот указатель она лежит во второй ячейке этого массива. Берем оттуда адрес на таблицу импорта и ...

// В таблице импорта ищем соответствующий элемент для библиотеки user32.dll
while(iid->Name) //до тех пор пока поле структуры не содержит 0
{
if(strcmp((char*)(pimage + iid->Name), "USER32.dll") ==0 ) break;
iid++;
}

// Ищем в IMAGE_THUNK_DATA нужный адрес
isd = (DWORD*)(pimage + iid->FirstThunk);
while(*isd!=adr_MessageBoxA && *isd!=0) isd++;
if(*isd == 0)
...

ПыСы: некоторые функции могут итмпортироваться не напрямую из ехе-файла а "косвенно" — из импортируемых им других dll. Пример — функция MessageBox в HyperTerminal (hypertrm.exe). Ее можно найти в блоке импорта модуля hypertrm.dll. Чтобы обратиться к этой таблице нужно вместо
BYTE *pimage = (BYTE*)GetModuleHandle(NULL);
нужно написать
BYTE *pimage = (BYTE*)GetModuleHandle("hypertrm.dll");
Путь указывать не надо поскольку dll-ка видна из процесса.

Может быть с этим связана проблема перехвата OutputDebugString в Windows Commander.
Re: .idata
От: Валиев Рустам  
Дата: 28.01.03 11:07
Оценка:
Да, еще, кому интересно, вот ссылки из которых много можно почерпнуть:
http://msdn.microsoft.com/msdnmag/issues/02/02/pe/default.aspx
http://msdn.microsoft.com/msdnmag/issues/02/03/pe2/default.aspx
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndebug/html/msdn_peeringpe.asp

хороший перевод содержится в статье "Форматы PE и COFF ..."
SoftICE
От: null  
Дата: 03.02.03 01:42
Оценка:
Когда я устанавливал SoftICE, инсталлятор выдавал окошко с предложением отключить защиту памяти "только для чтения" через настройки реестра. После того как я это сделал, начались глюки — неправильно работали списки и окошки редактирования текста(Edit control'ы) и программы не запускались через меню "Пуск" и значки на рабочем столе. Кроме того, исчезла картинка, выдающаяся при загрузке Windows 2000 (где написано "Windows 2000 на основе NT" и показывается индикатор загрузки). Я удалил SoftICE и все заработало нормально, но вот только картинка загрузки не вернулась.
Как вернуть все как было?
Re: SoftICE
От: vasketsov Россия http://ntprog.by.ru
Дата: 18.07.03 17:26
Оценка:
Здравствуйте, null, Вы писали:

Из boot.ini надо удалить /noguiboot
Васкецов Сергей
http://registry.km.ru
Re: Перехват API-функций в Windows NT/2000/XP
От: Аноним  
Дата: 23.11.03 16:33
Оценка:
Пытался исползовать "Внедрение 1" под 2000-им , но на команде CreateRemoteThread
выдается ошибка Memory Can't be writen. В чем дело ?
Re: push + ret vs jmp
От: В и к т о р  
Дата: 24.11.03 08:34
Оценка:
Здравствуйте, Sergey Ten, Вы писали:

ST>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


У Рихтера прочитал, что JUMP зависит от процессора и вообще он про первый метод пишет:

Этот метод был очень популярен среди программистов, создававших приложения для 16-разрядной Windows, и отлично работал в этой системе В современных системах у этого метода возникло несколько серьезных недостатков, и я настоятельно не рекомендую его применять. Во-первых, он создает зависимость от конкретного процессора из-за команды JUMP, и, кроме того, приходится вручную писать машинные коды. Во-вторых, в системе с вытесняющей многозадачностью данный метод вообще не годится. На замену кода в начале функции уходит какое-то время, а в этот момент перехватываемая функция может понадобиться другому потоку. Результаты могут быть просто катастрофическими!

Re[2]: .idata
От: Николай Gorlum  
Дата: 05.12.03 21:47
Оценка:
Здравствуйте, Валиев Рустам, Вы писали:

ВР>Вот нашел немного времени разобраться.


ВР>В качестве критики к статье хотел бы сказать, что поиск указателя на функцию не обязательно делать через .idata, это даже не совсем хорошо — примерно как удалять гланды через ухо.


ВР>Как правильно сказал sherp "...адрес данных, то в "необязательном" заголовке в конце есть поле DataDirectory[]. Именно оттуда необходимо выбирать информацию о том, где находятся таблицы, в том числе и импорта. ...", точнее, этот указатель она лежит во второй ячейке этого массива. Берем оттуда адрес на таблицу импорта и ...


ВР> // В таблице импорта ищем соответствующий элемент для библиотеки user32.dll

ВР> while(iid->Name) //до тех пор пока поле структуры не содержит 0
ВР> {
ВР> if(strcmp((char*)(pimage + iid->Name), "USER32.dll") ==0 ) break;
ВР> iid++;
ВР> }

ВР> // Ищем в IMAGE_THUNK_DATA нужный адрес

ВР> isd = (DWORD*)(pimage + iid->FirstThunk);
ВР> while(*isd!=adr_MessageBoxA && *isd!=0) isd++;
ВР> if(*isd == 0)
ВР>...

ВР>ПыСы: некоторые функции могут итмпортироваться не напрямую из ехе-файла а "косвенно" — из импортируемых им других dll. Пример — функция MessageBox в HyperTerminal (hypertrm.exe). Ее можно найти в блоке импорта модуля hypertrm.dll. Чтобы обратиться к этой таблице нужно вместо

ВР> BYTE *pimage = (BYTE*)GetModuleHandle(NULL);
ВР>нужно написать
ВР> BYTE *pimage = (BYTE*)GetModuleHandle("hypertrm.dll");
ВР>Путь указывать не надо поскольку dll-ка видна из процесса.

ВР>Может быть с этим связана проблема перехвата OutputDebugString в Windows Commander.


скажите, а я правильно понимаю, что ".idata" — это вовсе не обязательная секция и таблица может находиться где-нибудь в другом месте?
Re[3]: .idata
От: Sergey Россия  
Дата: 08.12.03 08:57
Оценка:
Hello, Николай!
You wrote on Fri, 05 Dec 2003 21:47:21 GMT:

НG> скажите, а я правильно понимаю, что ".idata" — это вовсе не

НG> обязательная секция и таблица может находиться где-нибудь в другом
НG> месте?

ДА.

Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Перехват API-функций в Windows NT/2000/XP
От: MOPO3 Литва  
Дата: 18.08.04 08:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Статья:



А>Авторы:

А>Тихомиров В.А.

А>Аннотация:

А>С переходом на Windows использование системных ресурсов программистами в большом объеме стало осуществляться через функции API, и у многих «сиспрогов» стал возникать вопрос: «существуют ли в Windows технологии перехватов этих системных функций?» Особый интерес это вызывает применительно к высокозащищенным ОС, выполненным на ядре NT. Данная статья подробнейшим образом, с действующими примерами покажет практическую реализацию такой технологии (предполагается, что читатель знаком с принципами системного программирования в Windows и умеет применять в своей работе Visual C++).

Вот это "intercpt.h" откуда взять ?
Re: Перехват API-функций в Windows NT/2000/XP
От: Keith  
Дата: 02.04.05 14:04
Оценка:
У Рихтера по поводу первого метода:

Этот метод был очень популярен среди программистов, создававших приложения для 16-разрядной Windows, и отлично работал в этой системе В современных системах у этого метода возникло несколько серьезных недостатков, и я настоятельно не рекомендую его применять. Во-первых, он создает зависимость от конкретного процессора из-за команды JUMP, и, кроме того, приходится вручную писать машинные коды. Во-вторых, в системе с вытесняющей многозадачностью данный метод вообще не годится. На замену кода в начале функции уходит какое-то время, а в этот момент перехватываемая функция может понадобиться другому потоку. Результаты могут быть просто катастрофическими!


По поводу "во-первых": распознавать тип процессора и в зависимости от него записывать либо x86 "JMP", либо x64 "JMP" по-моему не сложно.
По поводу "во-вторых": почему бы не выключать планирование всех потоков кроме текущего на время замены кода? Это должно занимать меньше времени, чем дизассемблирование команд, как в Detours. Или нет?

зы А есть ли бесплатные исходники дизассемблеров для x86 и x64, которые можно использовать в коммерческих продуктах?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Re[2]: Перехват API-функций в Windows NT/2000/XP
От: Alter_ Украина http://alter.org.ua
Дата: 02.04.05 19:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Пытался исползовать "Внедрение 1" под 2000-им , но на команде CreateRemoteThread

А>выдается ошибка Memory Can't be writen. В чем дело ?

Вероятно в отсутствии вот такого:
    if (VirtualProtect(pDest, dwSize, PAGE_READWRITE, &dwOldProtect))
    {
        memcpy(pDest, pSrc, dwSize);
        // Restore protection
        VirtualProtect(pDest, dwSize, dwOldProtect, &dwOldProtect);
    }
--
Alter, http://alter.org.ua
Re[2]: push + ret vs jmp
От: Alter_ Украина http://alter.org.ua
Дата: 02.04.05 19:41
Оценка:
Здравствуйте, В и к т о р, Вы писали:

ВИК>Здравствуйте, Sergey Ten, Вы писали:


ST>>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


ВИК>У Рихтера прочитал, что JUMP зависит от процессора и вообще он про первый метод пишет:

ВИК>

ВИК>Этот метод был очень популярен среди программистов, создававших приложения для 16-разрядной Windows, и отлично работал в этой системе В современных системах у этого метода возникло несколько серьезных недостатков, и я настоятельно не рекомендую его применять. Во-первых, он создает зависимость от конкретного процессора из-за команды JUMP, и, кроме того, приходится вручную писать машинные коды. Во-вторых, в системе с вытесняющей многозадачностью данный метод вообще не годится. На замену кода в начале функции уходит какое-то время, а в этот момент перехватываемая функция может понадобиться другому потоку. Результаты могут быть просто катастрофическими!


Все не так страшно Главное — на время патчинга нужно остановить текущий процесс (all threads) или все процессоры (если мы в kernel mode системную ф-цию из global address space перехватываем). Так что годится. Мало того, успешно применяется
--
Alter, http://alter.org.ua
Re[2]: push + ret vs jmp
От: Alex Alexandrov США  
Дата: 03.04.05 07:32
Оценка:
Здравствуйте, Alter_, Вы писали:

A_>Здравствуйте, Sergey Ten, Вы писали:


ST>>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


A_>На новых процах push + ret рассинхронизирует кеш адресов возврата со стеком. Шаманы утверждают, что потери производительности просто потрясающие.

A_>На каждом последующем ret'е данные подчитываются из памяти.
A_>Ну а преимущество конечно в том, что не нужно относительных адресов вычислять

А какое же тут шаманство? Открываем толстый том Intel(r) IA-32 Optimization Reference Manual:

Inlining, Calls and Returns

The return address stack mechanism augments the static and dynamic
predictors to optimize specifically for calls and returns. It holds 16
entries, which is large enough to cover the call depth of most programs.
If there is a chain of more than 16 nested calls and more than 16 returns
in rapid succession, performance may be degraded.
The trace cache maintains branch prediction information for calls and
returns. As long as the trace with the call or return remains in the trace
cache and if the call and return targets remain unchanged, the depth
limit of the return address stack described above will not impede
performance.
To enable the use of the return stack mechanism, calls and returns must
be matched in pairs. If this is done, the likelihood of exceeding the
stack depth in a manner that will impact performance is very low.


Таким образом, при рассинхронизации внутреннего стека адресов возврата при каждом ret будет происходить branch misprediction с соответствующим сбросом конвейера. Хуже и придумать нельзя...
[ Posted via RSDN@Home 1.1.4 beta 4 (303) listening to silent ]
It's kind of fun to do the impossible (Walt Disney)
Re: Перехват API-функций в Windows NT/2000/XP
От: Alex Alexandrov США  
Дата: 03.04.05 07:32
Оценка:
Здравствуйте, Тихомиров В.А., Вы писали:

ТВА>Статья:



ТВА>Авторы:

ТВА>Тихомиров В.А.

ТВА>Аннотация:

ТВА>С переходом на Windows использование системных ресурсов программистами в большом объеме стало осуществляться через функции API, и у многих «сиспрогов» стал возникать вопрос: «существуют ли в Windows технологии перехватов этих системных функций?» Особый интерес это вызывает применительно к высокозащищенным ОС, выполненным на ядре NT. Данная статья подробнейшим образом, с действующими примерами покажет практическую реализацию такой технологии (предполагается, что читатель знаком с принципами системного программирования в Windows и умеет применять в своей работе Visual C++).

Вот к этому:

Есть еще и третий способ внедрения, но он наиболее опасен, так как может привести к краху системы. При помощи данного метода ОС сама внедряет указанную dll во все без исключения процессы операционной системы, даже защищенные. Для реализации необходимо прописать в реестре по пути Hkey_local_machine\software\microsoft\windowsnt\currentversion\windows в ключе AppInit_DLLs полный путь к своей dll.


надо добавить

Кроме того, ключ AppInit_DLLs обрабатывается в коде инициализации user32.dll, так что если целевое приложение не загружает явно или неявно эту библиотеку, этот метод не сработает вовсе.

[ Posted via RSDN@Home 1.1.4 beta 4 (303) listening to silent ]
It's kind of fun to do the impossible (Walt Disney)
Re[2]: push + ret vs jmp
От: Alex Alexandrov США  
Дата: 03.04.05 07:32
Оценка:
Здравствуйте, В и к т о р, Вы писали:

ВИК>Здравствуйте, Sergey Ten, Вы писали:


ST>>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


ВИК>У Рихтера прочитал, что JUMP зависит от процессора


То есть вы хотите сказать, что jmp зависит от процессора, а push и ret — нет? Интересная точка зрения...
[ Posted via RSDN@Home 1.1.4 beta 4 (303) listening to silent ]
It's kind of fun to do the impossible (Walt Disney)
Re[3]: push + ret vs jmp
От: Alter_ Украина http://alter.org.ua
Дата: 03.04.05 08:07
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Здравствуйте, Alter_, Вы писали:


A_>>Здравствуйте, Sergey Ten, Вы писали:


ST>>>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


A_>>На новых процах push + ret рассинхронизирует кеш адресов возврата со стеком. Шаманы утверждают, что потери производительности просто потрясающие.

A_>>На каждом последующем ret'е данные подчитываются из памяти.
A_>>Ну а преимущество конечно в том, что не нужно относительных адресов вычислять

AA>А какое же тут шаманство? Открываем толстый том Intel(r) IA-32 Optimization Reference Manual:

Шаманы из команды разработки intel

AA>Таким образом, при рассинхронизации внутреннего стека адресов возврата при каждом ret будет происходить branch misprediction с соответствующим сбросом конвейера. Хуже и придумать нельзя...

Ну вот и я о том же
--
Alter, http://alter.org.ua
Re[4]: push + ret vs jmp
От: Alex Alexandrov США  
Дата: 03.04.05 08:58
Оценка:
Здравствуйте, Alter_, Вы писали:

AA>>А какое же тут шаманство? Открываем толстый том Intel(r) IA-32 Optimization Reference Manual:

A_>Шаманы из команды разработки intel

Ну надо же... Я тоже знаком с некоторыми из них...
[ Posted via RSDN@Home 1.1.4 beta 4 (303) listening to silent ]
It's kind of fun to do the impossible (Walt Disney)
Re[3]: push + ret vs jmp
От: Keith  
Дата: 04.04.05 11:29
Оценка:
A_>Все не так страшно Главное — на время патчинга нужно остановить текущий процесс (all threads) или все процессоры (если мы в kernel mode системную ф-цию из global address space перехватываем). Так что годится. Мало того, успешно применяется
Вы не могли бы поделиться кодом, который останавливает/запускает все потоки текущего процесса? Не хочется изобретать велосипед.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Re[3]: push + ret vs jmp
От: Злость Россия  
Дата: 04.04.05 12:21
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Здравствуйте, В и к т о р, Вы писали:


ВИК>>Здравствуйте, Sergey Ten, Вы писали:


ST>>>А какие преимущества у подхода push + ret по сравнению с jmp? Возможна ли ситуация, когда jmp не работает, а push+ret — работают? И на какие грабли здесь можно наступить?


ВИК>>У Рихтера прочитал, что JUMP зависит от процессора


AA>То есть вы хотите сказать, что jmp зависит от процессора, а push и ret — нет? Интересная точка зрения...


Наверное имелось ввиду что jump может иметь разный размер инструкции.
Правда, Ложь — мне все одно — я имею свое мнение.
Если функция недокументированна — это не значит, что ее не используют все ваши конкуренты в своих продуктах.
Любой строй переходный и отрицать это значит быть закостенелым идиотом.
Re: Перехват API-функций в Windows NT/2000/XP
От: ДимДимыч Украина http://klug.org.ua
Дата: 28.12.06 14:53
Оценка:
Здравствуйте, Тихомиров В.А., Вы писали:

ТВА>Статья:

ТВА>Перехват API-функций в Windows NT/2000/XP
Автор(ы): Тихомиров В.А.
Дата: 11.11.2002


Замечание по поводу метода 2: как выяснилось, компилятор Borland (возможно, не только он) может создавать несколько записей IMAGE_IMPORT_DESCRIPTOR, соответствующих одной и той же библиотеке. Поэтому, если перехватываемая функция упоминается не в первой записи, то следующий код:

 while(iid->Name)  //до тех пор пока поле структуры не содержит 0
  {
    if(strcmp((char*)(pimage + iid->Name), "USER32.dll") ==0 ) break;
    iid++;
  }

работать не будет. Пришлось заменить примерно следующим:

for (iid = (IMAGE_IMPORT_DESCRIPTOR*)(pimage + (ish +i)->VirtualAddress ); iid->Name; iid++)  //до тех пор пока поле структуры не содержит 0
    if(strcmp((char*)(pimage + iid->Name), "USER32.dll") == 0)
    {
        // Search address and intercept
        ....
    }
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re: Access violation
От: Аноним  
Дата: 22.07.08 00:00
Оценка:
Здравствуйте, Тихомиров В.А., Вы писали:

ТВА>Статья:

ТВА>Перехват API-функций в Windows NT/2000/XP
Автор(ы): Тихомиров В.А.
Дата: 11.11.2002


ТВА>Авторы:

ТВА>Тихомиров В.А.

ТВА>Аннотация:

ТВА>С переходом на Windows использование системных ресурсов программистами в большом объеме стало осуществляться через функции API, и у многих «сиспрогов» стал возникать вопрос: «существуют ли в Windows технологии перехватов этих системных функций?» Особый интерес это вызывает применительно к высокозащищенным ОС, выполненным на ядре NT. Данная статья подробнейшим образом, с действующими примерами покажет практическую реализацию такой технологии (предполагается, что читатель знаком с принципами системного программирования в Windows и умеет применять в своей работе Visual C++).


Пытался использовать метод 1, приведенный в статье для перехвата функции MessageBoxA()
Скомпилировал файл method1.dll из кода, приведенного в статье для метода 1. Использовал весь код из статьи, ничего не менял
Затем написал простейшее консольное приложение:

// MyProg.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    LoadLibrary("method1.dll");

    MessageBox(NULL, "Something has been written here", "MessageBox", 0);

    return 0;
}


Запустил. Но, к сожалению, оно вылетает со словами:
Unhandled exception at 0x77d70510 in MyProg.exe: 0xC0000005: Access violation writing location 0x10000000.

Никто случайно не знает, почему так случилось и можно ли как-то исправить, чтобы работало?
На всякий случай, платформа — WindowsXP, среда разработки — VC2003
Заранее благодарен
Re[2]: Access violation
От: Danchik Украина  
Дата: 22.07.08 14:52
Оценка:
Здравствуйте, Аноним, Вы писали:

[Skip]

А>Никто случайно не знает, почему так случилось и можно ли как-то исправить, чтобы работало?

А>На всякий случай, платформа — WindowsXP, среда разработки — VC2003
А>Заранее благодарен

Посмотрите на Detours
Re[2]: Access violation
От: Аноним  
Дата: 23.07.08 22:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Пытался использовать метод 1, приведенный в статье для перехвата функции MessageBoxA()

А>Скомпилировал файл method1.dll из кода, приведенного в статье для метода 1. Использовал весь код из статьи, ничего не менял
А>Затем написал простейшее консольное приложение:
А>Запустил. Но, к сожалению, оно вылетает со словами:


В общем, разобрался я, в чем дело, может, пригодится кому...
Оказалось, проблема у меня была с выравниванием. То есть все работает, если написать так:

#pragma pack(push,1)
struct jmp_far
{
  BYTE instr_push;  //здесь будет код инструкции push
  DWORD arg;         //аргумент push
  BYTE  instr_ret;    //здесь будет код инструкции ret
};
#pragma pack(pop)


Иначе структура имела неправильный размер
А так все отлично, работает на ура. По крайней мере, в WindowsXP
Автору статьи большое спасибо, хоть и времени уже порядочно прошло
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.