Этот пост является текстовой версией выступления, которое я провел на 35-м Chaos Computer Congress в конце 2018 года.
И так я должен признать, что MS-DOS слегка возмущает меня, несмотря на то, что вредоносные программы MS-DOS всегда в некоторой степени очаровывали меня, но сначала мы должны спросить: «Что такое DOS?»
- DOS — это одна из версий CP/M, еще одной очень старой операционной системы
- Семейство DOS охватывает широкий спектр поставщиков, просто потому, что это DOS, не означает, что он будет работать на 8086 CPU или лучше
- Некоторые из этих поставщиков DOS имеют совместимость API, а это означает, что некоторые из них используют вредоносное ПО!
Видео выступления:
Пост написан при поддержке компании EDISON Software, которая разрабатывает приложение для виртуального мобильного оператора и занимается разработкой и сопровождением сайтов на Python.
Но на самом деле, большинство наших воспоминаний об эре DOS — это эстетика того, как выглядели компьютеры того времени:
Это эра «вычислений бежевого цвета» и клавиатуры Model M, которая может быть известной или печально известной в зависимости от того, нравится ли вам шумная клавиатура или нет.
У некоторых из нас могут быть воспоминания об использовании DOS, а некоторые все еще могут использовать DOS!
Например, Джордж Р. Мартин, который написал «Игру престолов», по слухам, использовал Wordstar в DOS для написания книги!
Мы также не можем пропустить QBASIC, для многих это было бы их первым знакомством с программированием!
Но иногда жизнь с использованием DOS была не так хороша, иногда вы использовали DOS, и внезапно происходили подобные вещи. В этом примере проигрывается небольшая мелодия во время печати, так что это может быть очень неловкой ситуацией в офисной среде.
Некоторые из них более «милые», в этом случае, например, проезжает нарисованная символами ascii машина скорой помощи, а затем происходит запуск программы, которую вы хотели открыть, в худшем случае с легкими неудобствами.
Благодаря куче архивистов для вредоносных программ, работающие под названием VX Heavens, у нас есть хороший исторический архив вредоносных программ DOS, или, по крайней мере, до тех пор, пока украинская полиция не совершит рейд на сайт:
В пятницу, 23 марта, сервер был захвачен полицией в связи с уголовным расследованием (статья 361-1 Уголовного кодекса Украины — создание вредоносных программ с целью их продажи или распространения) на основании чьей-то подсказки. о «размещении в свободном доступе вредоносного программного обеспечения, предназначенного для несанкционированного взлома компьютеров, автоматизированных систем, компьютерных сетей».
К счастью, на популярных торрент-сайтах все еще есть копии базы данных сайтов, которые могут предоставить нам прекрасный набор данных:
$ tar -tvf viruses-20070914.tar | wc -l
66714
$ ls -alh viruses-20070914.tar
6.6G viruses-20070914.tar
Однако, чтобы начать изучать эти образцы, нам нужно сначала понять типичный поток распространения этих образцов, учитывая, что эти программы работали в доинтернетную эпоху:
После того, как вы получите зараженный файл в своей системе и запустите его, вредоносная программа будет либо активно искать, либо устанавливать перехватчики системных вызовов для программ, которые вы запускаете. Он часто делает это тонким и невидимым способом, чтобы избежать обнаружения. Важность тонкости важна, поскольку для распространения этой вредоносной программы необходимо либо передать ее в другую систему с помощью носителя (дискеты), либо загрузить в другую точку распространения, например BBS.
Во время выполнения вредоносная программа имеет два варианта; она может либо оставаться скрытой и заражать новые файлы, либо отображать полезную нагрузку.
Некоторые полезные нагрузки довольно красивые! В приведенном ниже примере используются необычные функции, такие как 256 цветов:
Или этот, который играет с вашим буфером экрана:
Однако по большей части вредоносная программа будет молчать и пытаться найти файлы для заражения. Заражение большинства файлов очень простое, например, если вы просматриваете COM-файл как длинную ленту машинного кода:
Затем «все, что вам нужно сделать» — это вставить JMP в начале программы и добавить данные в конец программы. Это будет выглядит примерно так:
Некоторый код был умнее и находил «пустое место» в двоичном файле и записывал себя там, что препятствовало увеличению размера двоичного файла, что, возможно, означало, что антивирус может использовать красный флаг.
Однако, ранее, я также упомянул перехват системных вызовов. Несмотря на то, что среда выполнения MS-DOS очень проста и практически не защищена (вы можете тривиально загрузить Linux из COM-файла). Она по-прежнему содержит полный API, чтобы приложениям не требовалось иметь собственной реализации файловой системы. Вот как выглядят некоторые функции syscalls:
Они работают, вызывая программное прерывание, в котором программа попросит процессор перейти к другому разделу системной памяти для обработки чего-либо:
Однако MS-DOS также предлагает возможность добавлять/изменять эти вызовы (с помощью другого вызова), позволяя расширить систему, чтобы новые драйверы могли загружаться во время выполнения. Однако это также идеальное место для добавления перехватов вредоносных программ:
Это был хорошо используемый трюк, поскольку вы могли перехватить вызов «Открыть файл», а затем использовать его, чтобы обнаружить новые исполняемые файлы в системе… и заразить их.
В качестве быстрого примера того, как они используются, давайте рассмотрим простую программу «Hello World»:
Как мы видим, здесь есть два вызова типа
int
. Мы используем 21h
(h = hex) в качестве основного номера системного вызова, и мы можем указать, какое действие мы хотим, чтобы MS-DOS выполнял, на основе значения Ah
В этом случае программа делает вызов для печати строки, а затем завершает работу с кодом возврата 0 (неустановленным).
Как уже упоминалось ранее. Когда вы вызываете int 21h, центральный процессор будет искать в таблице IVT, куда переходить, внутри этого обработчика часто находится сегмент типа маршрутизатора, который направляет различные основные вызовы, в случае Int 21h он направляет к различным функциям на основе значение ah. Как только мы доберемся до места, фактический обработчик вызова будет иметь дело с поставленной задачей, затем он запустит iret, чтобы вернуться к выполнению основной программы, часто оставляя после себя регистры о результатах вызова:
Так. Если мы хотим увидеть все системные вызовы, которые запускала программа, мы можем установить точку останова на начало обработчика прерываний и проверить, каково значение ah:
Мы делаем это потому, что обработчик прерываний всегда находится в фиксированном месте в MS-DOS (это намного раньше эры ASLR и Kernel ASLR), а местоположение программы — нет.
Как только мы запустим его, мы сможем увидеть вызовы, сделанные этим образцом. В то время как мы можем видеть на экране, что он только распечатал уведомление о файле Goat (Goat — это файл, предназначенный для заражения, как жертвенный козел). Мы также видим, что эта программа делает больше, чем просто печатает строку. Он проверяет версию DOS (вероятно, для проверки совместимости), а затем открывает, читает и записывает данные!
Это интересно! Но мы хотели бы узнать больше о том, что делают системные вызовы выделенные красным, так как они должны иметь входные данные для таких вещей, как имена файлов и данные для записи в файлы/вывод на экран.
Для этого нам нужно взглянуть на другие регистры во время syscall:
Используя «Print String» в качестве простого примера, мы можем увидеть, как выглядит использование:
Что такое DS:DX? Почему здесь два регистра, и как мы получаем данные из них?
Для этого нам нужно немного больше понять о процессоре 8086.
Процессор 8086 — это 16-битный ЦП, но с 20-битной адресацией памяти. Это означает, что процессор может хранить только значения, которые указывают на 64 КБ, это проблема, когда объем памяти составляет до 1 МБ.
Чтобы обойти это, нам нужно понять регистры сегментации:
Процессор 8086 имеет 4 регистра сегментации, о которых нам нужно позаботиться:
- CS — сегмент кода
- DS — сегмент данных
- SS — сегмент стека
- ES — дополнительный сегмент (на случай, если вам понадобится еще один, чтобы обойти разные ситуации)
Существует целый ряд других регистров общего назначения, которые избавляют вас от чрезмерного использования памяти и позволяют передавать параметры другим функциям.
Сегментация регистрирует работу, меняя блок в ОЗУ:
Это позволяет 16-битному ЦП видеть все 20 бит ОЗУ, гарантируя, что для каждого значения DS блок смещается на 16 байтов.
В случае этого вызов DS используется в качестве указателя внутри 16-битного окна относительно того, где находится начало строки. Затем строковый принтер будет сканировать, пока не найдет символ $, а затем остановится. Это похоже на другие системы, которые используют нулевой байт вместо $.
С возрастом ISA x86 мало что изменилось, вместо того, что размер битов процессоров вырос, те же регистры стали шире.
Итак, с этими знаниями, мы можем создать список «задач» для отслеживания этих программ:
С помощью этой настройки мы можем бросить несколько больших компьютеров на проблему на несколько часов и собрать результаты!
И мы получаем …
Ничего такого.
Это разочаровывает.
We burned at least a hamsters worth of power and got almost no cool activations! (Хз, как это перевести)
Если мы посмотрим на некоторые образцы, мы увидим здесь дымящийся пистолет. Приличный кусок образцов проверяет дату или время.
Если мы посмотрим на документацию для этих вызовов, то увидим, что системный вызов возвращает значения в виде регистров для программы:
Таким образом, мы можем брутфорсить их! Все, что нам нужно сделать, это что-то вроде этого:
Но есть одна проблема с этим методом.
Этап тестирования примера занимает около 15 секунд, поскольку в нем используется полный процесс эмуляции qemu, и для полного запуска программы в виртуальной машине может потребоваться до 15 секунд. Так как DOS не имеет функций энергосбережения, это означает, что когда DOS находится в режиме ожидания, он находится в занятом цикле
Таким образом, мы могли бы взглянуть на эту проблему по-другому, посмотрев, какой код будет выполняться после запроса даты/времени.
Поскольку наш трассировщик находится в обработчике прерываний, мы не знаем из коробки, где находится программа:
Для этого нам нужно взглянуть на стек, где нас ожидают регистры CS и IP!
Как только мы возьмем эти два регистра из стека, мы можем использовать их для получения кода возврата, чтобы наш контрольный список выглядел следующим образом:
После того, как мы сделали это и повторили тестирование набора данных, мы увидим, как выглядит часть кода возврата!
Вот образец одного. Здесь мы видим, что проводится сравнение для DL и 0x1e.
Если мы посмотрим на нашу документацию, то увидим, что DL — это день месяца, то есть мы можем проанализировать три верхних кода операции следующим образом:
Мы могли бы пойти и вручную просмотреть все это, но есть много этих образцов, которые проверяют время, около 4700:
Поэтому вместо этого нам нужно сделать что-то другое. Нам нужно что-то написать… Нам нужно написать …
Наихудший в мире эмулятор x86, получивший название BenX86, — это эмулятор, разработанный именно для наших нужд, и не более того:
Но у него есть некоторые преимущества в его скорости
Мы добавили 10 тыс. различных тестов выполнения, основанных на путях, которые мы нашли с помощью брут форса с использованием BenX86. Итак, я закончу с некоторыми из моих любимых открытий, которые активированы временем:
Этот образец активируется в день нового года и вешает вашу систему после отображения приветствия. Это может быть хорошо, если вы застряли в офисе на новый год, или может быть плохо, если вам действительно нужно что-то делать в новогодний день
Этот пример меня очень удивил. Он активируется в начале 1995 года и информирует пользователя обо всех зараженных файлах, которые он заразил, а затем удаляет вирус(удаляя переход в начале), а затем больше ничего не делает. Хотя по какой-то причине в нем говорится, что вы должны купить McAfee, очевидно, что это сообщение не устарело.
Это, честно говоря, действительно смущает меня, 8 ноября любого года, он превратит все 0 в системе в крошечные глифы «ненависти». Это действительно смущает меня, если вы знаете, почему вам это нужно, дайте мне знать …
Это, возможно, мой кошмарный сон, когда после запуска любой программы, это вывод сообщения о том, что она не смогла съесть ваш основной диск. Это было бы невероятно тревожно видеть на ровном месте.
Заканчивая, у нас есть то, что есть Navy Seal Copypasta версия вредоносного ПО для DOS. Не уверен, что этот автор не любит Аладдина, но что бы вы ни делали, вы, человек.
Если вас интересует код, который запускался в этой статье, я выпустил свой инструментарий на github, без каких-либо гарантий. Если вы хотите создать этот код самостоятельно, вам нужно будет поработать, чтобы убедиться, что он работает с вашей установкой MS-DOS ( исправление точки останова обработчика)
Однако, если вы просто смотрите, чтобы увидеть то, что я увидел, глядя на этот проект, я заархивировал веб-интерфейс здесь: dosv.benjojo.co.uk
До скорого!
rsashka
Очень тяжело читать.
Хотя мне данная тема интересна, но я так и не смог осилить до конца.
Материала много, но очень тяжело часто переключаться с картинок на текст.
И сразу непонятно, с анимацией картинка или без оной.
А ждать гифки, но не дождаться — очень сильно раздражает.
MagisterLudi Автор
Видео выступления:
ladutsko
Software archaeology
Даешь продолжение про загрузочные вирусы!
ps про OneHalf было
XRain
Здесь нельзя не вспомнить прекрасного ютубера, который делает обзоры на вирусы (в основном как раз под DOS): www.youtube.com/user/danooct1
LevOrdabesov
Это подстрочник, а не перевод.
«мы увидим здесь дымящийся пистолет»…
ClearAirTurbulence
Мне больше понравилось
ИМХО было бы логичнее договориться с докладчиком и опубликовать без перевода на англойзычном хабре. Правда, вряд ли кто-то бы прочитал там это. И это, кстати, проблема — пока нет настройки, показывающей смешанную ленту (рус+англ), английский хабр останется невостребованным, и в итоге умрёт.
Gobl1n
В смысле нет настойки? Там же чекбоксы, и можно выбрать и русский, и английский контент одновременно
saboteur_kiev
IMHO слишком много картинок, чтобы объяснить что такое прерывания, резидентная программа и что формат .com файла позволял добавлять в него произвольный код (вирус), без особых проблем.
Тема интересная, но было бы интересно углубиться в войну тогдашних вирусов и антивирусов.
Как вирусы пытались подчистить за собой следы, используя простейшую компрессию (чтобы сохранить длину файла), используя шифрование, чтобы усложнить «лечение файла». Это сейчас кажется странным, что вирус мог внедрить в файл код, а антивирус мог его оттуда извлечь и «восстановить файл» — нынче файлы восстанавливают разве что после крипторов.
Как залезть в бутсектор, выполниться раньше OS и поправить прерывания, чтобы антивирус не знал что в памяти кто-то закрывает ему глаза.
Чтоже касается забавных (недеструктивных) эффектов некоторых вирусов — это вообще отдельная тема и отдельные коллекционеры.
JerleShannara
Бррр, как вспоминаю болгарских полиморфов, так сразу противно становится.
saege5b
Ещё был тонкий момент по «тёплой» и «холодной» перезагрузке.
И не все файлы «вылечивались», но здорово помогал АДинф.
GCU
Вспомнился весёлый «вирус» который портил резервную копию таблицы FAT.
Веселье начиналось когда дисковая утилита бралась «починить» основную таблицу.
teecat
Прогноз из 1990го!
Веселые были времена. Антивирусы распространяли обновление быстрее вирусов — пока последние доходили ручной передачей до всех углов страны, там их ждал уже антивирус
И слово хакер знали еще не все
А вот как навести на ложный след придумали уже тогда
Линк 1, 2, 3