Сейчас на форуме: igorcauret, Rio (+6 невидимых) |
![]() |
eXeL@B —› Вопросы новичков —› Зачем нужна инструкция MOV EDI,EDI |
Посл.ответ | Сообщение |
|
Создано: 17 июня 2015 22:14 · Личное сообщение · #1 Приветствую. Почему реализация всех WinAPI-функций начинается с инструкции MOV EDI,EDI? В интернете (например, Вот, допустим, есть функция CreateFileA. Начало её реализации на моей системе имеет следующий вид: Code:
В результате патчинга JMP'ом с относительным адресом я затру первые три инструкции (MOV EDI, PUSH EBP и MOV EBP,ESP). Но что было бы плохого, если бы тут не было инструкции MOV EDI,EDI? Ну, затёр бы я тогда ещё два PUSH ECX, что в этом такого? Или это сделано, чтобы можно было пропатчить даже те функции, у которых реализация занимает ровно пять байт вместе с этим MOV EDI,EDI? Но даже если так, WinAPI-функции всё равно разделяются между собой NOP'ами, так что проблем с этим быть не должно. И ещё один момент, связанный с перехватом вызовов WinAPI-функций путём как раз подобного патча. На void BeginRedirect(LPVOID newFunction) Скажите, пожалуйста, зачем после JMP'а они предлагают писать инструкцию RET? Ведь это же безусловный переход на нашу функцию, внутри которой мы вернём оригинальный код WinAPI-функции обратно, и никогда не попадём на этот самый RET. Какой в этом смысл? Заранее благодарю за возможные ответы. ![]() |
|
Создано: 17 июня 2015 22:46 · Поправил: plutos · Личное сообщение · #2 |
|
Создано: 17 июня 2015 22:50 · Личное сообщение · #3 plutos пишет: Читаем тут, может поможет: http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx Так я же и скинул ссылку на эту статью. Собственно, я про неё и написал в начале следующее: > В интернете (например, тут) это объясняется тем, что данная инструкция позволяет написать двух-байтовый патч в виде JMP $-5, чтобы передать управление коду, который находится на пять байт раньше начала пропатченной WinAPI-функции. Но почему нельзя обойтись без MOV EDI,EDI и заменить JMP'ом другие инструкции? ![]() |
|
Создано: 17 июня 2015 23:01 · Личное сообщение · #4 b0r3d0m пишет: Но почему нельзя обойтись без MOV EDI,EDI и заменить JMP'ом другие инструкции? В смысле, первые инструкции, после MOV EDI, EDI? Так ведь их эмулить придется после выполнения перехвата. А так - имеем инструкцию-пустышку, которая не нужна целевой функции. Это, вроде, очевидно! b0r3d0m пишет: WinAPI-функции всё равно разделяются между собой NOP'ами, так что проблем с этим быть не должно. nop для выравнивания, и это уже другой район, который не относиться к хукам. Правда, годный для использования. b0r3d0m пишет: зачем после JMP'а они предлагают писать инструкцию RET? А вдруг CPU заглючит и переход безусловный не сработает ![]() ![]() Я бы по другому поставил вопрос еще: смысл в таких "паразитных" инструкциях, как MOV EDI, EDI. Положить регистр сам в себя?! Бессмысленно и беспощадно. ![]() |
|
Создано: 17 июня 2015 23:07 · Личное сообщение · #5 hello пишет: Так ведь их эмулить придется после выполнения перехвата Зачем? Вот, допустим, в том же примере с вики после выполнения безусловного перехода на нашу функцию мы просто возвращаем изначальные байты оригинальной функции обратно и вызываем её снова. hello пишет: nop для выравнивания, и это уже другой район, который не относиться к хукам Но ведь использовать же их можно, верно? hello пишет: А по хорошему: может туда управление, в конце концов передается Каким образом? Там выполняется безусловный переход с последующим восстановлением оригинального кода перехваченной WinAPI-функции, так что не вижу такой возможности. ![]() |
|
Создано: 17 июня 2015 23:13 · Поправил: plutos · Личное сообщение · #6 b0r3d0m пишет: Собственно, я про неё и написал в начале следующее:> В интернете (например, тут) это объясняется тем, что данная инструкция позволяет написать двух-байтовый патч в виде JMP $-5, чтобы передать управление коду, который находится на пять байт раньше начала пропатченной WinAPI-функции. Но почему нельзя обойтись без MOV EDI,EDI и заменить JMP'ом другие инструкции? Ну извините, не догадался, что это именно о ней идет речь. Оно как-то не очевидно. А самой ссылки не видал. Теперь вижу. ----- Give me a HANDLE and I will move the Earth. ![]() |
|
Создано: 17 июня 2015 23:16 · Личное сообщение · #7 |
|
Создано: 17 июня 2015 23:16 · Поправил: dosprog · Личное сообщение · #8 hello пишет: Я бы по другому поставил вопрос еще: смысл в таких "паразитных" инструкциях, как MOV EDI, EDI. Если использовать заполнение обычными NOP, то очевидна "неэффективность" полученного года, видимая "невооружённым" глазом в обычном текстовом редакторе. А так код выглядит солидно, да и дополнительная возможность для проверки сигнатуры. Вообще, такие вопросы сродни интересу к сигнатуре "MZ" - "почему-да-как?". Изначально сделали так, а потом изменять это не было нужды. ![]() |
|
Создано: 17 июня 2015 23:19 · Поправил: b0r3d0m · Личное сообщение · #9 dosprog пишет: Если использовать заполнение обычными NOP, то очевидна "неэффективность" полученного года, видимая "невооружённым" глазом в обычном текстовом редакторе > Why not just use two NOP instructions at the entry point? Well, because a NOP instruction consumes one clock cycle and one pipe, so two of them would consume two clock cycles and two pipes. (The instructions will likely be paired, one in each pipe, so the combined execution will take one clock cycle.) On the other hand, the MOV EDI, EDI instruction consumes one clock cycle and one pipe. (In practice, the instruction will occupy one pipe, leaving the other available to execute another instruction in parallel. You might say that the instruction executes in half a cycle.) However you calculate it, the MOV EDI, EDI instruction executes in half the time of two NOP instructions dosprog пишет: Вообще, такие вопросы сродни интересу к сигнатуре "MZ" - "почему-да-как?". Изначально сделали так, а потом изменять это не было нужды. Вопрос возник из-за необходимости патчить несколько интересующих меня WinAPI-функций. Наткнулся, погуглил, не понял причину, решил спросить, чтобы случайно не облажаться на ровном месте. ![]() |
|
Создано: 17 июня 2015 23:20 · Личное сообщение · #10 b0r3d0m пишет: просто возвращаем изначальные байты Ну это один из вариантов. Можно и так! Но если первая MOV EDI, EDI -тогда ничего не нужно восстанавливать и эмулировать. b0r3d0m пишет: использовать же их можно Там обычно мизер остаетс. Впрочем, вроде слышал, что в некоторых библиотеках такой подход встречается. Но не у микрософт. Если поставить громадное выравнивание в байт 16, тогда наверняка можно. Но это всё дело вкуса. ![]() |
|
Создано: 17 июня 2015 23:21 · Личное сообщение · #11 |
|
Создано: 17 июня 2015 23:22 · Личное сообщение · #12 |
|
Создано: 17 июня 2015 23:25 · Личное сообщение · #13 Я ссылку на перехват: jmp моя процедура jmp -5 Начало реальной процедуры делаю через WriteProcessMemory с ProcessID = -1 ----- StarForce и Themida ацтой! ![]() |
|
Создано: 17 июня 2015 23:27 · Личное сообщение · #14 |
|
Создано: 17 июня 2015 23:28 · Личное сообщение · #15 |
|
Создано: 17 июня 2015 23:28 · Личное сообщение · #16 Maximus пишет: Я ссылку на перехват Ну, т.е. Вы о том, что возвращать обратно изначальную реализацию нет особой необходимости в таком случае, да? hello пишет: Но если первая MOV EDI, EDI -тогда ничего не нужно восстанавливать и эмулировать Да, но только в том случае, если мы уместим наш JMP в два байта, что можно сделать только в ситуациях, подобных JMP $-5, что Вас же и не устраивает: > Там обычно мизер остаетс. Впрочем, вроде слышал, что в некоторых библиотеках такой подход встречается. Но не у микрософт ![]() |
|
Создано: 17 июня 2015 23:30 · Поправил: dosprog · Личное сообщение · #17 b0r3d0m пишет: чтобы случайно не облажаться на ровном месте. Надо пробовать. Облажаетесь - вернёте всё на место. ![]() |
|
Создано: 17 июня 2015 23:31 · Личное сообщение · #18 |
|
Создано: 17 июня 2015 23:32 · Личное сообщение · #19 Ну, т.е. Вы о том, что возвращать обратно изначальную реализацию нет особой необходимости в таком случае, да? Да, достаточно получить адрес процедуры MessageBox и прибавить к этому адресу 2 (пропускаем jmp-5) и каждый раз возвращать процедуру в исходное состояние не нужно. ----- StarForce и Themida ацтой! ![]() |
|
Создано: 17 июня 2015 23:35 · Личное сообщение · #20 Maximus пишет: Да, достаточно получить адрес процедуры MessageBox и прибавить к этому адресу 2 (пропускаем jmp-5) и каждый раз возвращать процедуру в исходное состояние не нужно Спасибо. А RET после безусловного перехода для чего делался в изначальном примере, не подскажете? dosprog пишет: Надо пробовать. Облажаетесь - вернёте всё на место Уже попробовал, просто было интересно, как и почему лучше делать. ![]() |
|
Создано: 17 июня 2015 23:43 · Поправил: Maximus · Личное сообщение · #21 |
|
Создано: 17 июня 2015 23:45 · Личное сообщение · #22 |
|
Создано: 17 июня 2015 23:53 · Личное сообщение · #23 |
![]() |
eXeL@B —› Вопросы новичков —› Зачем нужна инструкция MOV EDI,EDI |