C # или C ++ изолированная сборка - PullRequest
0 голосов
/ 20 ноября 2011

Я думаю о написании программы, которая включает в себя сверхбыструю сборку или, поскольку она не должна быть удобочитаемой для человека, это может быть машинный код на C ++ или C #.Однако у меня есть и другие, возможно, более проблематичные требования.

Мне нужно иметь возможность:

  • Хранить программы машинного кода в обычных переменных / экземплярах объектов, например, в строках."40 9B 7F 5F ...", чтобы редактировать и запускать их.

  • Имеют ли программы возможность выводить данные.Я видел пример, где у одного был указатель на int, который он мог бы использовать.

  • У программ не было возможности выводить данные где-либо еще.Например, чтобы не иметь возможности выполнять такие действия, как удаление файлов, просмотреть системные спецификации или изменить состояние памяти программы C ++ или C #, в которой они содержатся.

ДляНапример, это может быть что-то вроде этого:

machine n;
n = "40 9B 7F";
n[1] = "5F";
// 'n' is now "40 5F 7F"
unsigned short s = 2;
n.run(&s);
// while 'n' was running it may have changed 's' but would not have been able to
// change anything else anywhere on the system including in this C++ / C# program

Согласно вики-ссылке Майкл Дорган опубликовал "asm (std :: string);"запускает String как ассемблер, а также легко ссылаться на переменные из C ++ части программы.Редактировать std :: String легко, и Алекс отметил, что я могу гарантировать безопасность кода, не допуская небезопасных команд.

Ответы [ 4 ]

3 голосов
/ 20 ноября 2011

Песочница родного машинного кода нетривиальна. Если вы действительно хотите это, взгляните на NACL от Google, который реализует песочницу машинного кода для браузеров.

Более практичным является использование .NET IL вместо машинного кода и использование изолированного (или размещенного) AppDomain. Это происходит намного ближе и все еще быстро благодаря динамической JIT-компиляции в машинный код.

Альтернатива у вас есть - использовать встроенное управление правами Windows и запустить новый процесс с ограниченными правами. Никогда не делал этого, поэтому я не знаю, можете ли вы уменьшить права целевых процессов настолько, насколько вы хотите. В любом случае, это будет чистый процесс win32, просто выполняющий машинный код, так что вы потеряете возможность использовать .NET в изолированном процессе.

2 голосов
/ 20 ноября 2011

Если вы хотите включить ассемблер в свой код C / C ++, подумайте о встроенных процедурах сборки или о компиляции отдельных файлов ассемблера и их последующей компоновке. Синтаксис встроенного ассемблера довольно странный, но я считаю, что он, вероятно, лучшийвыбор из того, что я прочитал.

Википедия, чтобы спасти некоторые образцы:

Примеры встроенного ассемблера

2 голосов
/ 20 ноября 2011

Обновление на основе комментариев:

Это далеко не тривиальная задача.Вы должны реализовать компоновщик, ассемблер (для сканирования и песочницы) и загрузчик.

Интересно, каков вариант использования - для моего примера я предполагаю, что вы хотите устроить конкурс сборки, на котором люди отправляютрешения проблем, и вы их «тестируете».

Это лучшее решение, которое я могу придумать:

  • Иметь хост-программу, которая принимает в качестве входного языка ассемблера.

  • Вызовите ассемблер, чтобы скомпилировать и связать программу сборки.

  • Создать защищенную виртуальную среду для запуска программы (как это сделатьзависит от платформы), которая работает как пользователь, у которого нет прав на систему.

  • Захват результатов

Это решение позволяет использовать существующие ассемблеры, загрузчики и средства безопасности без необходимости их повторной реализации.


Лучший пример кода для динамической загрузки, запуска и песочницы кода C #, который я знаю, - это игра террариумв http://terrarium2.codeplex.com/

Однако вы можете рассмотреть что-то более подходящее для этой работы, например, систему сценариев.Lua приходит на ум как популярный.Используя Lua, пользователи смогут выполнять только те действия, которые вы разрешаете.http://www.lua.org/

1 голос
/ 20 ноября 2011

Если вы ограничите подмножество поддерживаемых инструкций, вы можете делать то, что хотите, более или менее легко.

Во-первых, вы должны проанализировать и декодировать инструкцию ввода, чтобы увидеть, находится ли она в поддерживаемом подмножестве (большая часть синтаксического анализа / декодирования может быть выполнена только один раз). Тогда вам нужно выполнить его.

Но перед выполнением, есть одна важная вещь, о которой нужно позаботиться. Основываясь на декодированных деталях команды и состоянии регистров ЦП, вы должны рассчитать адреса памяти, к которым команда будет обращаться как данные (включая расположения в стеке) или передавать управление. Если какой-либо из них выходит за установленные пределы, срабатывает пожарная сигнализация. В противном случае, если это инструкция передачи управления (например, jmp, jz), вы должны дополнительно убедиться, что адрес, на который она передает управление, находится не только в памяти, где находятся все эти инструкции, но также является адресом одной из этих инструкций и не адрес внутри любого из них (например, 1 или 2 байта от начала инструкции длиной 3+ байта). Передача контроля где-либо еще - нет-нет. Вы не хотите, чтобы эти инструкции передавали управление каким-либо стандартным библиотечным функциям, потому что вы не сможете контролировать их выполнение, и они не всегда безопасны при использовании поддельных / вредоносных входов. Кроме того, эти инструкции не должны быть в состоянии изменить сами.

Если все ясно, вы можете либо эмулировать инструкцию, либо выполнить ее более или менее непосредственно (инструкции по передаче управления, вероятно, придется всегда эмулировать, потому что вы хотите остановить выполнение после каждой инструкции). Для последнего вы можете создать модифицируемую функцию, содержащую эти вещи:

  1. Код для сохранения регистров процессора вызывающей стороны и загрузки их с состоянием для выполняемой инструкции.
  2. Инструкция.
  3. Обратная сторона шага 1: код для сохранения состояния регистра после выполнения и восстановления состояния регистра вызывающей стороны.

Вы можете попробовать этот подход.

...