Python アプリケーションのチュートリアル:パート 2

2024年4月11日

ID 201594

このチュートリアルでは、Kaspersky CyberTrace からデータを送受信する Python アプリケーションの実装方法について説明します。

このチュートリアルのパート 1 では、Kaspersky CyberTrace にデータを送信するアプリケーションについて説明します。

このチュートリアルのパート 2 では、Kaspersky CyberTrace からの受信イベントをリッスンするアプリケーションについて説明します。

はじめに

チュートリアルのこのパートでは、Kaspersky CyberTrace からの受信イベントをリッスンする Python アプリケーションを実装します。

アプリケーションには任意の名前を使用できます。このチュートリアルの例では、このアプリケーションに listen_events_cybertrace.py というファイル名を使用します。

接続設定とイベント形式について

アプリケーションは、指定したアドレスとポートでリッスンし、Kaspersky CyberTrace からの受信接続を受け入れ、受信したデータを解析します。

イベントの送信先のアドレスとポートを確認するために、[OutputSettings]→[ConnectionString]パラメータが使用されます。送信イベントのアドレスとポートは、CyberTrace Web の[Service settings]ページで表示および構成できます。

イベントの形式を確認するために、Kaspersky CyberTrace は、Kaspersky CyberTrace サービス設定情報ファイルの[OutputSettings]セクションの形式を使用します。全てのイベントが改行文字(\n)で終了する必要があります。イベント形式は、CyberTrace Web の[Event format settings]ページで構成できます。

ステージ 1。main() 関数を定義する

このステージの手順:

  1. socket モジュールをインポートします。

    Kaspersky CyberTrace との接続を確立し、データを受信するために、アプリケーションでこのモジュールからの関数を使用します。

  2. main() 関数を定義します。
  3. LISTEN_ADDR 変数と LISTEN_PORT 変数で、アプリケーションが受信イベントをリッスンするアドレスとポートを指定します。

    この情報は、CyberTrace Web の[Service settings]ページの[Service sends events to]領域で取得できます。

    import socket

     

    LISTEN_ADDR = "192.0.2.105"

    LISTEN_PORT = 9998

     

    def main():

    pass

    if __name__ == '__main__':

    main()

ステージ 2。サーバーコードを追加する

このステージの手順:

  1. main() 関数で、指定したアドレスとポートでサーバーを起動するコードを追加します。

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    print("Starting on {}:{}".format(LISTEN_ADDR, LISTEN_PORT))

    server_socket.bind((LISTEN_ADDR, LISTEN_PORT))

    server_socket.listen()

  2. 受信接続を処理するコードを追加します。

    socket.accept() 関数は、受信接続を受け入れます。この関数は、接続用の新しいソケットオブジェクト(connection 変数内)、およびもう一方の端で接続を確立したアドレス(client_address 変数内)を返します。

    このステージでは、アプリケーションは、接続から受信したデータを無視します。次のステージで、データを追加して機能を解析します。

    アプリケーションは、無限ループを開始します。これを終了するには、オペレーティングシステムに合った標準ショートカットまたはコマンドを使用します。大半のオペレーティングシステムでは、これは ^C または Control-C です。

    while True:

    connection, client_address = server_socket.accept()

    try:

    print("Connection from {}".format(client_address))

    # Add data parsing here

    finally:

    connection.close()

ステージ 3。受信データを解析する

このステージの手順:

  1. try... finally ブロックで、受信データをイベントに解析する関数を呼び出します。

    接続ごとに任意の数のイベントが送信される可能性があるため、アプリケーションは、全てのイベントが処理されるまで受信データを解析する必要があります。parse_response() 関数は、ジェネレータを返します。次に、for ループは、このジェネレータを使用して受信イベントを繰り返します。parse_response() 関数は、次のステージで実装します。

    try:

    print("Connection from {}".format(client_address))

    for event in parse_response(connection):

    print("Received:\n{}".format(event.decode()))

    finally:

    connection.close()

  2. parse_response() 関数を実装します。

    Kaspersky CyberTrace からのイベントは、改行文字(\n)で終了します。parse_response() 関数は、バッファに改行文字が含まれるまでソケット接続からバッファにデータを読み込みます。その後、バッファからイベントを分割し、このイベントを生成します。chunk_receive() 関数は、ソケット接続からのデータを繰り返します。この関数は、次のステージで実装します。

    main() 関数からの for ループが次の繰り返しに進むと、parse_response() 関数は、バッファから別のイベントを分割し、このイベントを生成します。これが不可能である場合、接続からバッファにより多くのデータを読み込みます。接続から受信したデータがなくなり、バッファ内の全てのイベントが生成されるまで、このプロセスが繰り返されます。

    def parse_response(connection):

    buff = b''

    for data in chunk_receive(connection):

    buff += data

    while b'\n' in buff:

    event, buff = buff.split(b'\n',1)

    yield event

  3. chunk_receive() 関数を実装します。

    chunk_receive() 関数は、接続から 4096 バイトのデータを読み込み、このデータを生成します。この関数は、接続から受信するデータがなくなるまでデータを返します。

    socket.recv() 関数は、接続からデータを受信します。データがない場合、この関数は、より多くのデータを受信するまで待機します。この関数は、接続が閉じられた時にゼロバイトを返すため、while ループはこの条件で終了します。

    def chunk_receive(connection):

    data = None

    while data != b'':

    data = connection.recv(4096)

    yield data

