How to implement ARP ping with Scapy? - python

I've been trying to create a network scanner similar to netdiscover. I used Python and Scapy module to do that. I'm running my script on Kali linux on virtual box and when I'm scanning my NAT network created by Virtual Box it's showing me devices that are connected, but when I'm using wireless adapter to scan my wifi network the scanner is unable to find any devices, which is strange because netdiscover finds tons of them. However when I'm using arping function implemented by Scapy, devices are also showing, but when I'm running my code it doesn't detect any devices. Why is that?
I used code suggested by Scapy documentation and it's still not showing any devices. Only Scapy arping function detects any devices at all
import scapy.all as scapy
import subprocess as sub
import re
def get_IP():
output=sub.check_output("route -n",shell=True)
ips={}
for row in output.split("\n")[2:]:
found=re.findall("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",row)
device=re.findall("[a-z]{2,10}\d$",row)
for ip in found:
if ("0.0.0" not in ip and "255.255.255" not in ip):
ips[device[0]]=ip
for device,ip in ips.items():
print("Device: {}\tIP: {}".format(device,ip))
device = raw_input("Choose a device > ")
return(ips[device][:-1]+"1/24")
def scan(ip):
#My code
print("Scanning...")
arp_request=scapy.ARP(pdst=ip)
brodcast=scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
arp=brodcast/arp_request
answered=scapy.srp(arp, timeout=1,verbose=False)[0]
for element in answered:
print("IP:{}".format(element[1].psrc))
print("MAC address: {}\n".format(element[1].hwsrc))
def scan2(ip):
#Code from scapy documentation and it's also not detecting any devices
ans, unans = scapy.srp(scapy.Ether(dst="ff:ff:ff:ff:ff:ff")/scapy.ARP(pdst=ip),timeout=2)
ans.summary(lambda (s,r): r.sprintf("%Ether.src% %ARP.psrc%") )
def scan3(ip):
#This works
scapy.arping(ip)
ip = get_IP()
scan(ip)
scan2(ip)
scan3(ip)

I solved it just by deactivating connection to NAT Network, so I used ifconfig eth0 down. However in some cases it's not the problem. If you're router does not allow net scans you need to change you're MAC address which means that you need to run series of these commands
ifconfig wlan0 down
ifconfig wlan0 hw ether 00:22:44:66:88:33 # Ofcourse you can choose any MAC address you want
ifconfig wlan0 down
ifconfig wlan0 up
service network-manager restart
After that network scanner will detect devices that are currently in the network

Try this way :
from scapy.all import scapy,ARP,Ether,srp,arping
or this way:
from scapy.layers.l2 import *
In both cases remember delete the "scapy.", like this:
#Before
scapy.arping(ip)
#After
arping(ip)

Related

Get Ethernet adapter IPv4 address without using external libraries

I have 2 computers connected with crossover cable and first time I need to start PC1 as server and PC2 as client and then second time PC2 as server and PC1 as client. I use UDP socket and it is on Windows. So I cant just put IP in code, I need the server code to get the IP automatically.
I tried this:
hostname = socket.gethostname()
IPAddr = socket.gethostbyname(hostname)
But this gives me wrong IP. I need the IP address that I see when I check Ethernet adapter Ethernet in ipconfig/all.
I'm not sure if you understand me sorry. English is not my best skill.
You could try using the netifaces package. Docs are here.
import netifaces
ip = netifaces.ifaddresses('eth0')[netifaces.AF_INET][0]['addr']
print(ip)
eth0 is just an example, you can get the actual interface name from ipconfig

Get local IP Address from a known MAC Address in Python?

I am running a Python Script on the Raspberry Pi in order to get measured data out of a Smart Plug. In my script I need to write the IP-Address of the Smart Plug so that I can retrieve the data it was measured. The problem is that I need to be able to take the Smart Plug to different places without having to hard code its new local IP-Address every time.
I have the MAC Address so I am hoping there is an "easy" way to add a couple lines of code and retrieve the local IP-Address from the MAC (?) in the Python Script. Thanks!
This can be achieve using arp command in the subprocess module. Here is code. Checked in windows.
import subprocess
cmd = 'arp -a | findstr "ff-ff-ff-ff-ff-ff" '
returned_output = subprocess.check_output((cmd),shell=True,stderr=subprocess.STDOUT)
print(returned_output)
parse=str(returned_output).split(' ',1)
ip=parse[1].split(' ')
print(ip[1])
What you're describing can be accomplished by crafting an ARP packet to get that info.
Generally something like:
from scapy.all import srp, Ether, ARP ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"),timeout=2)
ip = pkt[ARP].psrc
The local ip address is not based on the MAC address. The router uses DHCP to give the devises an ip address. So there is no way to tell the router which IP he must give you other than changing the settings.
I would rather try to broadcast the ip and on the raspberry listen on the broadcast channel for the message you are looking for.

Connecting to a wifi network using python

