Что такое пещера кода, и есть ли какое-либо законное использование для нее?
Я впервые столкнулся с этим словом в вопросе StackOverflow"C# теоретический: напишите JMP в кодекаве в asm.- Я вижу это по Wiktionary, пещера код:
неиспользуемый блок памяти, который кто-то, как правило, взломщик программного обеспечения, может использовать для инъекции пользовательский программный код для изменения поведения программы.
нашел ли я правильное определение? Если да, то есть ли законное применение для кодовой пещеры?
9 ответов
я использовал их, хотя я никогда не слышал термин пещера код до сегодняшнего дня. Определение Wiktionary предполагает, что пещера кода-это то, что взломщик находит в исполняемом файле, который он или она пытается взломать. Вопрос, который вы цитируете, не использует его таким образом. Вместо этого он предполагает, что пещера кода выделяется с VirtualAllocEx
создать новый блок памяти в целевом процессе. Это устраняет необходимость поиска неиспользуемого пространства в цели и гарантирует, что вы есть достаточно места, чтобы поместить весь ваш новый код.
в конечном счете, я думаю "пещера кода" -это просто место для хранения кода, сгенерированного во время выполнения. В этом кодексе не должно быть никакой гнусной цели. И в этот момент вопрос о том, что такое кодовая пещера, становится совершенно неинтересным. Интересные части - это причины создания кода во время выполнения и методы, позволяющие убедиться, что новый код запускается, когда вы этого хотите.
можно было бы намеренно создать пещеру кода в рамках использования самомодифицирующийся код.
предполагая, конечно, что это безумие.
пещеры кода обычно создаются компиляторами для трассы и часто расположены между функциями в огромных количествах. Также должны быть кодовые пещеры между структурами и переходами (в некоторых архитектурах), но обычно не в значительных количествах.
вы также можете искать блок обнуленной памяти, но нет никакой гарантии, что программа не будет их использовать.
Я полагаю, теоретически, если вы потеряли исходный код, вы можете исправить свой багги программы, используя их, и ваша программа не будет расти в размерах.
редактировать
для тех из вас, кто предлагает пещеры кода, предназначены только для кода, генерируемого во время выполнения: это неполное определение. Много раз я писал структуру данных в "пещере кода" и обновлял указатели, чтобы указать туда, и я подозреваю, что я не единственный человек, который это делает.
некоторые законные использует: исправление двоичных файлов Live OS без перезагрузки (MS делает это), подключение низкоуровневых функций ОС (файловая система, сеть) для брандмауэра и антивируса, расширение приложения, когда у вас нет исходного кода (например, очистка низкоуровневых вызовов ОС для DrawText, чтобы вы могли читать их вслух для слепых)
незнакомый с термином, но механизмы горячего исправления могут использовать зарезервированное пространство для хранения исправлений кода. Вы подключаетесь к дефектной функции и перенаправляете ее на новую улучшенную функцию. Это можно сделать на лету, не снимая критическое оборудование (большие телекоммуникационные коммутаторы).
его можно использовать для вставки кода во время выполнения. Его можно использовать для написания самомодифицирующегося кода на статических языках, предполагая, что ОС позволяет вам (NX бит не установлен и т. д.). Есть использование для него, но это не то, о чем вы должны думать в своем типичном бизнес-приложении.
звучит как правильное определение для меня.
нет никакого способа, чтобы этот тип вещей должен когда-нибудь перейти в производственный код:
- это огромная потенциальная проблема безопасности. Если можно ввести код в память, а затем выполнить его, a злоумышленник теоретически может делать, Ну, все, что угодно.
- это кошмар обслуживания кода и кошмар отладки. Если код, который в конечном итоге запускается, может измениться во время выполнения, становится почти невозможно отслеживать ошибки и ошибки.
Самомодифицирующийся код не следует рассматривать легко, но иногда может принести большой прирост производительности. Если вы программируете очень долго, вы, вероятно, использовали его, не осознавая этого.
до широкого использования 486 и выше многие ПК не включали аппаратную плавающую поддержку. Это оставило людей, пишущих программы с плавающей точкой с дилеммой. Если они скомпилировали свою программу для использования встроенных инструкций с плавающей запятой, она будет работать быстро на машина с процессором с плавающей запятой, и совсем не на машинах без одного. Если они скомпилируют свою программу с эмуляцией программного обеспечения с плавающей запятой, она будет работать на всех машинах, но медленно даже на машинах с плавающей запятой.
многие библиотеки компиляторов использовали интересный трюк с самомодифицирующимся кодом. Поведение по умолчанию заключалось в том, чтобы поместить инструкцию trap, где необходима операция с плавающей запятой. Обработчик ловушек будет либо эмулировать инструкцию в программном обеспечении, или, если он обнаружил, что он работает на машине с оборудованием с плавающей запятой, он изменит код, заменив инструкцию trap соответствующей инструкцией с плавающей запятой и выполнит ее. Результатом стало программное обеспечение, которое работало на всех машинах и работало почти так же быстро на машине с оборудованием с плавающей запятой, как если бы код был скомпилирован для использования оборудования с плавающей запятой напрямую (поскольку большинство интенсивных операций с плавающей запятой происходят в циклах, которые выполняются много раз).