
Самошифрующийся код на Ассемблере

Самошифрующийся код на Ассемблере
Макросы - один из наиболее мощных инструментов FASM. С их помощью можно не только описывать сложные структуры и целые наборы команд, но также модифицировать данные еще на этапе компиляции. Сегодня мы сделаем самошифрующийся код с помощью макросов FASM и реализуем его защиту.
Первым делом сформируем макрос для последовательной обработки байт. Шифрование тут будет достаточно простое, XOR каждого байта с ключом, но ключ будет динамически меняться. Это обеспечит надежное сокрытие даже последовательности однотипных данных.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------
- ; Макрос для шифрования кода
- ;------------------------------------------------
- macro encrypt_code enc_start,enc_len {
- local char,key
- key = 0x3D
- repeat enc_len
- load char from enc_start+%-1
- char = char xor key
- store char at enc_start+%-1
- key = (key + 13) and 0xFF
- key = key xor 0x25
- end repeat
- }
Code (Assembler) : Убрать нумерацию
- section '.code' code readable writeable executable
- start:
- ; Этот код будет зашифрован при компиляции
- invoke MessageBox,0,szText,szTitle,MB_OK
- invoke ExitProcess,0
- szTitle db 'Encrypted Code',0
- szText db 'Hello, World!',0
- ; Длина кода для шифрования
- code_size=$-start
- ; Зашифровать код
- encrypt_code start,code_size
Отлично, теперь код будет шифроваться на этапе компиляции. Но при выполнении надо же его расшифровать. В принципе, код расшифровки можно поместить до шифрованного блока и оформить точку входа на него, но есть вариант получше. С целью затруднения анализа и отладки, предлагаю разместить расшифровщик в TLS. Он будет вызываться еще до старта программы, а при обычном просмотре и попытке декомпиляции код с самой точки входа будет выдаваться в зашифрованном виде. Важное замечание. Функции TLS при старте программы могут вызываться несколько раз, поэтому обязательно надо проверять, что код уже был расшифрован и не обрабатывать его повторно. Для этого можно поместить первым байтом, например, команду NOP и проверять содержимое кода перед расшифровкой. Или, как в моем варианте, задействовать неиспользуемое поле в самой структуре TLS.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------
- ; Функция расшифровки кода
- ;------------------------------------------------
- proc decrypt
- ; Код уже расшифрован?
- cmp [tls_reserved],0
- jne .loc_ret
- pusha
- ; Указатель на зашифрованный код
- mov esi,start
- mov edi,start
- ; Длина зашифрованного кода
- mov ecx,code_size
- ; Начальное значение ключа
- mov bl,0x3D
- @@:
- ; Расшифровать символ
- lodsb
- xor al,bl
- stosb
- ; Изменить ключ
- add bl,13
- xor bl,0x25
- ; Следующий символ
- loop @b
- ; Код расшифрован
- mov [tls_reserved],1
- popa
- .loc_ret:
- ret
- endp
- ;------------------------------------------------
- ; Секция TLS
- ;------------------------------------------------
- data 9
- dd 0 ; Raw Data Start VA
- dd 0 ; Raw Data End VA
- dd tls_index ; Address of Index
- dd tls_callbacks ; Address of Callbacks
- dd 0 ; Size of Zero Fill
- tls_reserved dd 0 ; Reserved
- tls_index dd 0 ; Index
- tls_callbacks dd decrypt ; Callbacks
- dd 0 ; End
- end data
В приложении пример программы с исходным текстом, которая при компиляции шифрует свой код, а расшифровку выполняет еще до ее фактического запуска.
Просмотров: 542 | Комментариев: 7
Метки: Assembler

Комментарии
Отзывы посетителей сайта о статье

doz.me
(20.02.2025 в 17:48):
эта дорожка ведет к полиморфизму)

Виктор Лушников
(14.02.2025 в 01:39):
Интересно всё! Ждём новых статей! :-)

morgot
(13.02.2025 в 23:44):
Да, макросы в фасм мощные. В масм/Си и близко такого нет.
Спасибо за статью.
Спасибо за статью.

ufa
(12.02.2025 в 17:19):
ManHunter, все интересно! Но такие примеры - очень редко где встретишь (имею в виду - про шифрование).

ManHunter
(12.02.2025 в 17:09):
А остальное что, совсем не интересно?

ufa
(12.02.2025 в 17:09):
Вот это уже интересно! Благодарю!

Добавить комментарий
Заполните форму для добавления комментария

Я в своих поделиях использовал похожий алгоритм, только более хитрый. Кусочек кода динамически расшифровывался, исполнялся, затем шифровался обратно с другим ключом. И таких кусочков было дохрена и больше. В итоге в памяти висел практически полностью зашифрованный экземпляр, который при этом еще и постоянно менялся. Сдампить можно, конечно, но потом придется еще мудохаться с расшифровкой каждого отдельного кусочка.