Страницы

Из источника: Метаморф в сырцах - с глаз долой

 Исходный код на асме можно грубо разбить на две составные части - собственно код (.code) и инициализированные данные (.data).

Для обеспечения максимальной изменчивости каждого билда необходимо применить особый подход в обоих случаях. Поскольку сейчас мы не ставим целью использование антиотладки и антиэвристики, то целью будет сокрытие типичных сигнатур по которым сканер или беглый тренированный взгляд может оценить характер представленного в 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. Никакие другие регистры по выходу не должны быть изменены.
    В результате мы получаем достаточно простой и элегантный способ криптования строк без написания каждый раз вручную лишнего кода, а значит остается больше времени для этих вкусных кодесов и успешной "компеляции в месте" =) 

 Из источника: http://interpol.blog.ru Начало - Часть1






Комментариев нет:

Отправить комментарий