PythonでWindows形式のイベントログであるevtxデータをCSVに変換してみました


## 概要

NetAppファイルサーバのイベントログであるevtxデータを サクッと確認するために CSV形式 へ変換保存するプログラムです。

### 実行環境

macOS Ventura 13.0 
python 3.8.12

### 事前準備

事前に以下のモジュールをインポートしておきます。

```
$ pip install python-evtx
```

### 実行プログラム

```python:extviewer2.py
import argparse
import time
from Evtx.Evtx import Evtx
import pandas as pd

INPUT_FILE = './20230511_13.evtx'


# CSVファイルへの変換
def evtx_to_csv(evtx_file):
    # イベントスキーマーの定義
    SCHEMA = 'http://schemas.netapp.com/events/event'

    #　カラムの定義
    EventID = []
    EventName = []
    TimeCreated = []
    Computer = []
    SubjectIP = []
    DomainName = []
    UserName = []
    ObjectType = []
    ObjectName = []
    
    # イベントファイルのオープン
    with Evtx(evtx_file) as log:

        # イベントレコードの取得
        for record in log.records():
            elm = record.lxml()

            # # 個々のrecord構造の確認（最初に確認しましょう）
            # print(record.xml())

            EventID.append(elm.xpath("//event:EventID", namespaces={"event":SCHEMA})[0].text)
            EventName.append(elm.xpath("//event:EventName", namespaces={"event":SCHEMA})[0].text)
            TimeCreated.append(elm.xpath("//event:TimeCreated", namespaces={"event":SCHEMA})[0].get("SystemTime"))
            Computer.append(elm.xpath("//event:Computer", namespaces={"event":SCHEMA})[0].text)
            SubjectIP.append(elm.xpath("//event:Data", namespaces={"event":SCHEMA})[0].text)
            DomainName.append(elm.xpath("//event:Data", namespaces={"event":SCHEMA})[5].text)
            UserName.append(elm.xpath("//event:Data", namespaces={"event":SCHEMA})[6].text)
            ObjectType.append(elm.xpath("//event:Data", namespaces={"event":SCHEMA})[8].text)
            ObjectName.append(elm.xpath("//event:Data", namespaces={"event":SCHEMA})[10].text)

        # データフレームを作成
        df = pd.DataFrame({
            'EventID' : EventID,
            'EventName' : EventName,
            'TimeCreated' : TimeCreated,
            'Computer' : Computer,
            'SubjectIP' : SubjectIP,
            'DomainName' : DomainName,
            'UserName' : UserName,
            'ObjectType' : ObjectType,
            'ObjectName' : ObjectName
        })

        # # 画面への表示
        # print(df.to_markdown())

        # # CSVファイルへの書き込み
        # output_file = evtx_file + '.csv'
        # df.to_csv(output_file, header=True, index=True)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='extvをjson形式にするプログラム')
    parser.add_argument('-i', '--input', type=str, default=INPUT_FILE, help='対象となる extvファイル')
    args = parser.parse_args()

    # 経過時間の計測開始
    start = time.time()
    evtx_to_csv(args.input)
    generate_time = time.time() - start

    print("\n処理時間:{0}".format(generate_time) + " [sec]\n")
```

### プログラムの実行

.evtxの全体構造を知るために「print(record.xml())」のコメントを外して実行してみます。

```
$ python extviewer2.py
    :
    :
<Event xmlns="http://schemas.netapp.com/events/event"><System><Provider Name="NetApp-Security-Auditing" Guid="{3CB2AAAA-FEFE-4A4A-BDBD-DCF422F33333}"></Provider>
<EventID>4663</EventID>
<EventName>Write Object</EventName>
<Version>101.2</Version>
<Source>CIFS</Source>
<Level>0</Level>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<Result>Audit Success</Result>
<TimeCreated SystemTime="2023-05-09 13:07:44.935497"></TimeCreated>
<Correlation></Correlation>
<Channel>Security</Channel>
<Computer>FAS2750A/kg_domain</Computer>
<ComputerUUID>1c3a88ff-bbac-1111-7070-00a098000bee/55239d44-9393-1111-bebe-000098db8bee</ComputerUUID>
<Security></Security>
</System>
<EventData><Data Name="SubjectIP" IPVersion="4">10.2.1.6</Data>
<Data Name="SubjectHostname" Source=""></Data>
<Data Name="SubjectUnix" Uid="0" Gid="1" Local="false"></Data>
<Data Name="SubjectUserSid">S-1-5-22-888882222-1115556666-353845456-500</Data>
<Data Name="SubjectUserIsLocal">false</Data>
<Data Name="SubjectDomainName">NETAPP</Data>
<Data Name="SubjectUserName">testuser</Data>
<Data Name="ObjectServer">Security</Data>
<Data Name="ObjectType">File</Data>
<Data Name="HandleID">00000000000aaa;00;000999ee;0cdb8844</Data>
<Data Name="ObjectName">(zidoma);/00_Develop/HeaderEncryption/testdir/rs-audit.db.encryptedrn</Data>
<Data Name="WriteOffset">0</Data>
<Data Name="WriteCount">4096</Data>
</EventData>
</Event>
    :
    :
処理時間:0.23432326316833496 [sec]
```

.evtxデータを画面に表示するために「print(df.to_markdown())」のコメントを外して実行してみます。

```
$ python extviewer2.py
|    |   EventID | EventName             | TimeCreated                | Computer           | SubjectIP   | DomainName   | UserName      | ObjectType                          | ObjectName                                                            |
    ： 
    ：
| 10 |      4663 | Read Object           | 2023-05-09 13:07:44.851498 | FAS2750A/kg_domain | 10.2.1.6    | NETAPP       | testuser      | File                                | (zidoma);/00_Develop/HeaderEncryption/testdir/rs-audit.db.encryptedrn |
| 11 |      4663 | Write Object          | 2023-05-09 13:07:44.935497 | FAS2750A/kg_domain | 10.2.1.6    | NETAPP       | testuser      | File                                | (zidoma);/00_Develop/HeaderEncryption/testdir/rs-audit.db.encryp
    ： 
    ：
処理時間:0.15549492835998535 [sec]
```

.evtxデータをCSVに変換保存するために、「df.to_csv(output_file, header=True, index=True)」あたりのコメントを外して実行してみます。

```
$ python extviewer2.py

処理時間:0.13499021530151367 [sec]
```

作成されたCSVファイルを確認します。

```
$ vim 20230511_13.evtx.csv
-------------------------------
,EventID,EventName,TimeCreated,Computer,SubjectIP,DomainName,UserName,ObjectType,ObjectName
    ： 
    ：
10,4663,Read Object,2023-05-09 13:07:44.851498,FAS2750A/kg_domain,10.2.1.6,NETAPP,testuser,File,(zidoma);/00_Develop/HeaderEncryption/testdir/rs-audit.db.encryptedrn
11,4663,Write Object,2023-05-09 13:07:44.935497,FAS2750A/kg_domain,10.2.1.6,NETAPP,testuser,File,(zidoma);/00_Develop/HeaderEncryption/testdir/rs-audit.db.encryptedrn
    ： 
    ：
```

### まとめ

NetAppファイルサーバのイベントログの必要な部分のデータを選択し、CSVファイル形式で保存しました。これでサクッとイベントログの監査がやりやすくなりました。

### 参考記事

以下の記事を参考にさせていただきました。感謝申し上げます。
[.evtxファイルをPythonで解析する](https://qiita.com/kasanma3104/items/6971d3e7d09de134da37)