EICARテストファイルを深掘りしてみる

# はじめに
アンチウィルス対策製品の動作確認に使われたりするやつです。
EICAR STANDARD ANTIVIRUS TEST FILE
EICAR標準アンチウィルステストファイル

省略されて、EICARやEICARテストファイルみたいに呼ばれることもあります。
以下からダウンロードできます。

https://www.eicar.org/download-anti-malware-testfile/

# 目的1
15年くらい前にパソコンを触り始めたときにマルウェアに興味があって色々ググっていてこれを見つけた
当時はdebug.exeがOSに付属していたり、普通に16ビットリアルモードでDOS互換プログラムが動作したのでこのファイルを動かした記憶があった。
ただ、それなりに年月が経過していて、実行できたっけなぁというくらいにしか記憶に残ってなかったので改めてEICARと厳粛に向き合ってみようと思った。

# 目的2
日本語訳してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/190a4b48-357a-98b2-befc-24f4da2541f5.png)

DOSプログラムですね。
まぁ実行できるのは記憶に有ったから良いとして、どうせなら解析してみようぜと思っている。

# まずは結論から（解析方法は続きにあります）
どういうプログラムが書かれているのかというところに疑問を持っている。

`X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*`

この文字列は以下のように3分割できる。

1. `X5O!P%@AP[4\PZX54(P^)7CC)7}$`
2. `EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$`
3. `H+H*`

1：色々やっているけど、一番の目的は3番にある「出力命令（print）」と「プログラム終了命令（exit）」をデコードするためのコードが書かれている
2：3の命令で出力するための文字列（`EICAR-STANDARD-ANTIVIRUS-TEST-FILE!`が出力される）
3： INT 21h(DXレジスタを"$"終端の文字列へのポインタとみなし標準出力へ出力する命令)
　　また、INT 20h(exit)命令が、エンコードされて記述されている。

# 解析編
まずは実行してみよう。
DOSBox-XというDOSエミュレータツールがあるので、それをインストールして起動して実行してみる。

https://dosbox-x.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/8ed076f1-d872-ba97-4432-60bda4e1eb2a.png)
はい、出来ましたね。

とりあえずGhidraでリバースしてみる。ツールの使い方のような決まりきった手順は省略する。
一応画像においても、1～3がどこに該当するのかは明示しておこうと思う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/a34dd64e-d6b4-5018-3e1e-aa468fe041f7.png)

あとは出てきたアセンブリ（16bit Realmode）を読んでいくだけ。
```
0000:0100  58              POP        AX　// AX=0（CP/M互換のための値=0をスタックから取り出している）
0000:0101  35  4f  21      XOR AX ,0x214f // AX=0x214F
0000:0104  50              PUSH       AX // スタックに0x214Fを入れる
0000:0105  25  40  41      AND  AX ,0x4140 // 0x140 = 0x214F & 0x4140
0000:0108  50              PUSH       AX // スタックに0x140を入れる
0000:0109  5b              POP        BX // BX = 0x140
0000:010a  34  5c          XOR   AL ,0x5c // AL=0x11=0x40^0x5C (AX=0x11C)→表示する文字列のアドレス
0000:010c  50              PUSH  AX // 0x11Cをスタックに入れる
0000:010d  5a              POP   DX // DX = 0x11C // 表示する文字列のアドレス
0000:010e  58              POP   AX // AX = 0x214F
0000:010f  35  34  28      XOR   AX ,0x2834  // AX = 0x97B = 0x214F^x2834
0000:0112  50              PUSH  AX 
0000:0113  5e              POP   SI // SI = 0x97B
0000:0114  29  37          SUB   word ptr [BX ],SI // 0x21CD = 0x2B48 - 0x97B
0000:0116  43              INC   BX
0000:0117  43              INC   BX
0000:0118  29  37          SUB   word ptr [BX ],SI // 0x20CD = 0x2A48 - 0x97B
0000:011a  7d  24          JGE   0x0140  // 直前の引き算の結果が0以上の場合0x0140の処理へ分岐する
0000:011c  DB "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$" // 表示する文字列（0000:010aで計算した値）
0000:0140  48              DEC   AX // H+ の部分
0000:0141  2b  48  2a      SUB   CX ,word ptr [BX  + SI  + 0x2a ] // H* の部分
```
## 011cまで実行されたときのダンプ

```
0000:0100  58              POP        AX　// AX=0（CP/M互換のための値=0をスタックから取り出している）
0000:0101  35  4f  21      XOR AX ,0x214f // AX=0x214F
0000:0104  50              PUSH       AX // スタックに0x214Fを入れる
0000:0105  25  40  41      AND  AX ,0x4140 // 0x140 = 0x214F & 0x4140
0000:0108  50              PUSH       AX // スタックに0x140を入れる
0000:0109  5b              POP        BX // BX = 0x140
0000:010a  34  5c          XOR   AL ,0x5c // AL=0x11=0x40^0x5C (AX=0x11C)→表示する文字列のアドレス
0000:010c  50              PUSH  AX // 0x11Cをスタックに入れる
0000:010d  5a              POP   DX // DX = 0x11C // 表示する文字列のアドレス
0000:010e  58              POP   AX // AX = 0x214F
0000:010f  35  34  28      XOR   AX ,0x2834  // AX = 0x97B = 0x214F^x2834
0000:0112  50              PUSH  AX 
0000:0113  5e              POP   SI // SI = 0x97B
0000:0114  29  37          SUB   word ptr [BX ],SI // 0x21CD = 0x2B48 - 0x97B
0000:0116  43              INC   BX
0000:0117  43              INC   BX
0000:0118  29  37          SUB   word ptr [BX ],SI // 0x20CD = 0x2A48 - 0x97B
0000:011a  7d  24          JGE   0x0140  // 直前の引き算の結果が0以上の場合0x0140の処理へ分岐する
0000:011c  DB "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$" // 表示する文字列（0000:010aで計算した値）
0000:0140  cd 21           INT 21h // DXレジスタが指すメモリにある$で終わる文字列を表示する
0000:0141  cd 20           INT 20h // exitしておわり
```

# まとめ
EICARは単なるシグネチャ文字列ではない。
自身をメモリ上で書き換えるポリモーフィック型マルウェアを模した列記とした実行可能なプログラムである。


ということでした。おわり。
明日から使える無駄知識でした。