[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'ами и системными хернями решается (под маздаем) несколько более хитрыми приемами.
#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
Если у тебя есть ИСХОДНИК программы, почему бы не заменить код в исходнике и перекомпилить?
Если тебе важно генерить код динамически - все вызовы исходной функции заменяешь на вызовы специальной заглушки, которая передаст управление в массив, в который ты динамически напихаешь всё что нужно. Если ты ещё хочешь, чтобы DEP не сругнулся, читай советы выше.
В некоторых случаях наиболее простым будет вынести изменяемый код в дллку, которую грузить динамически.
Если ты хочешь устроить кому-нибудь смешное западло, есть гораздо более простые способы, типа грамотного #DEFINE.
нужно защитить программу с помощью электронного ключа. Я хочу хранить часть кода на этом ключе.
Вот выдержка из одного довольно старого документа о вирусах.это не документ времён 9х винды?
Вроде NT работает в 3х или 4х кольцах.
и как по твоему всякие exepack-и работают? или asprotect-ы? или хотя бы полиморфные вирусы?ладно, ладно... уговорили =)
так и есть
Можно заменить асмовскую процедуру на написанную на скриптовом языке и сложить программу на нем в ключ. Но все эти пути - потенциальная дырка в программе, не зря же все эти NX придумывали.
Таким образом, у кулхацкера остаётся всего две возможности -
1) угадать, что именно делает отсутствующая процедура и написать её заново (нереально, скорее всего)
2) купить программу и выдрать из ключа процедуру.
Причём с пунктом 2 можно побороться вообще забавным образом - написать генератор процедур (ну, там, если используются какие-то константы, то их можно как-то хитроумно менять, не меняя семантики) так, чтобы по появившемуся вдруг в сети крэку/кейгену можно было определить, какой именно зарегистрированный пользователь отдал свой ключ на поругание.
Правда, в таком случае опять-таки возникает соблазн не мучаться со всей этой фигнёй и оформить "ключ" в виде дллки. Почему бы и нет?
такая реализация - не лучший вариант. большую процедуру ты на асме в ключ не засунешь, тем более что-то серьезное. и ее можно будет поймать, если отслеживать, как прога работает с памятью
В качестве секретных данных можно использовать либо достаточно большой набор данных, необходимых для работы программы, которые надо расшифровывать ключом из "ключа", либо некоторый псевдокод, который легко контролировать и придавать ему специальные свойства.
что касается кул-хацкеров:
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'а. Там так называется процедура, которая стартует всё остальное.
В языках с GC тоже можно, в принципе, реализовывать так closure, но тогда в куче придётся делать, а не на стеке (хотя, если escape analisys показывает, что можно на стеке - то будет эффективнее именно там).
Прикольно, я правда не придумал для чего вложенные функции и передача наружу указателей на них могли бы мне пригодиться, но всё равно прикольно. А точно нельзя это реализовать без executable stack?
Оставить комментарий
Corrector
Имеется исходник программы, написанная на си под винду. Одна из её функций - на чистом ассемблере. Нужно до вызова этой функции заменить команды этой функции на другие, опкоды которых берутся из массива. Как записать поверх одного кода другой?