I have this code that is supposed to connect to wifi using a given ESSID and password. Here is the code:
def wifi_connect(essid, password):
# Connect to the wifi. Based on the example in the micropython
# documentation.
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network ' + essid + '...')
wlan.connect(essid, password)
# connect() appears to be async - waiting for it to complete
while not wlan.isconnected():
print('waiting for connection...')
print('checking connection...')
print('Wifi connect successful, network config: %s' % repr(wlan.ifconfig()))
else:
# Note that connection info is stored in non-volatile memory. If
# you are connected to the wrong network, do an explicity disconnect()
# and then reconnect.
print('Wifi already connected, network config: %s' % repr(wlan.ifconfig()))
At first, I got an error message that network was not installed. This was fixed by simply using pip to install network. After I ran this again, it told me that network has no attribute WLAN. How do I fix this? What am I doing wrong?
You are trying to run code designed for the MicroPython language, and it won't work on CPython (the Python version you'd download from Python.org or find installed on most PCs and servers).
MicroPython is designed to run on embeddable specialist hardware, and comes with its own library to support the hardware it is running on, including a network module:
To use this module, a MicroPython variant/build with network capabilities must be installed. Network drivers for specific hardware are available within this module and are used to configure hardware network interface(s).
It tells you so in the comments at the top:
# [...] Based on the example in the micropython
# documentation.
The code can't run on 'regular' CPython. You installed the PyPI network project, which is a very different module, originally designed to help learn coding for the Raspberry PI.
What project could work depends on your operating system (OS). Different OSes use different programming interfaces to let programs change networks. Most have command line tools to let you do this, which should be easy to drive from Python with the subprocess module:
Windows has the netsh command, run netsh wlan connect name=... to connect to a network interface
Mac OS X has the networksetup command, networksetup -setairportnetwork en1 ... connects you to a given WIFI network.
On a PC, you don't need network.py to connect to a Wifi access point as in ESPP32.
You connect normally by OS network connection.
The only library you need is socket. Here an example of code to get data !
import socket
def http_get(url, port):
_, _, host, path = url.split('/', 3)
addr = socket.getaddrinfo(host, port)[0][-1]
s = socket.socket()
s.connect(addr)
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
s.close()
http_get('http://micropython.org/ks/test.html',80)
http_get('http://towel.blinkenlights.nl/',23)

Is it possible to change|renew my "Temporary IPv6 Address" - windows (preferable via Python)

Best,
The title says it all:
Is it possible to change|renew my "Temporary IPv6 Address" - in windows (preferable with Python)
(via code)
I've noticed that, when I'm using my 5ghz wifi, and switch to the 2.4 ghz wifi & immediately back to the 5ghz wifi, that my Temporary IPv6 Address has been changed.
And for some specific reasons, I would like recreate this behaviour via python code. (or powershell, or cmd ( as long as python can execute the function or -windows command))
Kind regards
Under windows you should be able to use ipconfig:
import os
def refresh_ip():
# Switch to dhcp
system('netsh interface ip set address "Wi-Fi" dhcp');
system('ipconfig /release6 Wi-Fi')
system('ipconfig /renew6 Wi-Fi')
The above might not work so here is a solution for non dhcp adapters, note that this is for Python3:
import ipaddress
import os
# Set specific ipv6 unicast address of adapter "Wi-Fi"
def set_ip(ipv4):
ipv6 = ipaddress.IPv6Address('fe80::' + ipv4).compressed;
os.system('netsh interface ipv6 set address "Wi-Fi" ' + ipv6)
set_ip("192.168.0.1")

Finding active IPv6 interfaces under Mac OS (using Python)

My objective is to write a Python script that provides the user with a series of link-local IPv6 addresses of specific devices. My technique is to send out a multicast ping and then use neighbor discovery to get a list of addresses which I can then filter down.
The first step is this:
output = subprocess.check_output(['ping6', '-c', '2', 'ff02::1%en0'])
The problem is the term en0 at the end. It is not a constant. On MacOS it is en0 but on Linux it will be eth0 or possibly br0. Windows has a different command but the same problem. Without the interface qualifier the ping6 command does not work.
Also, some systems may have multiple interfaces.
So how would a Python script get a list of those interfaces?
Alternatively, can this be done by using the socket package and not subprocess? (I don't want my script to require privileged mode and using ping gets around that.)
Under Linux there's no guarantee that your first Ethernet interface will be named eth0. It might be named p1s3 or em1 or even internal. Or bob.
Under both Linux and OS X you can use the netifaces python module to get a list of available interfaces and addresses associated with those interfaces. For example, consider the following code:
import netifaces
for iface in netifaces.interfaces():
addrs = netifaces.ifaddresses(iface)
for addr in addrs.get(netifaces.AF_INET6, []):
print '%-8s %s' % (iface, addr['addr'])
Which on my Linux system produces:
lo ::1
enp0s25 fe80::3e97:eff:febf:6dce%enp0s25
docker0 fe80::d8d1:31ff:feb2:b6c6%docker0
br-ext fe80::f879:f3ff:fe6b:f445%br-ext
lxcbr0 fe80::fc45:6bff:fefd:543%lxcbr0
vethf8c98b2 fe80::a0a7:3bff:feff:4f9b%vethf8c98b2
vnet0 fe80::fc54:ff:fee5:2818%vnet0
And on my OS X system produces:
lo0 ::1
lo0 fe80::1%lo0
en3 fe80::e2f8:47ff:fe41:866a%en3
I have no idea if this works under Windows or not.

Categories

Resources