> Итак, как можно видеть, открывается дескриптор процесса > RegEdit. В нём выделяется память под поток. Копируется в > эту память исполняемый код потока. Запускается поток на > выполнение. Работает допущение, что базовый адрес, куда > загружен Kernel32 в чужом процессе и в моём одинаковые. > Вопросы: > 1) Существует ли более-менее "человеческий" способ > определения размера исполняемого кода — или заходить в > дебуггер и вручную его считать.
void F1() {}
void F2() {}
int SizeOfF1 = (int)F2 - (int)F1;
> 2) В этом простейшем случае инструкции в потоке идут одна > за другой. Надо думать, что с появлением ветвлений, циклов > и т.п., компилятор Delphi, "думая", что компилит для > "родного" процесса, будет ставить > абсолютные адреса переходов для > ветвлений. Можно ли как-нибудь исхитриться и задать > относительные? И вообще, возможно ли такое без применения > in-line ассемблера?
А по-моему, для ветвлений, циклов и т.п большинство компиляторов (VC и Delphi в том числе) генерят относительные переходы...
> 3) Почему компилятор генерит такой код возврата из функции, > помеченной как Stdcall: RET $0004. Я на всякий случай > поставил просто RET. Как более правильно, поскольку что > так, что эдак работает ;-)
Должно быть retn 4. Раз ф-я stdcall и принимает 1 параметр, она по возвращении сама должна снять со стека 4 байта. Мне вообще не понятно, зачем нужен этот код (и без него должно работать):
ASM // Correct return throm tread
POP EBP
RET
END;
К тому же этот код зависит от конкретного компилятора: компилятор может и не положить в стек EBP (или наоборот, кроме EBP в стеке может оказаться еще что-нибудь).
> И вообще, может я делаю что-то через задницу? ;-)) Что > лучше всего использовать для создания кода, который будет > исполняться в другом процессе? > Всем спасибо, жду ответов.
Посмотри в книге Рихтера - он с помощью CreateRemoteThread загружает в чужой процесс свою DLL. Вызывая CreateRemoteThread, ей качестве threadfunc передает адрес LoadLibrary (раз Kernel32 в другом процессе загружен по тому же адресу), а в качестве параметра - адрес строки "c:\mydll.dll" (перед этим ее надо поместить в адресное пространство чужого процесса).
Ну вот, доигрался. Не хватает мне возможностей моего любимого компилера. Что делать? Ума не преложу. Неужели на Asm писать весь код?
Итак, проблема. Нужно кое-что поделать в адресном пространстве запущенного приложения — к примеру, RegEdit.
Вот код примера, а конкретные вопросы смотрите после ;-)
--- Итак, как можно видеть, открывается дескриптор процесса RegEdit. В нём выделяется память под поток. Копируется в эту память исполняемый код потока. Запускается поток на выполнение. Работает допущение, что базовый адрес, куда загружен Kernel32 в чужом процессе и в моём одинаковые.
Вопросы:
1) Существует ли более-менее "человеческий" способ определения размера исполняемого кода — или заходить в дебуггер и вручную его считать.
2) В этом простейшем случае инструкции в потоке идут одна за другой. Надо думать, что с появлением ветвлений, циклов и т.п., компилятор Delphi, "думая", что компилит для "родного" процесса, будет ставить абсолютные адреса переходов для ветвлений. Можно ли как-нибудь исхитриться и задать относительные? И вообще, возможно ли такое без применения in-line ассемблера?
3) Почему компилятор генерит такой код возврата из функции, помеченной как Stdcall: RET $0004. Я на всякий случай поставил просто RET. Как более правильно, поскольку что так, что эдак работает ;-)
И вообще, может я делаю что-то через задницу? ;-)) Что лучше всего использовать для создания кода, который будет исполняться в другом процессе?
Всем спасибо, жду ответов.
> Итак, как можно видеть, открывается дескриптор процесса > RegEdit. В нём выделяется память под поток. Копируется в > эту память исполняемый код потока. Запускается поток на > выполнение. Работает допущение, что базовый адрес, куда > загружен Kernel32 в чужом процессе и в моём одинаковые. > Вопросы: > 1) Существует ли более-менее "человеческий" способ > определения размера исполняемого кода — или заходить в > дебуггер и вручную его считать.
void F1() {}
void F2() {}
int SizeOfF1 = (int)F2 - (int)F1;
> 2) В этом простейшем случае инструкции в потоке идут одна > за другой. Надо думать, что с появлением ветвлений, циклов > и т.п., компилятор Delphi, "думая", что компилит для > "родного" процесса, будет ставить > абсолютные адреса переходов для > ветвлений. Можно ли как-нибудь исхитриться и задать > относительные? И вообще, возможно ли такое без применения > in-line ассемблера?
А по-моему, для ветвлений, циклов и т.п большинство компиляторов (VC и Delphi в том числе) генерят относительные переходы...
> 3) Почему компилятор генерит такой код возврата из функции, > помеченной как Stdcall: RET $0004. Я на всякий случай > поставил просто RET. Как более правильно, поскольку что > так, что эдак работает ;-)
Должно быть retn 4. Раз ф-я stdcall и принимает 1 параметр, она по возвращении сама должна снять со стека 4 байта. Мне вообще не понятно, зачем нужен этот код (и без него должно работать):
ASM // Correct return throm tread
POP EBP
RET
END;
К тому же этот код зависит от конкретного компилятора: компилятор может и не положить в стек EBP (или наоборот, кроме EBP в стеке может оказаться еще что-нибудь).
> И вообще, может я делаю что-то через задницу? ;-)) Что > лучше всего использовать для создания кода, который будет > исполняться в другом процессе? > Всем спасибо, жду ответов.
Посмотри в книге Рихтера - он с помощью CreateRemoteThread загружает в чужой процесс свою DLL. Вызывая CreateRemoteThread, ей качестве threadfunc передает адрес LoadLibrary (раз Kernel32 в другом процессе загружен по тому же адресу), а в качестве параметра - адрес строки "c:\mydll.dll" (перед этим ее надо поместить в адресное пространство чужого процесса).
Понятно, спасибо. Про DLL я понимаю что будет клёво работать, просто мне была интересна идея работы "впрыскивания кода" в чужой процесс. "Чисто впрыснутый" поток трудно отследить ;-)27.10.02 19:17 Автор: HandleX <Александр М.> Статус: The Elderman