Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Самошифрующийся код на Ассемблере
Самошифрующийся код на Ассемблере

Макросы - один из наиболее мощных инструментов FASM. С их помощью можно не только описывать сложные структуры и целые наборы команд, но также модифицировать данные еще на этапе компиляции. Сегодня мы сделаем самошифрующийся код с помощью макросов FASM и реализуем его защиту.

Первым делом сформируем макрос для последовательной обработки байт. Шифрование тут будет достаточно простое, XOR каждого байта с ключом, но ключ будет динамически меняться. Это обеспечит надежное сокрытие даже последовательности однотипных данных.
  1. ;------------------------------------------------
  2. ; Макрос для шифрования кода
  3. ;------------------------------------------------
  4. macro encrypt_code enc_start,enc_len {
  5.         local char,key
  6.         key = 0x3D
  7.         repeat enc_len
  8.                 load char from enc_start+%-1
  9.                 char = char xor key
  10.                 store char at enc_start+%-1
  11.                 key = (key + 13) and 0xFF
  12.                 key = key xor 0x25
  13.         end repeat
  14. }
Для того, чтобы компилятор зашифровал байты в момент создания двоичного кода программы, его надо оформить примерно следующим образом:
  1. section '.code' code readable writeable executable
  2.  
  3. start:
  4.         ; Этот код будет зашифрован при компиляции
  5.         invoke  MessageBox,0,szText,szTitle,MB_OK
  6.         invoke  ExitProcess,0
  7.  
  8. szTitle db 'Encrypted Code',0
  9. szText  db 'Hello, World!',0
  10.  
  11.         ; Длина кода для шифрования
  12.         code_size=$-start
  13.  
  14.         ; Зашифровать код
  15.         encrypt_code start,code_size
В вызове макроса указывается начало шифруемого кода, а также его длина. Удобнее всего делать это сразу от начала программы, текстовые данные при этом лучше тоже поместить внутри шифруемого блока. Обратите внимание, что секция кода помечена как writeable, потому что ее содержимое будет модифицироваться.

Отлично, теперь код будет шифроваться на этапе компиляции. Но при выполнении надо же его расшифровать. В принципе, код расшифровки можно поместить до шифрованного блока и оформить точку входа на него, но есть вариант получше. С целью затруднения анализа и отладки, предлагаю разместить расшифровщик в TLS. Он будет вызываться еще до старта программы, а при обычном просмотре и попытке декомпиляции код с самой точки входа будет выдаваться в зашифрованном виде. Важное замечание. Функции TLS при старте программы могут вызываться несколько раз, поэтому обязательно надо проверять, что код уже был расшифрован и не обрабатывать его повторно. Для этого можно поместить первым байтом, например, команду NOP и проверять содержимое кода перед расшифровкой. Или, как в моем варианте, задействовать неиспользуемое поле в самой структуре TLS.
  1. ;------------------------------------------------
  2. ; Функция расшифровки кода
  3. ;------------------------------------------------
  4. proc decrypt
  5.         ; Код уже расшифрован?
  6.         cmp     [tls_reserved],0
  7.         jne     .loc_ret
  8.  
  9.         pusha
  10.         ; Указатель на зашифрованный код
  11.         mov     esi,start
  12.         mov     edi,start
  13.         ; Длина зашифрованного кода
  14.         mov     ecx,code_size
  15.  
  16.         ; Начальное значение ключа
  17.         mov     bl,0x3D
  18. @@:
  19.         ; Расшифровать символ
  20.         lodsb
  21.         xor     al,bl
  22.         stosb
  23.         ; Изменить ключ
  24.         add     bl,13
  25.         xor     bl,0x25
  26.         ; Следующий символ
  27.         loop    @b
  28.  
  29.         ; Код расшифрован
  30.         mov     [tls_reserved],1
  31.         popa
  32. .loc_ret:
  33.         ret
  34. endp
  35.  
  36. ;------------------------------------------------
  37. ; Секция TLS
  38. ;------------------------------------------------
  39. data 9
  40.               dd 0             ; Raw Data Start VA
  41.               dd 0             ; Raw Data End VA
  42.               dd tls_index     ; Address of Index
  43.               dd tls_callbacks ; Address of Callbacks
  44.               dd 0             ; Size of Zero Fill
  45. tls_reserved  dd 0             ; Reserved
  46. tls_index     dd 0             ; Index
  47. tls_callbacks dd decrypt       ; Callbacks
  48.               dd 0             ; End
  49. end data
Несмотря на простоту шифрования, от шаловливых ручонок такой способ прекрасно защитит. А функцию расшифровки можно дополнительно наворотить антиотладкой, в конце концов сделать несколько слоев шифрования, зашифровать расшифровщик, зашифровать его расшифровщик и т.д. по цепочке вызовов TLS. Все ограничивается вашей фантазией. Но главное тут, что вам не придется обрабатывать готовый исполняемый файл какими-то внешними утилитами, всю работу за вас сделает компилятор FASM. А чтобы программу можно было отлаживать в процессе ее разработки, шифрование легко отключить или сделать опциональным, как в прилагаемом исходнике.

В приложении пример программы с исходным текстом, которая при компиляции шифрует свой код, а расшифровку выполняет еще до ее фактического запуска.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Self.Encryption.Code.Demo.zip (1,929 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 542 | Комментариев: 7

Метки: Assembler

Комментарии

Отзывы посетителей сайта о статье
ManHunter (20.02.2025 в 18:10):
Полиморфизм нужен больше для самоходного программного обеспечения, чтобы при размножении ни одна копия не совпадала с другой. Пройденный этап :)

Я в своих поделиях использовал похожий алгоритм, только более хитрый. Кусочек кода динамически расшифровывался, исполнялся, затем шифровался обратно с другим ключом. И таких кусочков было дохрена и больше. В итоге в памяти висел практически полностью зашифрованный экземпляр, который при этом еще и постоянно менялся. Сдампить можно, конечно, но потом придется еще мудохаться с расшифровкой каждого отдельного кусочка.
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):
Вот это уже интересно! Благодарю!

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0037 сек.) / Память: 4.5 Mb
Наверх