[Assembler] Самомодифицирущийся код
А можно получить адрес этой на ассемблере написанной проги? Попробуй писать по тому адресу, естественно с необходимым смещением. Однако сразу оговорюсь, сам именно этого не пробовал, да и винда может это запретить. Но попробовать можно 

Это во время работы программы нужно делать?
Если да, то под виндами по-моему нельзя этого делать.
Если да, то под виндами по-моему нельзя этого делать.
да, нужно заменить код runtime
Переформулирую задачу: нужно выполнить код, находящийся в массиве. Необязательно записывать его поверх чего-либо.
на стеке можно попробовать, хотя тут NX помешать может
Содержимое массива будет меняться динамически так понимаю?
Кажись нельзя. Это типа одна из защит в виндовс.
Щас поищу, где-то у меня на эту тему было несколько статей.
Кажись нельзя. Это типа одна из защит в виндовс.
Щас поищу, где-то у меня на эту тему было несколько статей.
Это во время работы программы нужно делать?
Если да, то под виндами по-моему нельзя этого делать
Ну да, конечно. А как по-твоему работает JIT-компилятор у Java и .Net?
Переформулирую задачу: нужно выполнить код, находящийся в массиве. Необязательно записывать его поверх чего-либо.Вот такую задачу я решал, правда на Дельфи под ВинХР64. Я тестил как у них DEP работает. Действительно работает
То есть если он включен, то шансов - около нуля, но ведь DEP можно и выключить, тогда все работает как по маслу.
Ну да, конечно. А как по-твоему работает JIT-компилятор у Java и .Net?Понятия не имею, с ними никогда не работал.
Вот выдержка из одного довольно старого документа о вирусах.
Самая главная фишка.
Заключается в том, что для каждой страницы существует так называемый уровень доступа. В win32 всего два уровня защиты: ring-3 (юзер) и ring-0 (ядро). Находясь в ring-0 свершенно наплевать какой уровень доступа у какой страницы -- все их (подгруженные) можно без проблем читать и писать.
А вот для ring-3 есть несколько вариантов:
1. страницы для чтения и записи (read-write)
2. страницы только для чтения (read-only)
3. хуй (ни читать ни писать в такие страницы нельзя)
4. комбинации вышеперчисленных с испольнябельностью (executable а также guard, writecopy и еще хер знает что -- скорее всего ничего их этого вам не встретится.
Идея в том, что кодовые страницы в системе помечаются как read-only, и поэтому их можно исполнять и читать, а вот писать в них нельзя. Это в основном страницы кода в kernel'е и в ваших PE-файлах. Проблема с PE-файлами решается добавленим нужного бита в ObjectTable при заражении файла, либо через VirtualProtect/WriteProcessMemory; проблема с kernel'ами и системными хернями решается (под маздаем) несколько более хитрыми приемами.
Под POSIX вот:
под виндой наверняка есть аналог mmap'а.
#include <stdio.h>
#include <sys/mman.h>
typedef int function_t ;
int
main
{
char * sample_code = "\xB8\x01\x00\x00\x00\xC3";
function_t * function;
char * code;
function = code = mmap (0, 6, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
memcpy (code, sample_code, 6);
printf ("%d\n", (* function) ;
code [1] = 2;
printf ("%d\n", (* function) ;
}
под виндой наверняка есть аналог mmap'а.
> Кажись нельзя. Это типа одна из защит в виндовс.
и как по твоему всякие exepack-и работают? или asprotect-ы? или хотя бы полиморфные вирусы?
ps
VirtualAlloc
VirtualProtect
и как по твоему всякие exepack-и работают? или asprotect-ы? или хотя бы полиморфные вирусы?
ps
VirtualAlloc
VirtualProtect
Ты можешь более внятно объяснить, что именно тебе нужно?
Если у тебя есть ИСХОДНИК программы, почему бы не заменить код в исходнике и перекомпилить?
Если тебе важно генерить код динамически - все вызовы исходной функции заменяешь на вызовы специальной заглушки, которая передаст управление в массив, в который ты динамически напихаешь всё что нужно. Если ты ещё хочешь, чтобы DEP не сругнулся, читай советы выше.
В некоторых случаях наиболее простым будет вынести изменяемый код в дллку, которую грузить динамически.
Если ты хочешь устроить кому-нибудь смешное западло, есть гораздо более простые способы, типа грамотного #DEFINE.
Если у тебя есть ИСХОДНИК программы, почему бы не заменить код в исходнике и перекомпилить?
Если тебе важно генерить код динамически - все вызовы исходной функции заменяешь на вызовы специальной заглушки, которая передаст управление в массив, в который ты динамически напихаешь всё что нужно. Если ты ещё хочешь, чтобы DEP не сругнулся, читай советы выше.
В некоторых случаях наиболее простым будет вынести изменяемый код в дллку, которую грузить динамически.
Если ты хочешь устроить кому-нибудь смешное западло, есть гораздо более простые способы, типа грамотного #DEFINE.
нужно защитить программу с помощью электронного ключа. Я хочу хранить часть кода на этом ключе.
Вот выдержка из одного довольно старого документа о вирусах.это не документ времён 9х винды?
Вроде NT работает в 3х или 4х кольцах.
и как по твоему всякие exepack-и работают? или asprotect-ы? или хотя бы полиморфные вирусы?ладно, ладно... уговорили =)
так и есть
В этом нет смысла - такое действие не улучшит криптографических свойств ключа (если ключ простой, то есть не реализует криптоалгоритмов).
Можно заменить асмовскую процедуру на написанную на скриптовом языке и сложить программу на нем в ключ. Но все эти пути - потенциальная дырка в программе, не зря же все эти NX придумывали.
Можно заменить асмовскую процедуру на написанную на скриптовом языке и сложить программу на нем в ключ. Но все эти пути - потенциальная дырка в программе, не зря же все эти NX придумывали.
Смысл есть вот какой: при таком подходе кулхацкер уже не сможет найти все вызовы функции "проверить валидность ключа" и заменить их на нопы (что как правило и делается). Так же не будет никакого смысла в реверс-инжиниринге фунцкии "проверить валидность ключа" с целью написать кейген - ведь фактически в таком случае проверка валидности оказывается неявно размазана по всей программе.
Таким образом, у кулхацкера остаётся всего две возможности -
1) угадать, что именно делает отсутствующая процедура и написать её заново (нереально, скорее всего)
2) купить программу и выдрать из ключа процедуру.
Причём с пунктом 2 можно побороться вообще забавным образом - написать генератор процедур (ну, там, если используются какие-то константы, то их можно как-то хитроумно менять, не меняя семантики) так, чтобы по появившемуся вдруг в сети крэку/кейгену можно было определить, какой именно зарегистрированный пользователь отдал свой ключ на поругание.
Правда, в таком случае опять-таки возникает соблазн не мучаться со всей этой фигнёй и оформить "ключ" в виде дллки. Почему бы и нет?
Таким образом, у кулхацкера остаётся всего две возможности -
1) угадать, что именно делает отсутствующая процедура и написать её заново (нереально, скорее всего)
2) купить программу и выдрать из ключа процедуру.
Причём с пунктом 2 можно побороться вообще забавным образом - написать генератор процедур (ну, там, если используются какие-то константы, то их можно как-то хитроумно менять, не меняя семантики) так, чтобы по появившемуся вдруг в сети крэку/кейгену можно было определить, какой именно зарегистрированный пользователь отдал свой ключ на поругание.
Правда, в таком случае опять-таки возникает соблазн не мучаться со всей этой фигнёй и оформить "ключ" в виде дллки. Почему бы и нет?
такая реализация - не лучший вариант. большую процедуру ты на асме в ключ не засунешь, тем более что-то серьезное. и ее можно будет поймать, если отслеживать, как прога работает с памятью
Избыточность asm кода довольно велика, поэтому не разумно его использовать в качестве ключа
В качестве секретных данных можно использовать либо достаточно большой набор данных, необходимых для работы программы, которые надо расшифровывать ключом из "ключа", либо некоторый псевдокод, который легко контролировать и придавать ему специальные свойства.
что касается кул-хацкеров:
1) реверс инжиниринг нормально реализованного криптоалгоритма ничего не даст
2) с помощью пассивных флешек здесь бороться не получится - нужно чтобы этот код не только хранился в флешке но еще и исполнялся там, кстати - видел проекты обеспечения DRM с помощью таких чипов, вклеивающихся в лицензионные диски
В качестве секретных данных можно использовать либо достаточно большой набор данных, необходимых для работы программы, которые надо расшифровывать ключом из "ключа", либо некоторый псевдокод, который легко контролировать и придавать ему специальные свойства.
что касается кул-хацкеров:
1) реверс инжиниринг нормально реализованного криптоалгоритма ничего не даст
2) с помощью пассивных флешек здесь бороться не получится - нужно чтобы этот код не только хранился в флешке но еще и исполнялся там, кстати - видел проекты обеспечения DRM с помощью таких чипов, вклеивающихся в лицензионные диски
под винды можно так.
ибо исполняться в стеке никто не запрещал
char * sample_code = "\x33\B\xF7\xFB\xC3";
unsigned long address = (unsigned longsample_code);
__asm
{
xor eax,eax
mov eax, [address]
call eax
}
//---33DB xor ebx, ebx
//---F7FB idiv ebx
//---C3 ret
//Unhandled exception at 0x004240ca in test2.exe: 0xC0000094: Integer division by zero.
ибо исполняться в стеке никто не запрещал
ибо исполняться в стеке никто не запрещалА вот это зря. Допускает security violation при любом срыве стека.
К сожалению, большинство операционок обладает такой багой.
Где-то полтора года назад была статья Криса Касперского на сайте void.ru по защите программ от отладчиков и интерактивных дизассемблеров - там прога, если не ошибаюсь, проверяла свою целостность и модифицировала свой код. Может поможет.
Это фича. Трамплины можно делать.
Можно, понятно, и в куче, но это дольше, и срыв кучи немногим лучше срыва стека.
Можно, понятно, и в куче, но это дольше, и срыв кучи немногим лучше срыва стека.
Это фича. Трамплины можно делать.
Поясни
Можно, понятно, и в куче, но это дольше, и срыв кучи немногим лучше срыва стека.
Конечно, срыв кучи тоже плохо. Но, если куча (или стек) без права выполнения, то arbitrary code при срыве не запустишь и взломать до рутового шела становится сложнее. А то, что срыв -- это вина автора проги, так с этим никто не спорит. Просто более секъюрны системы, которые запрещают выполнение в стеке.
Что пояснить? Что такое трамплин?
> Просто более секъюрны системы, которые запрещают выполнение в стеке.
Только пока они в меньшинстве.
Если в мейнстрим пройдёт такое (а сейчас проходит уже не факт.
> Просто более секъюрны системы, которые запрещают выполнение в стеке.
Только пока они в меньшинстве.
Если в мейнстрим пройдёт такое (а сейчас проходит уже не факт.
Что пояснить? Что такое трамплин?
Да, я единственное упоминание видел в исходниках linux'а. Там так называется процедура, которая стартует всё остальное.
GCC умеет вложенные функции. Если взять на такую функцию указатель, получается фактически closure. Для его получения на стек кладётся динамически сгенерированный код, который и называется трамплином.
В языках с GC тоже можно, в принципе, реализовывать так closure, но тогда в куче придётся делать, а не на стеке (хотя, если escape analisys показывает, что можно на стеке - то будет эффективнее именно там).
В языках с GC тоже можно, в принципе, реализовывать так closure, но тогда в куче придётся делать, а не на стеке (хотя, если escape analisys показывает, что можно на стеке - то будет эффективнее именно там).
Прикольно, я правда не придумал для чего вложенные функции и передача наружу указателей на них могли бы мне пригодиться, но всё равно прикольно. А точно нельзя это реализовать без executable stack?
Оставить комментарий
Corrector
Имеется исходник программы, написанная на си под винду. Одна из её функций - на чистом ассемблере. Нужно до вызова этой функции заменить команды этой функции на другие, опкоды которых берутся из массива. Как записать поверх одного кода другой?