Тривиальное шифрование во вредоносных файлах

    Привет. Это снова Алексей Маланов из «Лаборатории Касперского». В прошлый раз я рассказывал про опыт найма вирусных аналитиков, а сегодня расскажу про то, что делают вирусописатели, чтобы их работа не была замечена, и что делаем мы, чтобы их труд в итоге оказался напрасен.

    Вообще говоря, злоумышленник пишет вредоносную программу, почти всегда заранее зная, что она рано или поздно попадет на «операционный стол» вирусному аналитику. И вся информация из зловреда может быть использована против автора. А чего ему скрывать? Ну, во-первых свою личность. Порой в зловредах встречаешь строки, типа C:\Users\Vasiliy Ivanov\Documents\Visual Studio 2005\заработок\trojan\Release\trojan.pdb. Во-вторых, довольно много информации, облегчающей анализ зловреда. Давайте рассмотрим некоторые приемы вирусописателей, и выясним, почему же они бесполезны.

    Что скрывают:


    Интернет-ссылки

    image

    Экземпляры Trojan-Downloader в первую очередь скачивают/обновляют другое вредоносное ПО по одной или нескольким ссылкам. Очевидно, что если ссылки хранить в явном виде, то система автообработки любой антивирусной компании с легкостью извлечет их, добавит в список на периодическое скачивание и забанит доступ к этим ресурсам. Смысл Trojan-Downloader'а пропадает напрочь. Зловредам других классов также свойственно скачивать новые версии своих модулей.

    Компоненты

    Зловреды нынче сложные, многокомпонентые. Один модуль отвечает за обновление, второй — драйвер-руткит, третий обеспечивает сбор паролей, четвертый ответственен за прием команд из центра управления и передачу результатов. В общем, очень часто все это оборачивается в один «инсталлятор». Это может быть специальный Trojan-Dropper стороннего «разработчика», а то и просто очередной компонент того же автора. Так же, как и с URL'ами, если внутренние PE-EXE модули не спрятать надёжнее, их легко выдерут автоматические средства, и все файлы отправятся на автоанализ и автодетектирование. Причем, если хотя бы один из модулей будет признан вредоносным, то вся пачка уже точно не потребует ручного анализа, и все будет успешно задетектировано.

    Пароли

    Вы не поверите, но во вредоносных файлах авторы зашивают даже свои пароли. Не часто, конечно, но бывает. Например, если Trojan-Spy делает много снимков экрана (или даже снимает видео камерой жертвы), то обычный способ доставки материала автору — заливка на FTP. Вирусописатель создает один аккаунт с доступом на чтение и запись. И чтобы никто лишний не забрел на его FTP, выставляет пароль, который вписывается в код зловреда. В результате туда забредает не абы кто, а конкретный независимый исследователь, стирает все награбленное и оставляет записочку горе-автору. Замечу, что это «неправомерный доступ к компьютерной информации», вот только преступник не побежит писать заявление.

    Другой пример — пароль от почтового ящика. Автору нужно переслать себе собранные у жертвы пароли. Но почтовый сервис, на котором у него зарегистрирован ящик, не позволяет отправлять письма непонятным людям и требует аутентификации при отправке. Понятно, что «серьезные» малварщики так не ошибаются, особенно те, кто нацелен на воровство банковской информации. Другие же, напротив, иногда намеренно рассчитывают, что их код будет просмотрен аналитиком. Сейчас-то почти все идет на автоматику, а вот 10 лет назад, когда я сам анализировал файлы, встречалось мне такое обращение к вирусному аналитику внутри сампла: «Это никем не детектируемый Pinch, и мне бы хотелось, чтобы он оставался таким. Вам для этого ничего не нужно делать. Спасибо.»

    Тривиальное шифрование:


    Отсюда вывод: вирусописателям есть что скрывать внутри своих творений, и они пытаются это делать. Если вы отлично знаете, что такое битовые операции XOR, ROL и понимаете, как при помощи них можно преобразовать данные, вы можете пропустить весь этот раздел.

    Предположим, у вас есть строка httр://secret.url, и вы хотите спрятать ее в коде от просмотра глазами. При этом алгоритм расшифровки и ключ тоже будут находиться в этом же коде, ведь вам самим эта строка понадобится. Пожалуй, самым-самым простым способом будет следующий.

    Not

    image

    Представим строку в виде цепочки битов 110100001110100… Заменим каждый бит на противоположный 001011110001011… Получим строку "ЧЛЛП┼╨╨МЪЬНЪЛ╤КНУ". Теперь невооруженным глазом такую строку уже не узнать. Зато программно можно. Применим ко всему файлу операцию NОТ: то, что было зашифровано, расшифруется обратно. А что нет — зашифруется. В получившемся файле URL виден автоматике и глазам.

    image

    Xor

    Слегка усложним. При шифровании инвертировать можно не каждый бит, а, например, каждый четвертый (чтобы никто не догадался). Такое вот инвертирование некоторых битов называется так же операцией XOR. Записывается a := a XOR key, где a — это преобразуемый байт, а key — ключ, в котором записано, какие биты меняем.

    image

    При этом, операция NOT эквивалентна a := a XOR FF. Шестнадцатеричное FF равно двоичному 11111111 — инвертируем каждый бит.

    Для расшифровки нужно «поксорить» данные еще раз с тем же ключом. Убедиться, что при этом получится именно оригинал, я предлагаю любопытному читателю самостоятельно. Не забывайте, что в отличие от предыдущего метода, в этом вам придется хранить ключ в программе, если вы хотите расшифровать свои данные при исполнении. И аналитику тоже придется искать/перебирать ключ, чтобы дешифровать строку. Есть, впрочем, еще один способ, но об этом ниже.

    Другие методы

    Что еще можно сделать:
    1. Применять к каждому байту операцию ADD, то есть добавлять некое число — ключ
    2. Менять ключ от байта к байту. Например, первый байт «ксорить» с ключом 71, второй — с 73, третий — с 75 и т.д. Тогда ключ нельзя будет уже просто перебрать, перебирать придется уже 2 ключа, а это в 256 раз дольше
    3. Можно увеличить длину ключа. Например, первый DWORD «ксорить» с четырехбайтовым ключом, второй DWORD «ксорить» с ним же и т.д. Тогда для расшифровки без ключа вам придется перебирать уже 4 миллиарда вариантов. А если вы (или программа-выдиралка) не знаете, где точно расположена искомая информация в файле, то такой перебор придется производить для каждого байта (размер зловреда обычно составляет несколько сотен килобайт)
    4. Можно применить операцию циклического сдвига ROL на каждый байт. Но только при побайтовой шифрации «ролить» имеет смысл только на 1-7 битов. При циклическом сдвиге байта на 8 бит мы получаем тот же самый байт.
    5. Можно «ксорить» два раза. Один малварщик зашифровал строку. Ему показалось, что этого мало, он еще раз «поксорил» ее с тем же ключом. Что из этого получилось, догадайтесь сами.
    6. Строчку можно записать задом наперед
    7. Строчку можно записать через байт. Для ASCII-символов получится Unicode.
    8. Строчку можно сдвинуть на пол алфавита, то есть a->n, b->o, ..., z->m, 0->5, 1->6...
    9. Записать символы в hex-виде, то есть 687474703A2F2F
    10. Разместить строку на стеке

      push 'w//:'
      push 'ptth'
    11. И тому подобное

    Все обозначенные способы, очевидно, можно комбинировать для пущей конспирации :)

    Расшифровка:


    Обозначим задачу. Есть файл длиной в 1 Мб. Внутри в неизвестном месте зашифрована одним из описанных выше методов строка, начинающаяся с http://. Ключ неизвестен. Надо написать программу, которая обработает файл и, без эпического перебора, извлечет эту строку. Зашифровано может быть что-то еще, например, MZ-PE заголовок внутреннего файла, но с условием: вам известно, что именно вы ищете. А то искать неизвестный мусор, зашифрованный неизвестно чем, в неизвестном месте – не очень-то благодарное занятие.

    Небольшое отступление. В ЛК сейчас используются такие методы автоанализа, которым все равно, что зашифровано, и как. Хотя бы даже очень стойким алгоритмом (в отличие от описанных). Если данные используются самой программой, они все равно будут нами извлечены. Ниже я лишь продемонстрирую, что описанные методы шифрования не защитят вирусописателя и не составят трудности даже для аналитика-любителя. Никаких откровений. Следите за руками.

    Xor

    Вы помните урл, к которому применили операцию NOT? "ЧЛЛП┼╨╨". Увидев эти буквы вновь, вы всегда угадаете, что это урл. А вот строка, поксоренная с ключом F0: "ШДДА╩▀▀". Или с 0F: "g{{⌂5 ". Обратите внимание, второй и третий, а также последний и предпоследний символы равны. «Полезное» свойство описанных байтовых преобразований — они переводят равные байты в равные. Но у XOR есть еще полезное свойство — операция обратима. То есть, из 'Ш' = 'h' XOR key
    следует, что key = 'Ш' XOR 'h'. А это значит, что если есть последовательность "ЙЦУКЕНГ", то key := 'Й' XOR 'h'. Далее проверяем, что
    'Ц' == 't' XOR key
    'К' == 'p' XOR key
    'Е' == ':' XOR key...
    Если так и есть, то мы нашли урл и знаем ключ.

    Add

    Аналогично, если 'Й' = 'h' + key, то key = 'Й' — 'h'. И проверяем, что оставшаяся часть урла действительно является урлом.

    Но вот что делать, если злоумышленник линейно менял ключ от байта к байту?
    'Й' = 'h' + key
    'Ц' = 't' + (key + d)
    'У' = 't' + (key + 2d)
    'К' = 'p' + (key + 3d)...

    Все то же самое:
    key = 'Й' — 'h'
    key + d = 'Ц' — 't'

    Если автор использовал четырехбайтовый ключ:
    'ЙЦУК' = 'http' XOR key32

    То мы все равно сможем вычислить ключ и даже провалидировать его на оставшихся трех известных байтах. Но если ключ длиной в саму искомую строку, то описанный подход не работает. Почему-то малварщики делают что угодно, но только не то, что на самом деле помогло бы им.

    Комбинирование

    Например, они комбинируют методы. Запишут урл задом наперед, да еще через байт, а потом еще поксорят с переменным ключом. Да, некоторую автоматику это может сбить с толку. По факту же это не мешает успешно детектировать такие файлы. А как только зловреда разберет вирусный аналитик, он добавит в дешифровщик метод Reverse(Unicode(LinearXor(stream))), после этого все старые и новые версии расшифровываются автоматически.

    Водяные знаки

    Еще одно применение описанных методов шифрации: водяные знаки в программе. Предположим, вы честный программист и отдаете копию программы клиентам Василию и Георгию. Нет, лучше Эдуарду и Григорию. И хотите знать, а не выкладывает ли один из них программу в публичный доступ. В исходном коде вы можете написать:
    #pragma data_seg(".text")
    extern char WATERMARK[]= «uQPW►▀}_▲WTW►»; // «Копия Эдуарда» XOR FF


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

    Однако, как мы только что выяснили, если копия Эдуарда все-таки попадет в публичный доступ, то у Григория окажутся два варианта программы, и он без труда найдет разницу в них и разгадает шифр. Получится только хуже для вас, Григорий сможет подделывать чужие копии.

    Заключение:


    Вот в целом и все. Мы познакомились с некоторыми тривиальными методами шифрации и выяснили, почему же они бесполезны. Если у вас есть вопросы и комментарии — отлично, очень жду. Если же материал показался вам слишком простым, то вот вам жизненный пример из области анализа вирусов на эту же тему.

    Вирус (инфектор) встраивает свое тело в заражаемый файл. Тело у него постоянно, но он его ксорит по DWORD'ам с псевдослучайными числами так:
    srand(key);
    crypted[0] = body[0] XOR rand();
    crypted[1] = body[1] XOR rand();


    Дешифратор тела с ключом «размазан» по коду жертвы (entry-point obscuring), поэтому детектировать придется по зашифрованному телу. Для примера можете считать, что телом вируса является секция кода notepad.exe.

    Известно, что в качестве генератора псевдо-случайных чисел используется самый популярный в компиляторах алгоритм:


    seed = seed * 1103515245 + 12345;
    return (seed % ((unsigned int)RAND_MAX + 1));
    

    Показать полностью
    /*
     * This file is part of the libpayload project.
     *
     * It was originally taken from the OpenBSD project.
     *
     * Copyright (c) 1990 The Regents of the University of California.
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 3. Neither the name of the University nor the names of its contributors
     *    may be used to endorse or promote products derived from this software
     *    without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE.
     */
    
    #include <libpayload.h>
    
    static unsigned int next = 1;
    
    int rand_r(unsigned int *seed)
    {
            *seed = *seed * 1103515245 + 12345;
            return (*seed % ((unsigned int)RAND_MAX + 1));
    }
    
    int rand(void)
    {
            return (rand_r(&next));
    }
    
    void srand(unsigned int seed)
    {
            next = seed;
    }
    



    Реально ли быстро в уме программно задетектировать этот вирус?
    «Лаборатория Касперского»
    Ловим вирусы, исследуем угрозы, спасаем мир

    Comments 44

      0
      Ну есть метод «в лоб» без разбирательств, если алгоритм генерации случайного числа встроен в вирь, я бы смотрел число «1103515245» в теле, или скомпилил функцию генерации и использовал ее в качестве сигнатуры, ибо это то, что требуется вирю в незашифрованном виде (если конечно не применено комбинирование или какая-то обфускация)

      Ну а если по уму, то надо смотерть распределение, дающееся таким генератором ПСЧ, и смотреть варианты его взлома (а его точно давным-давно сломали) и на основе их, а так-же учитывая что XOR обратим, думать дальше :-) Как-то так. ИМХО.
        0
        Подход неплохой, но. У этого метода равномерное распределение. Если вы RAND_MAX+1 раз вызовете rand(), она вернет вам все числа от 0 до RAND_MAX ровно по одному разу. А указанное Вами число находится в библиотечной функции rand() и в зараженной программе не встретится. Либо будет встречаться в каждой программе, использующей rand(), если тело функций компилятор помещает в исполняемый файл.
          +1
          Я просто так понял, что код генератора как раз «зашит», т.е. не используется системный, ок, согласен.

          Ну вот так, сходу, приходит на ум только сравнение двух закодированных одинаковых файлов (например исходного notepad и завирусованного его-же, либо одинаковых, но по разному завирусованных файлов), либо если только задетектить — хэш суммы, entry-point, сравнение эталонных длин файлов.

          А вот чисто алгоритмическое решение сообразить не могу.
          Если конечно вирус был заранее известен, то тогда, можно найти в нем какие-либо повторяющиеся байты на определенном расстоянии, к которым можно прицепится для детекта XOR — ибо какой бы «XOR число» не был использован — они так-же будут повторятся, хоть и будут иметь другие значения…

          P.S. OMG, чем мы занимаемся в Пятницу :-D
            0
            Всё нормально, у многих завтра понедельник… Перенос выходного на 30е декабря. Если вы, конечно, не сам себе начальник :)
          0
          Скорее всего код будет выполняться в WIndows и компилироваться в Visual C++. А в этом случае RAND_MAX равен 0x7fff, т.е. из 32 бит DWORD'а «ксориться» будут только 15. По оставшимся старшим 17 битам вполне можно детектировать вирус
          +1
          В результате туда забредает не абы кто, а конкретный независимый исследователь, стирает все награбленное и оставляет записочку горе-автору. Замечу, что это «неправомерный доступ к компьютерной информации», вот только преступник не побежит писать заявление.

          Вот будет весело если побежит: «знать не знаю ни про какие зловреды, пароль от фтп украли и стерли оттуда коммерческую информацию.» IP ваш, вы туда заходили и что-то уничтожали. Уголовка до двух лет, а то и до четырех лет. А если выяснится что вы это сделали по работе, то и до пяти можно.
            +5
            Будет весело, это правда. Поэтому мы предупреждаем независимых исследователей и советуем так не делать.
            0
            А почему не используют p2p технологии для управления вирусами? Ведь при таком использовании нужно будет лишь прописать начальную magnet ссылку и все, управление не получится так просто заблокировать (выключив СС сервера).
              0
              Используют, насколько я знаю.
              Ботнеты это очень любят.
              Но вообще это гораздо более сложный метод чем FTP / POST(GET) / SMTP ибо есть в системе практически все готовое.
                +1
                А как в таком случае поступают для перехвата и закрытия ботнетов? А то постоянно пишут только про ботнеты, использующие обычные сервера для управления.
                А вообще, как по мне, так это довольно интересная тема насчёт принципов работы и выведения из строя вирусов, использующих р2р (I2C, tor наверно же тоже используются?).
                • UFO just landed and posted this here
              +2
              А почему не используют обычные алгоритмы шифрования, допустим с некоторой модификацией? Зачем эти примитивные алгоритмы со сдвигами и прочими школьными шалостями?
                0
                По-разному: кто-то ленится, кто-то не умеет, кто-то вовсе не знает. Собственно говоря, об этом и статья :) Но в ЛК все равно расшифровано будет все и вся, так что пущай ленятся дальше.
                  0
                  Ещё вопрос скорости и незаметности :) А вообще от подобных поделок не нужно лютое шифрование а нужна лишь социальная инженерия что бы пациент не подумав, и с криками «всё пропало» побежал денежку платить.
                  0
                  Не совсем строгие условия. Я так понимаю, что ключ для srand один, но последовательность числ rand1 и rand2 будет разной? Взять два (?) закриптованых эксземпляра. crypted1[0] xor crypted2[0] = body1[0] xor rand1 xor body2[0] xor rand2 = body1[0] xor body2[0] xor rand1[0] xor rand2[0] =|body1[0] == body2[0]|= 0 xor rand1[0] xor rand2[0] = | xor 0| = rand1[0] xor rand2[0]. таким образом получить rand1[1] xor rand2[1]. Так как не совсем понял про генератор и каким образом он инициализурется, вродебы двух значений должно быть достаточно, чтобы найти seed и раскодировать все.
                    +2
                    Так-с. srand(key); — здесь используется ключ, известный в момент шифрации, но неизвестный нам в момент дешифрации. Генератор случайных чисел в C устроен так: вы инициализируете его вызовом srand(seed) (обычно в параметре указывают time, который при однократном вызове очень случаен), после чего на основе seed строятся следующие числа. Восле задания seed последовательность rand всегда одна и та же. Так устроен указанный алгоритм генерации псевдослучайных чисел и многие другие. В процессе анализа файла антивирусным движком у вас есть зашифрованные данные (только в конкретном файле), а ключа нет. Так вот ваша задача — понять, зашифровано там тело вируса или это просто какой-то мусор. На этапе написания детектирования у вас и тело есть, и ключи уже подобраны, и много вариантов зараженных файлов.
                      0
                      Ну так расшифрованное тело же есть. XOR-им им подозрительный кусок файла и получаем чистую последовательность от rand()-а. То есть, может быть получаем. Подставляем получившиеся числа в формулу rand()-а, если все получилось — он, вирус. Если не вышло — значит не он. Это работает потому, что в используемом rand-е почти нет скрытого состояния, там фактически seed и есть очередное случайное число (минус старший бит, так как RAND_MAX=2147483647). Так что зная первое случайное число, можно тривиально вычислить второе (точнее, два возможных вторых), потом третье, и так далее.
                    +7
                    Хочу предостеречь насчет «самого популярного в компиляторах алгоритма». Несмотря на то, что линейный конгруэнтный метод генерации случайных чисел сам по себе неплох, константы, взятые в данной конкретной его реализации, выбраны неудачно. Их опубликовал комитет по стандартизации в качестве примера, просто лишь бы чем-нибудь заполнить пропуски. Но многие программисты библиотек не потрудились проверить, какие там должны стоять числа, и бездумно скопировали их их «стандартного примера». В результате сильно страдают статистические свойства получаемых случайных чисел. Подробно об этом написано в книге William H. Press et al «Numerical Recipes».
                      +3
                      Чертовски приятно видеть человека, хорошо разбирающегося в вопросе!
                      0
                      Только методы эти почти всегда часто не от защиты от целенаправленного анализа, а от ковыряния школьниками файла в hex-редакторе на предмет ссылок/учеток. Считается, что таким «исследователям» будет лениво запускать сэмпл в виртуалке или в IDA, да и простая защита от всего этого дела также может быть.
                        0
                        Автор, большое спасибо вам за статью. Очень интересно читать о технологиях борьбы с вредоносным ПО. Жду от Вас еще статей на эту тему. Было бы интересно почитать и о других трюках, применяемых в вирусах, а также об уникальных методах борьбы с ними, которые не реализованы в продукции Ваших конкурентов.
                          +6
                          Рады бы рассказать об «уникальных методах борьбы, которые не реализованы в продукции конкурентов», но, боимся, после выхода статьи методы перестанут быть уникальными :)
                            –3
                            Может все таки стоит? А то порой зальешь файл на вирустотал и становится очень грустно, когда видишь только 2-3 срабатывания.
                              +2
                              Тут надо понимать, что на вирустотал происходит только сканирование базами. Современный же антивирус — это многослойная защита, поведенческий анализ и прочие техники и технологии. Поэтому оценивать антивирусы лишь по вирустотал не стоит.
                                +1
                                Я это хорошо понимаю. Только все равно мечтаю, что когда-нибудь сифилис будет определяться еще до его запуска. Хоть и знаю, что это глупая наивная мечта.
                                  0
                                  Фактически так и есть — зловред запускается в виртуальной среде и там анализируется его поведение :) Это одна из занятных фич продуктов ЛК.
                                  +1
                                  Тут недавно была статься про локеры. Почему антивирусы пропускают такое? Сразу же видно ненормальное поведение программы. В крайнем случае можно лишний раз запросить подтверждение.
                                  Хотелось бы иметь антиврус, которые не скачивал ежедневно базы, а просто контролировал кто-что делает на компьютере и все изменения файлов.
                                  Запускается неизвестный процесс, посмотреть какие вызовы Windows API он использует, потом в процессе работы что делает, куда лезет. Неужели это очень сложно?
                                  Я пользуюсь вашим антивирусом уже много лет, но что-то защищенным себя чувствую только процентов на 80.
                                    +2
                                    Вот то же самое. Мне даже не столько антивирус нужен, сколько какой-нибудь watchdog, который будет следить, лезет ли какой-то левый софт к файлам паролей от Firefox, к примеру, какой набор действий выполняет и по ряду критериев решает легитимны ли они. До сих пор стоящего решения не видел.
                                      0
                                      Outpost? или не то?
                                        0
                                        Пробовал. Очень фанатичная софтина со сложным файрволом, который хрен пойми как работает. Тем более я за роутером — мне в принципе всё равно. Kerio вроде понятный, но он файрвол и я его не пробовал.
                                        Была одна софтина интересная, но уж больно куцые и неудобные настройки у неё были. Тоже watchdog, но туповатый и не могу вспомнить название :)
                                +1
                                И правда. Ну тогда пишите хотя бы о неуникальных методах, которые на сегодняшний день повсеместно применяются в антивирусном ПО. Поведенческий анализ — очень интересное направление. В самом деле, неважно, как вирус там себе шифруется, если его можно вычислить по результатам его деятельности, которые так просто не замаскируешь. Кстати говоря, люди обнаруживают на своем компе новые вирусы в основном именно благодаря поведенческому анализу, то есть наблюдению за поведением пораженного компьютера, которое имеет ряд характерных признаков.
                              +4
                              В какой то момент возникло стойкое ощущение что, это статья для обучения вирусописателей, а не анализ антивирусного специалиста.
                                0
                                Это одно и тоже )
                                +5
                                Подобные способы ещё во времена Синклера существовали. Распространённой темой в те годы было переделывание игр с кассеты под диск. Для этого нужно было получить дамп кода игры в незашифрованном виде, а на кассете он зачастую был зашифрован, а распаковывался при помощи загрузчика, написанного в кодах, но интегрированного в BASIC текст заголовка игры. Обычно все эти загрузчики были очень простыми: банальный XOR по всей программе. Часто XOR'ом загрузчик был завёрнут несколько раз последовательно, не знаю зачем: распаковку это никак не затрудняло, отладчик справлялся с задачей без проблем.

                                Но особенно запомнилась игра TRAP DOOR. Её дамп был зашифрован плавающим двухбайтным XOR ключом (т.е. ключ менялся в процессе расшифровки). Начальное значение самого ключа загрузчик получал путём неких вычислений в реальном времени, используя значения таймера, который инкрементировался с заданной частотой при помощи прерываний независимо от основного кода программы. Таким образом, прогнав этот фрагмент загрузчика через отладчик, было невозможно получить правильное значение ключа. Далее, по мере распаковки, значение ключа изменялось тоже при помощи процедуры таймера.

                                В итоге, это оказалась единственная игра загрузчик которой мне так и не удалось сломать. :-/ Конечно, я её потом слил через «волшебную кнопку» (дамп памяти по внешнему прерыванию), но это было нечестно. Сам загрузчик мне в итоге так и не поддался.
                                  +2
                                  1. Если бы я писал автоматический анализатор, я бы просто автоматически трассировал бы исследуемый зловред до тех пор, пока он не дойдёт до системного вызова с обращением к искомому URL, тогда можно одолеть любую обфускацию, а не только XOR. Кстати некоторые вирусы делали во времена MS-DOS так же, трасируя прерывания BIOS до тех пор пока не доходили до адресов BIOS, обходя тем самым от антивирусные мониторы.
                                  2. (Лучше напишу здесь, а не личным письмом, т.к. очень много людей делают эту ошибку) Нет такого слова «шифрация», есть «шифрование».
                                    –1
                                    Поправте меня если я не прав, можно сгенерить паблик и приват ключ, и всю инфу сливать на общедоступное место, закодировав приват ключем, на какойнить форум, или свалку, или канал.и только зная приватный ключ можно будет раскодировать нужную инфу. (вроде как без палева)
                                      0
                                      При шифровании используются последние 8 бит псеводслучайного числа. Переносы при уможнении и сложении идут влево, поэтому достаточно перебрать 256 возможных значений key — от 0 до 255, примерно так:

                                      int main(void)
                                      {
                                        char *original = strdup("Hello, world!");
                                        int len = strlen(original);
                                      
                                        // Encrypt
                                        int key = 232222329;
                                        srand(key);
                                        char *encrypted = strdup(original);
                                        printf("Original:\t");
                                        for (int i = 0; i < len; i++) {
                                          int x = rand();
                                          printf("%02x ", (unsigned)encrypted[i] & 0xff);
                                          encrypted[i] ^= x;
                                        }
                                        printf("\n");
                                        
                                        // Decrypt
                                        for (int j = 0; j < 256; j++) {
                                          printf("Attempt %d:\t", j);
                                          srand(j);
                                          bool success = true;
                                          for (int i = 0; i < len; i++) {
                                            int y = rand();
                                            char d = encrypted[i] ^ y;
                                            if (d != original[i]) {
                                              success = false;
                                            }
                                            printf("%02x ", (unsigned)d & 0xff);
                                          }
                                          if (success) {
                                            printf(" <-- this one!\n");
                                            return 0;
                                          }
                                          printf("\n");
                                        }
                                        return 1;
                                      }
                                      
                                        0
                                        Прозевал в условии слово DWORD, простой перебор не подойдёт. Но можно узнать ключ, поксорив первый DWORD шифра и тела, пробовать расшифровывать этим ключом следующие DWORD-ы шифра и сравнивать результат с телом:

                                        int main(void)
                                        {
                                          unsigned* original = (unsigned*)strdup("Hello, world!");
                                          unsigned* encrypted = (unsigned*)strdup((char*)original);
                                          int len = strlen((char*)original);
                                        
                                          // Encrypt
                                          int key = 232222329;
                                          srand(key);
                                          printf("Encryption:\nOriginal   keystream   encrypted\n");
                                          for (int i = 0; i < len / sizeof(unsigned); i++) {
                                            int x = rand();
                                            encrypted[i] ^= x;
                                            printf("%08x ^ %d = %08x\n", original[i], x, encrypted[i]);
                                          }
                                          printf("\n");
                                          
                                          int candidate_key = original[0] ^ encrypted[0];
                                          printf("Candidate key=%d\n\n", candidate_key);
                                          srand(candidate_key);
                                          printf("Decrypting the rest:\nCyphertext keystream   decrypted\n");
                                          for (int i = 1; i < len / sizeof(unsigned); i++) {
                                            int x = rand();
                                            printf("%08x ^ %d = %08x, expected %08x\n", encrypted[i], x, encrypted[i] ^ x, original[i]);
                                          }
                                          printf("\n");
                                        
                                          return 1;
                                        }
                                        
                                        –1
                                        >>что она рано или поздно попадет на «операционный стол» вирусному аналитику
                                        Самоуверенно как-то, на деле не всегда так. Рано или поздно Zловред может не попасть! Степень сложности Zловреда бывает разной! Для некоторых хватает автоматики, для чуть посложнее уже нужен человек чуть-чуть знающий ассемблер, но есть такие Zловреды, которые требуют достаточно много времени на анализ и выделение времени очень дорогостоящим специалистом из антивирусной компании. Таких Zловредов очень много! Такие файлы приходится ложить в очередь к экспертам и пока у этих экспертов дойдут руки, Zловред может быть уже модернизирован и улучшен.

                                        Самое интересное то, что по ту сторону стоят порою весьма не глупые парни! Они пишут достаточно серьезные решения. У них тоже многое автоматизировано и налажено.

                                        Я к тому что не стоит читателю статьи не следует покупаться на процитированные мною слова из статьи. Вашу голову при работе за компом ни один антивирус не заменит! Цените Ваше время!!! Ваши сэкономленные пару секунд от броска файла в виртуальную машину могут акнутся часами или днями восстановления вашей рабочей среды.
                                          0
                                          Ну формально Ваше высказывание никак не противоречит цитате =) «Рано или поздно» можно истолковать и как «наверное, в следующей жизни...» А «попадет на стол» != «алгоритм будет восстановлен».
                                          0
                                          Какой смысл искать ключ расшифровки, если вы имеете не только зашифрованную строку но и саму программу? Если в ней используется xor, я уверен что функция расшифровки тоже там. Если не там, то поверьте, там будет уж точно не xor :)
                                            0
                                            Если речь идёт о примере в самом конце, то ключ расшифровки нужен для того, чтобы определить, находится ли в памяти упомянутая программа. В памяти она хранится в зашифрованном виде, ключ неизвестен (и хорошо спрятан, лень искать).

                                            Из-за слабости использованного шифрования вместо перебора всех возможных значений ключа (что слишком долго) достаточно перебрать 256 значений. Ещё быстрее зашифровать сигнатуру 256 ключами и искать эти зашифрованные строки алгоритмом Ахо-Корасика, который ищет все строки сразу, в один проход.
                                            0
                                            Интересно, а каким образом идет анализ заразы на веб-страницах? Я про всевозможные iframe/plugin detect (js). Идет анализ кода или анализ «поведения» браузера? Несколько раз загружал на вирустотал страничку (html), в которой был зловред по мнению Касперского, но остальные антивирусы его не обнаруживали. Я не про jar/payload, а про html/js (детект плагинов, iframe).
                                              0
                                              Комбинирование

                                              Например, они комбинируют методы. Запишут урл задом наперед, да еще через байт, а потом еще поксорят с переменным ключом. Да, некоторую автоматику это может сбить с толку. По факту же это не мешает успешно детектировать такие файлы. А как только зловреда разберет вирусный аналитик, он добавит в дешифровщик метод Reverse(Unicode(LinearXor(stream))), после этого все старые и новые версии расшифровываются автоматически.

                                              В частности интересует «По факту же это не мешает успешно детектировать такие файлы.» Например просто поксорим, да поменяем местами символы по pos = (pos+1)%groupLength, например группами по 3. Получим вместо ЧЛЛП┼╨╨ какой-нибудь ЛЧЛ╨П┼╨. И как отсюда очевидно достать? Я конечно не спорю, что XOR — это не самый сильный вид шифрования, но мне кажется, для облома автоматической расшифровки его достаточно…

                                              Only users with full accounts can post comments. Log in, please.