Пришла идея эмулятора. Позреваю что это банальный велосипед, тогда хочется ссылок или хотя бы названия этой технологии.
Итак. Библиотека эмулятора с поддержкой конвертаци ассемблерного/исполнимого кода в C/C++-подобные исходники. В классе ядра содержатся мемберы-регистры.
Инструкции эмулируются методами. Также имеются контейнеры памяти данных, стека данных, портов и т.д.
Теперь отличие от полной эмуляции: переход осуществляется обычными хостовыми goto. Условный переход — if(the_flag) goto label. Вызов — хостовым вызовом.
Косвенный вызов в принципе можно эмулировать (поможет отображение виртуальных адресов подпрограм в хостовые ).
А вот эмуляция косвенных переходов вызовет сложности (косвенный goto — это нестандартное расширение).
Также вызовет сложности переход на подпрограмму и переход между подпрограммами...
Прошу высказываться.
Модератор-националист Kerk преследует оппонентов по политическим мотивам.
ononim:
BB>>Прошу высказываться. O>тогда уж лучше транслировать в llvm ir.
Бинарь или ассемблер можно оттранслировать в Intermediate Representation?
Да, припоминаю, с чем-то таким экспериментировал, точнее экспериментировал с C++-выхлопом.
На выходе получается полная жесть. Формально это C++, но совершенно не читабельно.
В отличие от сабжа чуть более высокоуровнево. На идею это безусловно повлияло...
ЗЫ. Я этот C++-выхлоп от llvm так и не смог собрать, чего-то не хватало...
Модератор-националист Kerk преследует оппонентов по политическим мотивам.
BB>>>Прошу высказываться. O>>тогда уж лучше транслировать в llvm ir. BB>Бинарь или ассемблер можно оттранслировать в Intermediate Representation?
Ну имхо это будет проще чем на плюсы, как минимум indirect jumps не будут проблемой. А они юзаются достаточно часто — во первых на них делаются jump tables, во вторых (наверно менее важно для древних платформ) indirect sibling calls через них делаются.
BB>ЗЫ. Я этот C++-выхлоп от llvm так и не смог собрать, чего-то не хватало...
Ты не понял. Я предлагаю прямо транслировать бинарь в llvm ir. Минуя С/С++.
Как много веселых ребят, и все делают велосипед...
ononim:
BB>>ЗЫ. Я этот C++-выхлоп от llvm так и не смог собрать, чего-то не хватало... O>Ты не понял. Я предлагаю прямо транслировать бинарь в llvm ir. Минуя С/С++.
Это ты не понял, я предлагаю транслировать бинарь в С/С++.
Нечто среднее между пристёгнутой библиотекой эмуляции и полноценной декомпиляцией с портированием.
Модератор-националист Kerk преследует оппонентов по политическим мотивам.
BB>>>ЗЫ. Я этот C++-выхлоп от llvm так и не смог собрать, чего-то не хватало... O>>Ты не понял. Я предлагаю прямо транслировать бинарь в llvm ir. Минуя С/С++. BB>Это ты не понял, я предлагаю транслировать бинарь в С/С++.
Это то я понял, но транслировать асм в С — это не самое эффективное и безгеморное решение. Лучше уж транслировать в другой асм. Например ллвмовский.
BB>Нечто среднее между пристёгнутой библиотекой эмуляции и полноценной декомпиляцией с портированием.
Нуу, полноценным портированием такой код назвать будет сложно. Результат будет читаем чуть более чем оригинальный асм.
И уж простым то его назвать тем более будет сложно.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Bill Baklushi, Вы писали:
BB>Косвенный вызов в принципе можно эмулировать (поможет отображение виртуальных адресов подпрограм в хостовые ). BB>А вот эмуляция косвенных переходов вызовет сложности (косвенный goto — это нестандартное расширение). BB>Также вызовет сложности переход на подпрограмму и переход между подпрограммами...
Можно сделать большой-большой свитч:
switch(pc) {
case 0: mov(eax, ebx);
case 1: add(esi, eax);
...
}
Тогда последовательное исполнение осуществится само собой, а для косвенного перехода надо засунуть адрес в pc, и перейти к началу свитча. С помощью goto внутри метода это сделать не получится, но можно использовать исключение. Реализацию этого подходя я оставлю в качестве упражнения пытливому читателю.
Здравствуйте, Bill Baklushi, Вы писали:
BB>Прошу высказываться.
A эмуляция x86-кода, на сколько я понял?
У меня был опыт x86-скрипт-эмулятора, который напомнила Ваша тема.
Мне тогда требовалось внедрять x86-код прямо в работающую программу, аналогично «шейдеру»…
Если интересно…
На случай, если Вы только начали развивать концепцию.
Весь код из файла трассировался из x86 и переводился снова в x86 с ограничениями:
Jmp/Jcnd переводились в блочные: jc $+1 — continue if CF; jz $-1 — break if ZF
Регистры ESP/EBP не адресовали стек и участвовали в вычислениях
Абсолютная/индексная адресация отсутствовала
Вместо вектора/смещения использовалось ASCII-кодирование
Здравствуйте, ononim, Вы писали:
O>А как насчет самомодифицируещогся кода? Что как бы не редкость. Впрочем аналогичный вопрос можно ставить ТС.
Ну, можно представить программу в виде массива ссылок на функции. Но тогда исполнение сильно замедлится.
Можно так же разбить ее на блоки, и про каждый блок иметь отметочку, содержит ли он самомодифицированный код. Соответственно, если не содержит, исполнять версию в виде большого свитча, а если нет — в виде массива (по свитчу и по массиву на каждый блок).
ononim:
O>А как насчет самомодифицируещогся кода? Что как бы не редкость. Впрочем аналогичный вопрос можно ставить ТС.
Сабжевый эмулятор рассчитан на "обычный" код, написанный на языке высокого уровня (главным образом на C/C++/Delphi).
Ясно, что простыми антихакерскими, антиотладочными трюками его легко побить.
ИМО, в сях косвенный jmp возникает в основном как реализация некоторых switch, и то в редких случаях.
Такие jmp-ы заворачиваются опять в switch-и.
В случае антиотладочных трюков "декомпилятор" эмулятора фейлится.
Модератор-националист Kerk преследует оппонентов по политическим мотивам.