ステージ 5. (オプション)イベントを送信するアプリケーションを変更する

このチュートリアルのパート 1 で実装したアプリケーションを使用して Kaspersky CyberTrace にイベントを送信する場合、これを変更してレスポンスを待機せずにイベントを送信します。

このステージの手順:

  1. フラグを送信するアプリケーションコード内の行にコメントするか、この行を削除します。Kaspersky CyberTrace は、リスナーアプリケーションにイベントを送信するため、X-KF-ReplyBack フラグが必要なくなります。
  2. レスポンスを受信および出力する行にコメントするか、この行を削除します。

次に示すのは、アプリケーションからの try... finally ブロックと、コメントされた行です。

try:

ct_socket.connect((CYBERTRACE_ADDR, CYBERTRACE_PORT))

#ct_socket.sendall(b'X-KF-SendFinishedEventX-KF-ReplyBack')

for event in events:

print("Sending:\n{}".format(event))

ct_socket.sendall(event.encode())

#response = ct_socket.recv(16384)

#print("Response:\n{}".format(response.decode()))

finally:

ct_socket.close()

 

ステージ 6. アプリケーションを実行する

コンソールからアプリケーションを実行します:

python3 ./listen_events_cybertrace.py

アプリケーションは、Kaspersky CyberTrace からの検知イベントとアラートイベントをリッスンし、これらをコンソールに出力します。

このチュートリアルのパート 1 で開発したアプリケーションを使用して Kaspersky CyberTrace にイベントを送信する場合、これをコンソールから実行します:

python3 ./send_events_cybertrace.py

以下は、アプリケーション出力の例です。

Starting on 192.0.2.105:9998

Connection from ('192.0.2.42', 41882)

Received:

- category=KL_Malicious_Hash_MD5 matchedIndicator=776735A8CA96DB15B422879DA599F474 url=- src=- ip=- md5=776735A8CA96DB15B422879DA599F474 sha1=- sha256=- usrName=- confidence=100 MD5=776735A8CA96DB15B422879DA599F474 SHA1=3B66A1D70562E291DA023E87B349DD89DFE00213 SHA256=1963CBCBB9FDAAD45F782FAAA467EE2C115C3111C003AE14D01181880B03F6ED file_size=1431 first_seen=10.07.2015 23:53 last_seen=14.07.2020 13:35 popularity=1 threat=HEUR:Trojan.Win32.Generic

Received:

- category=KL_IP_Reputation matchedIndicator=192.0.2.1 url=- src=- ip=192.0.2.1 md5=- sha1=- sha256=- usrName=- confidence=100 category=test first_seen=01.01.2017 00:00 ip=192.0.2.1 ip_geo=ru last_seen=17.07.2020 09:02 popularity=1 threat_score=75

Received:

- category=KL_Malicious_Hash_MD5 matchedIndicator=FEAF2058298C1E174C2B79AFFC7CF4DF url=- src=- ip=- md5=FEAF2058298C1E174C2B79AFFC7CF4DF sha1=- sha256=- usrName=- confidence=100 MD5=FEAF2058298C1E174C2B79AFFC7CF4DF SHA1=D01D17F6B13C7255A234F558ED85078EA5DD3F3D SHA256=4CA914C9791CF2BF2AC69F9A2B21006F0361E247F2CE92F0A9F166DBC6B43670 file_size=1989 first_seen=10.07.2015 23:53 last_seen=14.07.2020 13:35 popularity=1 threat=HEUR:Trojan.Win32.Generic

Received:

- category=KL_IP_Reputation matchedIndicator=192.0.2.3 url=- src=- ip=192.0.2.3 md5=- sha1=- sha256=- usrName=- confidence=100 category=test first_seen=15.01.2017 00:00 ip=192.0.2.3 ip_geo=ru last_seen=17.07.2020 08:51 popularity=1 threat_score=75

パート 2 の全コード

以下は、このチュートリアルのパート 2 の全コードです。

import socket

 

LISTEN_ADDR = "192.0.2.105"

LISTEN_PORT = 9998

 

def chunk_receive(connection):

data = None

while data != b'':

data = connection.recv(4096)

yield data

 

def parse_response(connection):

buff = b''

for data in chunk_receive(connection):

buff += data

while b'\n' in buff:

event, buff = buff.split(b'\n',1)

yield event

 

def main():

 

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print("Starting on {}:{}".format(LISTEN_ADDR, LISTEN_PORT))

server_socket.bind((LISTEN_ADDR, LISTEN_PORT))

server_socket.listen()

 

while True:

connection, client_address = server_socket.accept()

try:

print("Connection from {}".format(client_address))

for event in parse_response(connection):

print("Received:\n{}".format(event.decode()))

finally:

connection.close()

 

if __name__ == '__main__':

 

main()

この記事はお役に立ちましたか?
改善できる点がありましたらお聞かせください。
フィードバックをいただき、ありがとうございました。改善に向けて取り組んでまいります。
フィードバックをいただき、ありがとうございました。改善に向けて取り組んでまいります。