I am reading a Python book and in it there is a script to use scapy, the Python tool/module, to scan a subnet for any hosts that are up and report back their IP and MAC addresses. This script is an enhancement on a previous one that was calling /usr/bin/arping. That previous script only allowed one IP address at a time and was platform dependent on the arping tool being available. Apparently, this script (that does not work for me) is platform independent!
If someone could look over the script and debug it that would be awesome. Here is the script:
#! /usr/bin/env python
from scapy.all import srp
from scapy.all import Ether, ARP, conf
import sys
def arping(iprange="10.0.1.0/24"):
"""Arping function takes IP Address or Network, returns nested mac/ip list"""
#conf, verb = 0
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange), timeout=2)
collection = []
for snd, rcv in ans:
result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split()
collection.append(result)
return collection
if __name__ == "__main__":
if len(sys.argv) > 1:
for ip in sys.argv[1:]:
print "arping", ip
print arping(ip)
else:
print arping()
The script does not work. It just prints that it is scanning stuff but that nothing was found.
I looked on this website and found a tutorial that also did not work. That website with the relevant content is here: http://www.secdev.org/projects/scapy/doc/usage.html#arp-ping
Please, see below for a sample of the output I obtain when running this script:
loser#loser:~/Desktop/pyFun2$ gedit arp_scanz.py
loser#loser:~/Desktop/pyFun2$ sudo python arp_scanz.py
WARNING: No route found for IPv6 destination :: (no default route?)
Begin emission:
Finished to send 256 packets.
Received 0 packets, got 0 answers, remaining 256 packets
[]
Does anyone out there know what I am missing?
UPDATE - SOLUTION
change the srp function or method call to specify the exact interface to scan on like so:
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange),iface="en1", timeout=2)
Could be any number of things. I seem to have the script running just fine on my network using valid IP starting points.
Are you putting in a proper IP range?
For example I use:
def arping(iprange="192.168.1.*"):
which produces the correct results and identical results to scapy's built in arping() function.
So I think perhaps it's not the code exactly but the range you are attempting.
Related
I am working on a virtual Machine by Oracle in Linux and my Linux version is 20.04 LTS and python version is 3.8. I have a python code which is used to capture live network traffic and save in a pcap file. The issue I am facing is that I want to run this code without any root or administrative or without sudo command.
test.py:
import time
from scapy.all import *
import uuid
# IP address to capture packets for
ip_address = "0.0.0.0"
start_time = time.time()
end_time = start_time + 10 # Capture for 10 seconds
# Create an empty list to store the packets
packets = []
def packet_callback(packet):
if IP in packet:
packets.append(packet)
# Create a capture filter to capture only packets from the specified IP address
capture_filter = "ip host " + ip_address
sniff(prn=packet_callback, timeout=end_time-start_time, filter= capture_filter)
# Write all the packets to a single pcap file
filename = "/path_to_capture/capture_" + str(uuid.uuid1()) + ".pcap"
wrpcap(filename, packets)
print(len(packets))
I run my code in terminal by writing the following cmd:
sudo python3 test.py
By running this command, my code executes and capture the network traffic and save in a pcap file. But I want to execute my code without sudo or root privileges by writing a simple cmd:
python3 test.py
Kindly provide me the solution to resolve this issue.
I think that you can use the 'setcap' command in linux.
I have a experience of only 'C' language.
See the below link. (I'm not sure about Python)
https://medium.com/#badbot/safe-packet-capture-python-without-sudo-b08c4c4e531
I've been writing little scripts and experimenting with Scapy.
I've followed many tutorials and MOST say to define your packet handler with pkt as input and then immediately an if statement that checks if the packet is Dot11.
This has NEVER worked for me as I get nothing.
Example :
#!/usr/bin/env python3
from scapy.layers.dot11 import Dot11 # \
from scapy.sendrecv import sniff # > Tried all of these without success.
from scapy.all import * # /
def packetHandler(pkt):
if pkt.haslayer(Dot11):
print("yay!")
sniff(iface="wlan0", prn=packetHandler)
I'm using Arch Linux and Python3. I've also tried this in Python2 with no success.
And YES my card is in monitor mode and is up.
I've successfully made many scripts using Scapy, but NONE with this if pkt.haslayer(Dot11): statement.
Anyone have any ideas ?
I am trying to learn how to send a list of lists in Python to R -script which runs statistical methods and gives two or three data frames back to Python
I stumbled across the pyRserve package. I was able to follow the manual in their documentation and everything works great in command line (>>> ). When I run a script, it does not stop. I have installed Rserve package and started its service in RStudio. Below is the code:
import pyRserve
print "here1" #prints this line...
conn = pyRserve.connect(host='localhost', port=6311)
print "here2"
a= conn.eval('3+5')
print a
Can anyone please help?
The (docs) suggest:
$ python
>>> import pyRserve
>>> conn = pyRserve.connect()
And then go on with:
To connect to a different location host and port can be specified explicitly:
pyRserve.connect(host='localhost', port=6311)
This is not meant to indicate that both lines should be run. The second line should be viewed as a potential modifier for the first. So if you need an alternate address or port, then it should look like:
$ python
>>> import pyRserve
>>> conn = pyRserve.connect(host='localhost', port=6311)
Also note this caveat for windows users:
Note On some windows versions it might be necessary to always provide ‘localhost’ for connecting to a locally running Rserve instance.
I am a security analyst..and Python newbie that constantly needs to find the following 3 pieces of information on end users during incident investigations at work:
1.Their device hostname
2.The IP address associated with the device
3.Their login username
I don't even know how to begin creating a script that would provide this information, but I'm thinking that it would prompt me to input 1 of the 3 piece of info I mentioned above and then print out the other 2 pieces. Beyond the prompt part below, I'm stuck..
#!/usr/bin/python
print "Please paste in one of the following pieces of information.."
print "\n"
print "1. Device hostname"
print "2. IP address"
print "3. Username"
print "\n"
str = raw_input()
I've seen a few posts that detail how to pull various bits of info on a system locally, but not remotely. Does anyone know how I'd go about building this type of script in Python?
There are existing command line tools that you can use like: dig, the host command, and nslookup which will all do DNS lookups for hostnames and IP addresses. The request for "username" doesn't seem meaningful. More than one user can log in to a single machine, so I'm not sure how you plan on gathering that piece of information unless you allow for multiple return values.
Also here's a Perl one-liner that will do an IP to name resolution (reverse DNS lookup):
perl -e 'use Socket qw(getnameinfo inet_aton pack_sockaddr_in NI_NUMERICSERV); my $ip = inet_aton($ARGV[0]); my $addr = pack_sockaddr_in(80, $ip); my ($err, $hostname) = getnameinfo($addr, NI_NUMERICSERV); print "$hostname\n"'
The script assumes a single argument on the command line.
Here's a script that does the same thing in the forward DNS direction, printing all IPs:
perl -e 'use Socket qw(getaddrinfo getnameinfo NI_NUMERICSERV NI_NUMERICHOST); my ($err, #res) = getaddrinfo($ARGV[0], "www", {socktype => SOCK_STREAM}); for my $r (#res) { my ($err, $ip) = getnameinfo($r->{addr}, NI_NUMERICHOST | NI_NUMERICSERV); print "$ip\n";}'
It also assumes a single command line argument.
If you want a Python solution, this will get you started using the gevent library:
import gevent.resolver_ares
from gevent.socket import AF_INET, SOCK_STREAM
def resolve(fqdn):
resolver = gevent.resolver_ares.Resolver()
results = resolver.getaddrinfo(
fqdn, 0, family=AF_INET, socktype=SOCK_STREAM)
return results[0][-1][0]
This only does a forward resolution, but you should be able to modify it based on the Perl code to get a working reverse resolution as well. You can also use the built-in socket.getaddrinfo instead, but if you plan on doing this for a large number of machines, I'd recommend the gevent library.
How do you get correct MAC/Ethernet id of local network card using python?
Most of the article on Google/stackoverflow suggests to parse the result of ipconfig /all (windows) and ifconfig (Linux).
On windows (2x/xp/7) 'ipconfig /all' works fine but is this a fail safe method?
I am new to linux and I have no idea whether 'ifconfig' is the standard method to get MAC/Ethernet id.
I have to implement a license check method in a python application which is based on local MAC/Ethernet id.
There is a special case when you have a VPN or virtualization apps such as VirtualBox installed. In this case you'll get more then one MAC/Ethernet Ids. This is not going to be a problem if I have to use parsing method but I am not sure.
Cheers
Prashant
import sys
import os
def getMacAddress():
if sys.platform == 'win32':
for line in os.popen("ipconfig /all"):
if line.lstrip().startswith('Physical Address'):
mac = line.split(':')[1].strip().replace('-',':')
break
else:
for line in os.popen("/sbin/ifconfig"):
if line.find('Ether') > -1:
mac = line.split()[4]
break
return mac
Is a cross platform function that will return the answer for you.
On linux, you can access hardware information through sysfs.
>>> ifname = 'eth0'
>>> print open('/sys/class/net/%s/address' % ifname).read()
78:e7:g1:84:b5:ed
This way you avoid the complications of shelling out to ifconfig, and parsing the output.
I have used a socket based solution, works well on linux and I believe windows would be fine too
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
getHwAddr("eth0")
Original Source