Перехват системных вызовов на винде - Detours на коленке..
сохранить первую инструкцию в -ах и короткий jmp на вторую инструкцию,
первую инструкцию заменить на короткий jmp в -ы, откуда уже делать длинный jmp в подвал
дизассемблировать достаточно только первую инструкцию и знать надо только ее длину
есть две подставы:
- на первую инструкцию замыкается цикл внутри функции, тогда подвал будет выполняться на каждой итерации
- первая инструкция является коротким jmp-ом, тогда придется корректно пересчитать смещение
diStorm вроде ничё так,
А без дизассемблера видимо никуда - накатит микрософт очередной апдейт, начала функций поменяются - и привет.
как вариант - закладываться на известные модификации нужной мне dll (включая различные сервис-паки и локализации, ага!)
мои глаза замылились - diStorm нормально работает.
mov rax, SOME_DWORD_OFFSET
jmp rax
А после этого соответствующим образом поправить relocations и таблицу экспорта в заголовке PE.
DWORD_OFFSET не всегда получится сделать - нет гарантии, что мне будут доступны +-2Гб от места перехвата
DWORD_OFFSET не всегда получится сделать - нет гарантии, что мне будут доступны +-2Гб от места перехватаВ таком случае приходит на ум только
push qword ptr [rip+DWORD_OFFSET]
ret
7 байт, в 'ы умещается, только нужно ещё где-то заранее разместить нужный адрес. Можно в 'ах другой функции, например, которую не нужно перехватывать.
По ссылке этого вроде бы нет.
Ещё релокации править, похоже, не нужно будет. Только таблицу экспорта для правильной линковки вновь загружаемых модулей, а также IAT у уже загруженных.
Если места совсем не хватает на размещение адресов обработчиков перехватов, можно попробовать заменить код на
call qword ptr [rip+DWORD_OFFSET]
и сделать всего один обработчик-"роутер", который по адресу возврата в стэке определял бы перехватываемую функцию и вызывал соответствующий другой обработчик. Ну и стэк подчистить надо будет.
1. сделать оберточные библиотеки ntdll_1.dll, kernel32_1.dll, которые будут экспортировать все те же функции, что и исходные библиотеки и перенаправлять соответствующие функции куда надо, т.е. либо к тебе, либо в исходный код. Далее, сделать так, чтобы исследуемая программа ссылалась бы не на kernel32.dll, а не kernel32_1.dll
2. если нужный тебе системный вызов (т.е. MessageBoxW) один, то можно переопределить его в таблице экспорта исследуемой программы на вызов функции DebugBreak, твой же модуль должен будет приаттачиться в качестве дебаггера
3. что мешает сделать патчинг на коленке, если у тебя системных вызовов - небольшое счетное число? если их даже штук 20, то быстрее ручками повставлять jmp-ы с последующим исполнением правильных команд?
4. вставлять не jmp, а int 3?
вот так
Нужные мне вызовы сосредоточены в другом месте.
int 3 - попробую, опыт есть. но что-то мне подсказывает, что тут потребуется внешний процесс, а аттачиться к рабочему не всегда возможно.
ща надо будет у конкурентов подсмотреть, как они внедряются.
с int 3 ещё есть засада - туда из ядра не зайдёшь.
патчить ntdll и kernel нельзя - начиная с 2003 сервера/висты микрософт извернулась Нужные мне вызовы сосредоточены в другом месте.
int 3 - попробую, опыт есть. но что-то мне подсказывает, что тут потребуется внешний процесс, а аттачиться к рабочему не всегда возможно.
ща надо будет у конкурентов подсмотреть, как они внедряются.
с int 3 ещё есть засада - туда из ядра не зайдёшь.
или, как вариант, запустить старой версии на windows xp
гугл выдает, кстати, какие-то ссылки по теме 'disable kernel patch protection'
ну здрасьте, у клиентов винду портить?
http://code.google.com/p/windows-reimport/
К сожалению, нет 100% гарантий, что в exe'шнике найдется место для добавления в заголовок новой секции.
Оставить комментарий
yolki
Задача: перехватить некоторые системные вызовы и перенаправить на себя.Для x86 я более-менее представляю как это делать. Благо все интересные мне функции имеют вначале mov edi,edi - и пять NOP-ов до тела функции.
вместо mov edi, edi ставится jmp -7, а вместо NOP-ов - длинный джамп ко мне в подвал.
однако, в x64 Микрософт концепцию поменяла:
патчинг на коленке не пройдёт, надо сохранять часть начала функции, непонятно только - где. и сколько (10 байт? не придутся ли они на половину инструкции?) - дизассемблировать на лету вроде не вариант.
а девять NOP-ов до начала функции намекают на то, что туда можно ставить трамплин к себе. вот только не понятно как зарулить выполнение на трамплин.
может, кто подскажет?
Чтение по теме
раз
два
три