- [Duke's Virus Labs #9] - [Page 25] - Полиморфизм для Word97 (c) by CyberShadow/SMF Привет всем! Эта статья посвящена написанию полиморфов высокого уровня на VB, конкретно на Word97Basic, но теория подойдет и для Excel и для прочих офисных приложений. Я предполагаю, что человек читающий эту статью достаточно продвинут в написании программ на VB, например умеет создавать случайные имена типа jjkJIjlJ3 и имеет опыт написания VB вирусов. Итак, на данный момент есть множество полиморфов на VB, но подавляющее большинство из них являются не совсем полиморфами, то есть представляют из себя конструкции типа: 'kj2atlk3jOIJOJ6LkjrlJlkjLjrk22 For i=1 To n 'hjkljhlkjhl324jhlkqj3h5jkqhb MsgBox i 'jhjehodhfgjnkbkjwekjt25jkbkjbKJBKJB Next В зависимости от алгоритма и фантазии автора вируса эти строки могут содержать в себе различные символы, но основная идея остается той же - вставлять между строками строки переменной длины с различными символами. Недостатки ясны - стоит отсеять все ремарки, и voila! Вот ваш вирус. Кроме того, большинство полиморфов модифицируют весь свой код, не производя никаких проверок, что очень быстро делает вирус просто огромным по размеру, и либо преращает его дальнейшее распространение, либо ясно показывает, что файл поражен вирусом :(. Хотя сбылась мечта всех вирмакеров, модифицировать весь код вируса, но толку принесло совсем мало :(. Зачем изобретать велосипед? Есть множество хороших алгоритмов для создания защищенных вирусов. Причем эти алгоритмы давно используются для создания вирусов под DOS и Windows. Это старые добрые шифрующие алгоритмы различной сложности. Существует множество статей о создании шифрованного вируса под Word, но тем не менее, я коснусь этой темы (кратко). Зашифрованное тело можно хранить, как минимум двумя способами: 1. Создавая переменную в которой храниться зашифрованной тело вируса: CryptedVirusBody="hl23kj6liuhrkljhluhilUHLIhliu" CryptedVirusBody=CryptedVirusBody+"sdg3wW#HSDsehEh" 2. Храня зашифрованное тело вируса прямо в исходном коде: Private Sub CryptedVirusBody() 'jl;kj2lkj;Ij)JHhh5kjhKJhKJ5huoho 'LKjlkigsohjwhj4klhLhLKhlwktioh 'JklwjijgnLnlniowngoi End Sub Разумеется, при разных способах хранения, существуют разные способы расшифровки, для первого способа вы пишите декриптор работающий напрямую с переменной, в которой храниться зашифрованное тело вируса. Для второго же способа понадобиться алгоритм работающий напрямую с исходным кодом, то есть что-то вроде: c=lines(j,1) if mid$(c,1,1)="'" then ... расшифровка ... ReplaceLine j, EncryptedVariable End If Где j - номер строки кода. У обоих способов есть свои преимущества и недостатки, у первого способа это необходимость выработки алгоритма который вставляет куда-то расшифрованную строку, у второго - некоторая громоздкость кода для работы с поиском строк. Выбирайте любой. Существуют еще способы хранения зашифрованных строк, но эти самые простые. Вот, вкратце и все о шифровании тела вируса. Теперь, о самом интересном: о полиморфах. Рассмотрим следующий пример: For i=1 to n 'часть расшифровщика; For j=1 to 12425 '-+ eyeu=12 ' | do while eyeu<234 ' | мусор; eyeu=eyeu+43 ' | loop ' | next '-+ lkj=ljk+1 'часть расшифровщика; jkhlk=142 ' -+ if sdfg", "=" и сравнение с RND. Для работы с работы с переменными следующие варианты: var1=random var1=var1+var2 var1=var2+var3 var1=var2 и т.д. Вот и все о рекурсивных полиморфных алгоритмах. Но! После того, как вы написали программу генерирующую полиморфный расшифровщик, сразу же всплывает масса проблем о которых вы раньше не подозревали: длина одной сроки не может быть больше 1024 символов, размер одной процедуры не может быть больше 64 килобайт. И та и другая проблема сказывается на возможностях полиморфа. Итак, вы должны внести корректировку по длине строки, на полиморфных блоках это не сказывается, а вот если вы храните зашифрованное тело вируса в строковых переменных, тогда придется делить переменную на части. Размер полиморфа можно коррекитровать уменьшая степень рекурсии. Есть другой вариант, перемешать строки расшифровщика и добавить в него вызов процедур, тогда размер вируса равномерно распределиться между процедурами и и одна из них не будет больше 64К. Как перемешать, спросите вы? Тогда ведь структура расшифровщика нарушиться и он будет представлять собой просто набор нерабочих комманд. Приведу пример: private sub try() goto loop1 loop2: msgbox "метка номер двас :)" goto loop3 loop1: msgbox "метка номер раз" goto loop2 loop3: end sub Что сделает такая программа когда вы ее запустите? Правильно, сначала напечатат про метку номер раз, а потом про метку номер двас. Но ведь метка номер два у нас идет первой? Как же так? Поняли? Та же самая идея в полиморфе, имеется куча премешанных комманд, которые после выполнения уходят в случайное место кода, где уже подготовлена следующая комманда для выполнения. Кроме того, чтобы не перегружать размер подпрограммы, мы с чистой совестью можем сделать вызов процедуры вместо GOTO, разумеется процедуру нужно вызывать со всеми переменными используемыми в расшифровщике, либо объявлять их глобальными, но это уже мелочи. Теперь о возможных глюках: 1. Длина одной строки должна быть меньше 1024 символов; 2. Размер одной процедуры должен быть меньше 64К; 3. Переменные используемые в расшифровщике должны быть доступны в любой подпрограмме; 4. Переменные используемые в расшифровщике и используемые в "мусоре" не должны совпадать, иначе расшифровка пойдет неправильно; 5. Циклы в "мусоре" не должны быть очень большими, иначе юзер может подумать, что компьютер завис; 6. Имена меток не должны совпадать с именами любых переменных; 7. Любая строка с условием должна стоять отдельно: никаких lkj=24: if jkh