Запись pcap в буфер с помощью Scapy

#python #buffer #scapy #pcap #bytesio

#python #буфер #scapy #pcap #bytesio

Вопрос:

У меня возникли проблемы с записью pcap в файловый буфер, важно, чтобы я не касался диска для этих записей pcap, и да, они должны быть активными.

 sudo scapy
>>> import io
>>> cap = sniff(timeout=30)
>>> buf = io.BytesIO()
>>> wrpcap(buf, cap)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/scapy/utils.py", line 524, in wrpcap
    with PcapWriter(filename, *args, **kargs) as fdesc:
  File "/usr/lib/python2.7/dist-packages/scapy/utils.py", line 682, in __init__
    self.f = [open,gzip.open][gz](filename,append and "ab" or "wb", gz and 9 or bufsz)
TypeError: coercing to Unicode: need string or buffer, _io.BytesIO found
  

Обычно это происходит, когда вы открываете (Нет), это ошибка в функции PcapWriter в Scapy Utils?

Я также пробовал это с помощью: buf.seek(0) перед написанием, и это все еще не удается.

Комментарии:

1. Я проверил в коде — wrpcap ожидает имя файла. Вы не можете использовать какой-либо буфер.

2. Интересно, могу ли я каким-либо образом перенести данные pcap в буфер, хм.

3. если в utils.py вы могли бы изменить строку self.f = [open,gzip.open]... на self.f = your_buffer , то, вероятно, вы могли бы получить pcap доступ к памяти. Вы можете получить wrpcap код и написать собственную версию с помощью собственного self.f .

4. Да, я мог бы попробовать изменить utils.py файл, однако я обнаружил, что могу это сделать: buf = io.BytesIO() for i in range(0, len(cap)-1): buf.write(str(cap[i])) единственным недостатком является то, что это все необработанные пакетные данные, а не формат pcap. однако ‘text2pcap’ из утилит WireShark оказывается сложным с этими данными. Итак, да, вы можете удалить данные в виде буфера, но, похоже, это только необработанные пакетные данные, а не в формате pcap.

5. кстати. короче и более pythonic for x in cap: buf.write(str(x))

Ответ №1:

Вы должны использовать последнюю версию Scapy, она работает из коробки:

 Welcome to Scapy (2.3.3)
>>> import io
>>> cap = sniff(timeout=30)
>>> buf = io.BytesIO()
>>> wrpcap(buf, cap)
>>>
  

Если вам нужно сохранить buf открытым, просто сделайте:

 Welcome to Scapy (2.3.3)
>>> import io
>>> cap = sniff(timeout=30)
>>> buf = io.BytesIO()
>>> PcapWriter(buf).write(cap)
>>> buf.seek(0)
0L
>>> rdpcap(buf)
<No name: TCP:736 UDP:0 ICMP:0 Other:0>
  

Комментарии:

1. просто я нашел это в коде на GitHub 🙂 И, похоже, вы добавили эту модификацию 🙂

2. Однако я сделал это, объединил более 7 месяцев назад, так что это не совсем ново 😉

3. Похоже, мне придется получить версию scapy Kali для Github, должно быть, устаревшую, lol!

4. Да, Kali устарел, я пробовал wrpcap, однако после этого все равно нужно открыть буфер, чтобы манипулировать им. Однако второй набор кода с более новой версией работает нормально.

Ответ №2:

Я получил код из scapy ( utils.py ) и создал memwrpcap который может записывать в io.BytesIO .

 buf = io.BytesIO()
memwrpcap(buf, cap)
  

(после записи буфер не закрывается, и вы можете перейти к началу чтения из буфера.)

После этого я использовал стандартные open() и write() для сохранения данных из io.BytesIO и сравнил этот файл с файлом, созданным с wrpcap

 diff -c test-std.pcap test-mem.pcap
  

и кажется, что они идентичны, поэтому io.BytesIO имеет данные в формате pcap.

Полный код — memwrpcam , MemoryPcapWriter и код, который я использовал для его тестирования.

 #
# from: scapy/utils.py
#

from scapy.all import *

def memwrpcap(filename, pkt, *args, **kargs):
    """Write a list of packets to a pcap file
    gz: set to 1 to save a gzipped capture
    linktype: force linktype value
    endianness: "<" or ">", force endianness"""

    # use MemoryPcapWriter instead of PcapWriter
    with MemoryPcapWriter(filename, *args, **kargs) as fdesc:
        fdesc.write(pkt)


class MemoryPcapWriter(PcapWriter):
    """A stream PCAP writer with more control than wrpcap()"""
    def __init__(self, filename, linktype=None, gz=False, endianness="", append=False, sync=False):
        """
        linktype: force linktype to a given value. If None, linktype is taken
                  from the first writter packet
        gz: compress the capture on the fly
        endianness: force an endianness (little:"<", big:">"). Default is native
        append: append packets to the capture file instead of truncating it
        sync: do not bufferize writes to the capture file
        """

        self.linktype = linktype
        self.header_present = 0
        self.append=append
        self.gz = gz
        self.endian = endianness
        self.filename=filename
        self.sync=sync
        bufsz=4096
        if sync:
            bufsz=0

        # use filename or file-like object 
        if isinstance(self.filename, str):
            self.f = [open,gzip.open][gz](filename,append and "ab" or "wb", gz and 9 or bufsz)
        else: # file-like object 
            self.f = filename

    def __exit__(self, exc_type, exc_value, tracback):
        self.flush()
        if isinstance(self.filename, str):
            self.close() # don't close file-like object


# --- main ---

#
# run script with sudo
#
# compare results (on Linux)
#    diff -s test-std.pcap test-mem.pcap
#

from scapy.all import *

import io

cap = sniff(timeout=5)

# save to pcap file
wrpcap('test-std.pcap', cap)

# save to buffer
buf = io.BytesIO()
memwrpcap(buf, cap)

# move to beginning and save to file
#print('current position:', buf.tell())
buf.seek(0)
#print('current position:', buf.tell())

with open('test-mem.pcap', 'wb') as fp:
    fp.write(buf.read())
  

Комментарии:

1. Я собираюсь немного рассказать об этом: я смог использовать файловый буфер для записи каждого пакета в виде raw hex, затем взять их и преобразовать в полезный pcap, выполнив: for f in *.hex; do od -Ax -tx1 -v $f >> cap.dump; done amp;amp; text2pcap -n cap.dump cap.pcap проблема, с которой я столкнулся при повторной сборке данных, заключалась в том, что text2pcap должен знать длину каждого пакета, прежде чем его можно будет должным образом обработать. Я расскажу об этом позже, если это сработает, это должно быть преобразовано в запрос на извлечение в scapy.

2. В качестве дополнительного примечания, это может быть из-за того, что моя версия utils.py старше, если у кого-то есть проблемы с выполнением этой работы, просто измените на MemoryPcapWriter(filename, *args, **kargs) as fdesc: fdesc.write(pkt) на MemoryPcapWriter(filename, *args, **kargs).write(pkt) , кроме того, что это работает как шарм, вы собираетесь создать запрос на извлечение этого для проекта scapy?

3. Я проверил новейший код в репозитории, и он был добавлен 8 марта. Теперь вы можете использовать PcapWriter() вместо wrpcap() : buf = io.BytesIO() ; PcapWriter(buf).write(cap)