Эмулятор под Linux
Posted: Tue Oct 09, 2007 11:43 am
Я - виндоузятник. В качестве такового я написал известный, думаю, абсолютному большинству участников этого форума эмулятор KlbrInWin (который, кстати, считаю своей лучшей программой). С Linux'ом я связываюсь только если я вынужден это сделать либо мне за это платят. Так что чего-нибудь похожего под Linux я писать не собираюсь.
Тем не менее я признаю право на существование линуксоидов. На этом форуме таковые, насколько я знаю, есть. Кроме того, я считаю себя крутым системным программистом (не без оснований). Какое-то время назад я придумал (основываясь на знаниях, полученных в общем-то случайно) метод эмуляции Колибри-бинарников под Linux (в смысле, решение двух основных проблем: загрузки бинарника по нулевому адресу и перехвата int 0x40, причём без полной эмуляции процессора, требующей дополнительно кучи усилий по кодированию и тормозящей). Поскольку сам я этим пользоваться не собираюсь, то потратил некоторое количество времени на написание работающего примера (писал, естественно, под виндой) и комментариев к коду (предупреждение: комментарии у меня по жизни получаются плохо, но я старался) и теперь предлагаю любому, кто захочет, изучить этот пример и заняться на его базе разработкой.
1. Запуск с нулевого адреса. Идея в том, что "настоящий" адрес программы ненулевой, но можно исполнять программу с не-плоскими cs,ds,es,ss: создать дескриптор в LDT с базой, равной "настоящему" адресу, по которому загружена Колибри-программа, и лимитом, равным размеру памяти, требуемой Колибри-программе. LDT можно модифицировать системным вызовом sys_modify_ldt, для которого в libc есть обёртка modify_ldt. Фактически требуются два дескриптора: для кода и для данных. Передача управления делается ассемблерной вставкой.
2. Перехват int 0x40. В Linux int 0x40 означает исключение #GP, которое Linux обрабатывает как сигнал SIGSEGV. Можно установить свой обработчик сигнала через sys_sigaction - аналог в libc называется sigaction. Только при этом нужно во флагах структуры sigaction установить флаг SS_ONSTACK и определить через sys_sigaltstack - обёртка в libc именуется sigaltstack, можно также sigstack - стек, на который будет переключение при вызове обработчика, конкретно область памяти размера минимум 2 Кб (рекомендуется, скажем, 32 Кб), которая станет стеком обработчика.
http://diamondz.land.ru/linuxemuldemo.7z
Примечания:
1. Поскольку на моём компе Linux существует только в виде мини-образа под Bochs и исходников ядра, то Си-компилятора, способного генерировать ELF, у меня нет, равно как и заголовочных файлов. Так что пример написан на FASM'е и системных вызовах. Надеюсь, впрочем, что основные идеи оттуда всё же можно понять.
2. Пример для простоты не мучается с загрузкой Колибри-бинарника и файлов вообще, а эмулируемый код включается как файл. Он начинается с сигнатуры "MENUET01", а точкой входа считается смещение 8 (сразу после сигнатуры).
3. Я тестировал этот код в вышеупомянутом мини-образе, а также на двух различных реальных Linux-системах (причём ни в одной их этих систем прав root'а у меня не было совсем), одной древней и одной относительно новой. Работало.
Организационные замечания:
1. В теме про KlbrInWin довольно давно O01eg заявил, что написал бы эмулятор при условии решения двух вышеупомянутых проблем. Когда я придумал вышеупомянутый способ, я сообщил об этом O01eg'у (было это пару месяцев назад). В ответном сообщении было сказано, что он от своих слов не отказывается, но Linux временно не работает из-за проблем с железом. Так что, возможно, эмулятор уже пишется, а я тут своим постом весь сюрприз сбиваю. В таком случае прошу прощения и обращаю внимание форума на приоритет O01eg'а.
2. Когда меня на этом форуме ещё не было, а MeOSEmul (Windows-эмулятор, решающий вышеупомянутые проблемы эмуляцией процессора) был ещё жив, в соответствующей теме был вопрос о портировании под Linux, тем более что эмуляция процессора системно-независима. Тогда за это никто не взялся. С того времени прошло несколько лет, на форуме появилось много народу (в том числе добавилось несколько активных людей), а некоторые, возможно, изменили своё отношение к этой оси и уж точно изменили приоритеты задач. Возможно, в этот раз ситуация всё-таки изменится к лучшему?
3. Может быть, кто-то один захочет взяться за написание эмулятора целиком. Может быть, вы (линуксоиды) решите разделить работу. (системных функций в Колибри много...) Может быть, никто не захочет ничего делать. Пожалуйста (мне-то что?). Для координации действий предлагаю использовать эту тему.
Тем не менее я признаю право на существование линуксоидов. На этом форуме таковые, насколько я знаю, есть. Кроме того, я считаю себя крутым системным программистом (не без оснований). Какое-то время назад я придумал (основываясь на знаниях, полученных в общем-то случайно) метод эмуляции Колибри-бинарников под Linux (в смысле, решение двух основных проблем: загрузки бинарника по нулевому адресу и перехвата int 0x40, причём без полной эмуляции процессора, требующей дополнительно кучи усилий по кодированию и тормозящей). Поскольку сам я этим пользоваться не собираюсь, то потратил некоторое количество времени на написание работающего примера (писал, естественно, под виндой) и комментариев к коду (предупреждение: комментарии у меня по жизни получаются плохо, но я старался) и теперь предлагаю любому, кто захочет, изучить этот пример и заняться на его базе разработкой.
1. Запуск с нулевого адреса. Идея в том, что "настоящий" адрес программы ненулевой, но можно исполнять программу с не-плоскими cs,ds,es,ss: создать дескриптор в LDT с базой, равной "настоящему" адресу, по которому загружена Колибри-программа, и лимитом, равным размеру памяти, требуемой Колибри-программе. LDT можно модифицировать системным вызовом sys_modify_ldt, для которого в libc есть обёртка modify_ldt. Фактически требуются два дескриптора: для кода и для данных. Передача управления делается ассемблерной вставкой.
2. Перехват int 0x40. В Linux int 0x40 означает исключение #GP, которое Linux обрабатывает как сигнал SIGSEGV. Можно установить свой обработчик сигнала через sys_sigaction - аналог в libc называется sigaction. Только при этом нужно во флагах структуры sigaction установить флаг SS_ONSTACK и определить через sys_sigaltstack - обёртка в libc именуется sigaltstack, можно также sigstack - стек, на который будет переключение при вызове обработчика, конкретно область памяти размера минимум 2 Кб (рекомендуется, скажем, 32 Кб), которая станет стеком обработчика.
http://diamondz.land.ru/linuxemuldemo.7z
Примечания:
1. Поскольку на моём компе Linux существует только в виде мини-образа под Bochs и исходников ядра, то Си-компилятора, способного генерировать ELF, у меня нет, равно как и заголовочных файлов. Так что пример написан на FASM'е и системных вызовах. Надеюсь, впрочем, что основные идеи оттуда всё же можно понять.
2. Пример для простоты не мучается с загрузкой Колибри-бинарника и файлов вообще, а эмулируемый код включается как файл. Он начинается с сигнатуры "MENUET01", а точкой входа считается смещение 8 (сразу после сигнатуры).
3. Я тестировал этот код в вышеупомянутом мини-образе, а также на двух различных реальных Linux-системах (причём ни в одной их этих систем прав root'а у меня не было совсем), одной древней и одной относительно новой. Работало.
Организационные замечания:
1. В теме про KlbrInWin довольно давно O01eg заявил, что написал бы эмулятор при условии решения двух вышеупомянутых проблем. Когда я придумал вышеупомянутый способ, я сообщил об этом O01eg'у (было это пару месяцев назад). В ответном сообщении было сказано, что он от своих слов не отказывается, но Linux временно не работает из-за проблем с железом. Так что, возможно, эмулятор уже пишется, а я тут своим постом весь сюрприз сбиваю. В таком случае прошу прощения и обращаю внимание форума на приоритет O01eg'а.
2. Когда меня на этом форуме ещё не было, а MeOSEmul (Windows-эмулятор, решающий вышеупомянутые проблемы эмуляцией процессора) был ещё жив, в соответствующей теме был вопрос о портировании под Linux, тем более что эмуляция процессора системно-независима. Тогда за это никто не взялся. С того времени прошло несколько лет, на форуме появилось много народу (в том числе добавилось несколько активных людей), а некоторые, возможно, изменили своё отношение к этой оси и уж точно изменили приоритеты задач. Возможно, в этот раз ситуация всё-таки изменится к лучшему?
3. Может быть, кто-то один захочет взяться за написание эмулятора целиком. Может быть, вы (линуксоиды) решите разделить работу. (системных функций в Колибри много...) Может быть, никто не захочет ничего делать. Пожалуйста (мне-то что?). Для координации действий предлагаю использовать эту тему.