Исходный код на асме можно грубо разбить на две составные части -
собственно код (.code) и инициализированные данные (.data).
Для обеспечения максимальной изменчивости каждого билда необходимо применить особый подход в обоих случаях. Поскольку сейчас мы не ставим целью использование антиотладки и антиэвристики, то целью будет сокрытие типичных сигнатур по которым сканер или беглый тренированный взгляд может оценить характер представленного в exe кода. (Покачто не рассматриваем эвристику и сигнатурный скан по импортам).
Добиться этого можно "криптованием" строковых ресурсов следующими способами:
* через внешнюю утилиту которая или криптанет (читай поксорит с небольшими вариациями) часть бинарника или его весь. Плюс - отсутствие дополнительных проблем на этапе разработки. Минус - время на создание и отладку внешней утилиты, относительная простота в детектировании т.к. обычно после декрипта весь кусок висит в памяти
* через конструкции наподобие:
Не правдали красиво? ;)
В последнем варианте вся остальная работа осталась "за кадром". Рассмотрим ее поподробнее. Итак, мы ставим вместо указателя на строку макрос. Что он может нам вернуть, т.е. вместо него после работы что мы можем получить? Если рассматривать только этот вызов invoke - то обычный параметр - или регистр, или ссылку на адрес памяти.
Принимая во внимание тот факт, что нам бы еще надо делать крипт-декрипт, и еще бы строку убивать после использования - пусть там будет регистр, указывающий на буфер со строкой, сгенерированной после работы функции-декриптора. Функция декрипта должна принимать на вход указатель на область памяти с криптованной строкой. Ну и конечно же нам бы сгенерировать код наподобие описанного во втором варианте. Мы только что прошли от простого к сложному путь проектирования макро-криптора строк. Определены основные моменты, дело теперь лишь за реализацией.
Для начала - макрос по генерированию криптованой строки:
Из источника: http://interpol.blog.ru Начало - Часть1
Для обеспечения максимальной изменчивости каждого билда необходимо применить особый подход в обоих случаях. Поскольку сейчас мы не ставим целью использование антиотладки и антиэвристики, то целью будет сокрытие типичных сигнатур по которым сканер или беглый тренированный взгляд может оценить характер представленного в exe кода. (Покачто не рассматриваем эвристику и сигнатурный скан по импортам).
Добиться этого можно "криптованием" строковых ресурсов следующими способами:
* через внешнюю утилиту которая или криптанет (читай поксорит с небольшими вариациями) часть бинарника или его весь. Плюс - отсутствие дополнительных проблем на этапе разработки. Минус - время на создание и отладку внешней утилиты, относительная простота в детектировании т.к. обычно после декрипта весь кусок висит в памяти
* через конструкции наподобие:
X equ 011h
.data
szString byte "T" xor X, "e" xor X, "s" xor X, "t" xor X, 0 xor X
.code
invoke XorData, addr szString, X
invoke MessageBox, 0, addr szString, NULL, MB_OK
Это код без использования макросов, вручную определяем ключ и затем
каждый символ берем и ксорим. Если определение ключа сделать рандомным
(используя макрос из предыдущего поста) уже будет некое подобие сокрытия
от сигнатурного детекта. Однако такой код ужасно выглядит и неудобен в
написании и соответственно модификации.
* через вызов макросов:
* через вызов макросов:
.code
invoke MessageBox, 0, $CRSTR(Test), NULL, MB_OK
Не правдали красиво? ;)
В последнем варианте вся остальная работа осталась "за кадром". Рассмотрим ее поподробнее. Итак, мы ставим вместо указателя на строку макрос. Что он может нам вернуть, т.е. вместо него после работы что мы можем получить? Если рассматривать только этот вызов invoke - то обычный параметр - или регистр, или ссылку на адрес памяти.
Принимая во внимание тот факт, что нам бы еще надо делать крипт-декрипт, и еще бы строку убивать после использования - пусть там будет регистр, указывающий на буфер со строкой, сгенерированной после работы функции-декриптора. Функция декрипта должна принимать на вход указатель на область памяти с криптованной строкой. Ну и конечно же нам бы сгенерировать код наподобие описанного во втором варианте. Мы только что прошли от простого к сложному путь проектирования макро-криптора строк. Определены основные моменты, дело теперь лишь за реализацией.
Для начала - макрос по генерированию криптованой строки:
$CR macro sStr: REQ
LOCAL bRx, bXored
LOCAL iLen
bRx=@Random(253)+1 ; generate random xor base
* iLen SIZESTR < sStr > ; calculate string len
FORC char, < sStr >
bXored = bRx xor '&char' ; prepare out string
* byte @CatStr(*bXored) ; output prepared string
ENDM
* byte @CatStr(*iLen) ; output string len
* byte bRx ; output xor key
endm
Этот макрос выбирает рандомный ключ для ксора (заметьте, что из
диапазона случайных числе исключен ноль) и затем создает в месте вызова
примерно следующий код:
byte 'T' xor 13 ; поксоренные байты
byte 'e' xor 13
byte 's' xor 13
byte 't' xor 13
byte 4 ; длина строки
byte 13 ; ключ для ксора
Для простоты здесь используется простой ксор, однако в макросе можно
изменять ключ на каждой итерации по какому-нибудь алгоритму.
Итак, закриптованные данные мы можем сгенерировать, теперь надо реализовать часть по декрипту и передаче данных в вызвавшее макрос место =) Да будет так:
Итак, закриптованные данные мы можем сгенерировать, теперь надо реализовать часть по декрипту и передаче данных в вызвавшее макрос место =) Да будет так:
$CRSTR macro sStr: REQ
jmp @F
$CR sStr
@@:
push $
call Decrypt
exitm < eax >
endm
Этот макрос прямо в коде производит вызов $CR, обрамляет его результат в
jmp @F // @@:, и затем производит вызов декриптора с передачей в него
текущего смещения. Декриптор в данном случае должен идти в сторону
уменьшения переданного адреса и обрабатывать переданную структуру,
сгенерировать буфер и записать в него расшифрованный кусок и вернуть его
адрес в регистре eax. Никакие другие регистры по выходу не должны быть
изменены.
В результате мы получаем достаточно простой и элегантный способ криптования строк без написания каждый раз вручную лишнего кода, а значит остается больше времени для этих вкусных кодесов и успешной "компеляции в месте" =)
В результате мы получаем достаточно простой и элегантный способ криптования строк без написания каждый раз вручную лишнего кода, а значит остается больше времени для этих вкусных кодесов и успешной "компеляции в месте" =)
Комментариев нет:
Отправить комментарий