Самый простой способ сделать это - использовать то, что называется «Software Dynamic Translation». Вы можете найти некоторую информацию о технике здесь:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.120.5182&rep=rep1&type=pdf
Он работает путем динамического перевода «базовых блоков», когда вы переводите все инструкции вплоть до контрольной точки (ветвление, вызов, переход), а затем заменяете код в целях ветвления заглушками, которые вызывают обратный вызов в переводчике. Он примерно эквивалентен чему-то вроде «JIT-компиляции» в CLR, за исключением того, что он работает на более детальном уровне (базовые блоки вместо методов). Это выгодно по сравнению с подходами статического перевода, потому что оно не зависит от точной разборки. Получение идеальной разборки невозможно (это эквивалентно проблеме остановки). Даже у действительно хороших дизассемблеров, таких как IDA pro, могут возникнуть проблемы с идентификацией таких вещей, как обработчики исключений, и они часто путают код с данными.
Программный динамический перевод, однако, не подпадает ни под одно из этих ограничений. Он может даже (теоретически) обрабатывать самоизменяющийся код, используя соответствующие методы защиты памяти.