質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.03%

dpktを使いpcapファイルからHTTPレスポンスを抽出したい

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 957

xBASARAx

score 4

 前提・実現したいこと

pythonモジュールである「dpkt」を使用し、pcapファイルからHTTPレスポンスを抽出したい

ここに質問の内容を詳しく書いてください。

pythonモジュールである「dpkt」を使用し、pcapファイルからTCP通信を解析したいと考えています。
現在、開発者のサンプルコードを参考にHTTP通信のリクエストとレスポンスの情報を抽出し、コンソール上に出力、csvファイルに書き込みを行うとしています。

しかし、出力と書き込みができるのはrequestのパケットのみでresponseおよびその両方を一度に行おうとすると表示もされず、書き込みも行われません。
また、これを行うと他の関係のないコード(タイムスタンプを表示させる。コードが動いているか確認するためのコード[print("success")]など)全てのプログラムが動作しません。

回避策はありますでしょうか?
よろしくお願いします。

 発生している問題・エラーメッセージ

responseのパケットを抽出して表示、書き込みができない。実行するとプログラム自体は動作しているようだが、動きが見られない。(printを使用してもなにも表示されない)

エラーメッセージ
特にエラーコードは無く、コンソール上になにも表示されない

 該当のソースコード

python3.6

#macで動かしています
import dpkt
import datetime
import socket
import os
import subprocess
import csv
from dpkt.compat import compat_ord
import tldextract
import urllib.parse


if(os.name == 'posix'):
    import GeoIP
    url = open('url.csv','w')
    w = open('W.csv', 'w',encoding = 'utf-8')

    u = open('U.csv','w')
    user = open('User.csv','w')
    httpres =open('response.csv','w')

    g_data = open('g_data.csv','w')

writer_url = csv.writer(url)
writer_w = csv.writer(w)
writer_u = csv.writer(u)
writer_user = csv.writer(user)
writer_res =csv.writer(httpres)
writer_g_data = csv.writer(g_data)

def mac_addr(address):
    return ':'.join('%02x' % compat_ord(b) for b in address)


def inet_to_str(inet):

    try:
        return socket.inet_ntop(socket.AF_INET, inet)
    except ValueError:
        return socket.inet_ntop(socket.AF_INET6, inet)

def print_http_requests(pcap):

    tmp = str(subprocess.check_output(["parse_pcap","mal.pcap"]))
    httpres.write(tmp)

    for timestamp, buf in pcap:

        eth = dpkt.ethernet.Ethernet(buf)

        if not isinstance(eth.data, dpkt.ip.IP):
            print('Non IP Packet type not supported %s\n' % eth.data.__class__.__name__)
            continue

        ip = eth.data
        src = ip.src #送信側のipアドレス抽出
        dst = ip.dst #受信側のipアドレス抽出

        src_a = socket.inet_ntoa(src) 
        dst_a = socket.inet_ntoa(dst)

        if isinstance(ip.data, dpkt.tcp.TCP):
            tcp = ip.data
#該当箇所
            try:
                request = dpkt.http.Request(tcp.data)
                res = dpkt.http.Response(tcp.data)


            except (dpkt.dpkt.NeedData, dpkt.dpkt.UnpackError):
                continue

            do_not_fragment = bool(ip.off & dpkt.ip.IP_DF)
            more_fragments = bool(ip.off & dpkt.ip.IP_MF)
            fragment_offset = ip.off & dpkt.ip.IP_OFFMASK

            print('Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp)))
            print('Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type)
            print('IP: %s -> %s   (len=%d ttl=%d DF=%d MF=%d offset=%d)' %
                (src_a, dst_a, ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset))
            print('HTTP request: %s\n' % repr(request))
                        user.write('Timestamp:' + str(datetime.datetime.utcfromtimestamp(timestamp))+'\n')
#書き込み
            user.write('Ethernet Frame: ')
            user.write(mac_addr(eth.src))
            user.write(mac_addr(eth.dst))
            user.write(str(eth.type))
            user.write('\n')
            user.write('IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)\n'%
                (src_a, dst_a, ip.len, ip.ttl, do_not_fragment, more_fragments, fragment_offset))
            user.write('HTTP request: %s\n' % repr(request))


            u.write('IP address : %s \n'% src_a)
            u.write('OS and Browser info: ')
            #keyerror回避
            try:    
                u.write(request.headers['user-agent'])
            except:
                continue
            u.write('\n')

#TCPセグメント間のスパニングの確認            
       if not tcp.data.endswith(b'\r\n'):
                print('\nHEADER TRUNCATED! Reassemble TCP segments!\n')

            dst = ip.dst #受信側のipアドレス抽出 
            dst_a = socket.inet_ntoa(dst) 
            if eth.type != dpkt.ethernet.ETH_TYPE_IP:
                print ('Non IP Packet type not supported')
                continue


            if tcp.dport == 80 and len(tcp.data) > 0:                
                URL = request.headers['host'] + request.uri
                url.write('IP address : %s \n'% src_a)
                url.write(URL+"\n\n")

def test():
    with open('test.pcap', 'rb') as f:
        pcap = dpkt.pcap.Reader(f)
        print_http_requests(pcap)


if __name__ == '__main__':
    test()

 試したこと

メモリー不足の可能性があると思い、responseのみ解析してみたが、特に変化なし
(これに関するエラーコードが出なかったので関係なかったかもしれません...)

 補足情報(FW/ツールのバージョンなど)

実行環境
macbook core m3 RAM 8GB
dpkt1.9.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • y_waiwai

    2018/09/15 19:02

    ソースコードは、<code>ボタンを押して、’’’の枠の中に貼り付けてください

    キャンセル

  • xBASARAx

    2018/09/15 23:03

    修正いたしました。ご指摘ありがとうございます。

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる