внедряю в другой x64-процесс x64-exe файл, настраиваю ему релоки, импорты... вызываю точку входа внутри чужого процесса с помощью кода: Код (Text): nop mov rax, EntryPoint call rax возникает эксес вайолейтинг внутри точки входа, глубоко после вызова MessageBox где-то в библиотеке lkp.dll... что в принципе странно, так как если делать CreateRemoteThread на EntryPoint, а не на код, то все прекрасно работает... более того, если тоже самое проделать в контексте текущего процесса (CreateThread на такой же код), то все так же прекрасно отрабатывает... x86-exe файл с аналогичным кодом тоже исполняется без проблем, как в текущем, так и в чужом процессе... сделал вывод, что вызов кодом что-то портит в стеке, но не могу понять что, и как... подскажите пожалуйста в чем может быть проблема?
Предположу что адрес возврата остается в стэке и может как-то влияет. Сделай переход на OEP так: push EntryPoint ret либо nop mov rax, EntryPoint jmp rax
Правильно предполагаешь. А если быть точнее то это обусловлено новыми соглашениями по передаче аргументов.
спасибо, но можно поподробнее объяснить, почему адрес возврата может портить стек... дело в том, что после ret из EntryPoint поток должен вернуться на код с которого он стартовал (на инструкцию следующую за call rax)... далее за call rax происходит вызов ExitThread, это сделано для контроля того, что поток может уйти неизвестно куда, если PE-файл собирался с какой-нить левой CRT или если это вообще не PE-файл, а какой-нить независимый от базы кодец... соответственно EntryPoint во всех случаях без параметров, но если PE-файл является DLL, то в этом случае - три параметра (передаются через RCX, EDX, R8)...
Значит подробнее. 1. Перед вызовом функции т. е. непосредственно перед call`oм стэк должен быть выравнен на границу 16-байт. 2. При написании программ на ассемблере становиться необходимым использование хорошо продуманного пролога и эпилога плюс макроса invoke. Я подчёркиваю что это именно минимум, если ты пытаешься написать, что-нибудь отличное Хеллоу Ворлда на Месседж Боксе. Также я видел что упаковщики сохраняют значения всех 16 регистров push/pop`aми.
да... большое спасибо! я по глупости упустил этот момент из виду... теперь перед вызовом делаю sub rsp, 8... на первичных тестах работает, как надо... это да, но все PE-файлы, что я гружу компилируются студией, то есть фактически мне важно чтобы стек был выровнен до вызова EntryPoint, далее вопросы вызова уже решены компилятором...