Sniff RTS's and send CTS in return with Scapy - python-3.x

I'm able to sniff RTS packets without a problem. I'm also able to utilize 'sendp' to send CTS packets. What I'm unable to figure out is how to have Scapy sniff RTS packets and reply to those RTS's with a crafted CTS in real-time. The intent is to send a CTS for every RTS that my AWUS036ACH can hear regardless of the intended device.
import os
import time
from threading import Thread
from scapy.layers.all import Dot11,Dot11Elt,RadioTap,sniff,sendp
def change_channel():
ch = 1
while True:
try:
os.system(f"iwconfig {iface} channel {ch}")
ch = ch % 14 + 1
time.sleep(1)
except KeyboardInterrupt:
break
if __name__ == "__main__":
iface = "wlan0"
channel_changer = Thread(target=change_channel)
channel_changer.daemon = True
channel_changer.start()
def PacketHandler(packet):
if packet.haslayer(Dot11):
if packet.type==1 and packet.subtype==11:
rts_list.append(bssid)
bssid = packet[Dot11].addr2
print("MAC: %s" %(bssid))
sniff(iface=iface, prn=PacketHandler)
i=1
while 1:
time.sleep(.100)
i = i + 1
dot11 = Dot11(type=1, subtype=12, addr1=bssid,ID=0x99)
pkt = RadioTap()/dot11
sendp(pkt,iface=iface, realtime=True)

Why don't you try to add sendp inside your PacketHandler function?
The logic goes like this:
PacketHandler is called upon every received frame
You check whether it's an RTS frame, extract all of the necessary info you need to send a CTS frame
Call sendp with received info
There are ways to write ARP response utilities, take a look for ideas.
My concern is whether it's possible to send a frame while your adapter is put in monitor mode. Unfortunately I can't test it right now.
Recommendation. Try to use BPF filter with sniff. It goes like this:
sniff(iface=iface, filter="type ctl subtype rts", prn=PacketHandler)
And get rid of testing for frame type inside you PacketHandler. This way you will filter for RTS on a kernel level thus performance is increased. Scapy itself can easily miss RTS frames in a dense wireless environment. For more BPF filters applied to 802.11 check man pcap-filter.

Related

Interrupting a bluetooth connection in a programmable way

I am wanting to interrupt this bluetooth connect in a programmable way in python if I can. I have read many articles online and cannot seem to find a way to send an interrupt, other than a keyboard interrupt, to the client_sock, clientInfo = server_sock.accept() so that this line of code stops its bluetooth connectivity. The end game is to use my GUI side of this program by implementing a "Stop Connection" button in my GUI to halt the bluetooth connection. Is there a way to do that in python3 at all, or is this something that can only be handled via command line???
size = 1024
while True:
self.bluetooth_information.append("Waiting for connection")
self.bluetooth_information.append(str(datetime.now().time()))
client_sock, clientInfo = server_sock.accept()
try:
data = client_sock.recv(size) # receives data from client
if len(data) == 0:
break
client_sock.send(self.parse.process_data(data)) # Echo response back to client
# except bluetooth.btcommon.BluetoothError:
# pass
if self.stop:
client_sock.close()
server_sock.close()
self.stop = False
self.bluetooth_information.clear()
break
except KeyboardInterrupt:
client_sock.close()
server_sock.close()
break

Reading data from a Bluetooth device low energy rfcomm python3

Faced a problem. There is a bluetooth device with low power consumption. BLE. The goal is to send a command to the device and get the data back.
For example: command - 0x** 0x** 0x**, where first 0x** - code command, second 0x - data lenght. Response mast be - 0x** 0x** 0x**. I can not send a command to the device. The device works by RFCOMM. Actually the code that is available, but it does not give a result - it says that the device is off.
from bluetooth import *
import socket
class Work:
def __init__(self):
self.rfcon = BluetoothSocket(RFCOMM)
# self.socket = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM)
self.server = '**:**:**:**:**:**'
self.port = 1
self.data = '0x01 0x00 0x00'
def scan_device(self):
connection = self.rfcon.connect((self.server, self.port))
print('con ===>>> ', connection)
senddata = self.rfcon.send(self.data)
print('senddata ====>>>> ', senddata)
data = self.rfcon.recv(256)
if not data:
print("no data!!!")
self.rfcon.close()
else:
print(data)
self.rfcon.close()
if __name__ == '__main__':
a = Work()
a.scan_device()
a.rfcon.close()
I made it through another library - the code:
from bluepy.btle import *
class Work:
def __init__(self):
self.initialize = Peripheral()
def scan_devices(self):
scanner = Scanner()
devices = scanner.scan(10.0)
for dev in devices:
print("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
for (adtype, desc, value) in dev.getScanData():
print(" %s = %s" % (desc, value))
def connect_to_device(self):
print('start con')
connection = self.initialize.connect('**:**:**:**:**:**', 'public')
print('initialize complite')
return connection
def check_device_status(self):
print('test ====>>> ', self.initialize.getCharacteristics())
cmd = '0x01 0x00 0x00 0x20 0x00'.encode('UTF-8')
print(cmd)
status_device = self.initialize.readCharacteristic(cmd)
print('Device status => ', status_device)
def diconnect(self):
self.initialize.disconnect()
if __name__ == '__main__':
a = Work()
a.connect_to_device()
a.check_device_status()
a.diconnect()
It gives a connection but does not send a command and does not return a value since this library does not know what RFCOMM is. Perhaps someone faced this problem in the python and knows how to solve it?
RFCOMM is a protocol of Bluetooth Classic, BLE does not support it. It is impossible to use RFCOMM for communicating with a BLE device.
You should read an introduction to BLE, it will give you a basic understanding of BLE.
Anything further will be guessing, it depends on how the BLE device is configured.
If you are using your own device that you can configure, one possibility is to create a characteristic that supports Write and Indicate. You can indicate (to be notified when the characteristic value changes and what is the new value) and write the command. The response will be received via an indication.
For most practical purposes the answer that RFCOMM is only available in Bluetooth "Classic" is true: most Bluetooth LE devices don't support RFCOMM. However, in principle the Bluetooth Core Spec describes how a channel for RFCOMM can be opened between two LE devices using LE credit-based control flow with an L2CAP_LE_CREDIT_BASED_CONNECTION_REQ command (introduced in Core Spec v4.1 Vol 3 Part A Chapter 4.22 and the Assigned Numbers document).

Python scapy Beacon Frames

I'm trying to build a scapy program that scans for Beacon Frames. Every router should send beacon frames to the air in an interval of X milliseconds so the possible hosts know the router(AP) is alive.
I'm getting nothing, the only kind of Dot11 frames I've been able to get so far is Prob Request, very rarely some data or control frames as well. I setup my wireless card to monitor mode before running the script and it supports it as well. I don't what I might be doing wrong... Here's the code :
from scapy.all import *
global list_prob
list_prob = []
def search_prob(packet1):
if (packet1.haslayer(Dot11)) and (packet1[Dot11].type == 0) and\
(packet1[Dot11].subtype == 8) : #type 4 == ProbRequest
if packet1[Dot11].addr2 not in list_prob:
if packet1[Dot11].info not in list_prob:
print('[>]AP',packet1[Dot11].addr2,'SSID',packet1[Dot11].info)
list_prob.append(packet1[Dot11].addr2)
list_prob.append(packet1[Dot11].info)
sniff(iface='wlan0mon',prn=search_prob)
Ive also tried it with Dot11Beacon instead of subtype 8 and nothing changed . I'm programming with python3.5 on Linux.
Any ideas ?
Code to constantly change channel of network interface using python :
from threading import Thread
import subprocess,shlex,time
import threading
locky = threading.Lock()
def Change_Freq_channel(channel_c):
print('Channel:',str(channel_c))
command = 'iwconfig wlan1mon channel '+str(channel_c)
command = shlex.split(command)
subprocess.Popen(command,shell=False) # To prevent shell injection attacks !
while True:
for channel_c in range(1,15):
t = Thread(target=Change_Freq_channel,args=(channel_c,))
t.daemon = True
locky.acquire()
t.start()
time.sleep(0.1)
locky.release()

Obtain bluetooth signal strength on Raspberry Pi of BT device without pairing

I like to create a kind of indoor-tracking-system for my already existing home automation system. I thought of using BLE. I already successfully set up hcitool on my Raspberry Pi and I can connect to my iPhone without any problems. But how can I obtain the signal strength between my Raspberry Pi and my iPhone without connecting them. I already tried to use sudo hcitool cc [BTADDRESS] to connect to my iPhone without authentication, but it looks like the iPhone don't allow those connection to stay open. I think that must be a way to get the signal strength without connecting both devices. I want to use it to determine the distance from my Raspberry Pi to my iPhone. May I am able to calculate the distance from the time I need to discover my iPhone?
There are two ways to go, and by now I have been able to get both work reliably only on Android devices.
Exploiting the Bluetooth friendly name of the smartphone and set the discoverability to infinite. I have done this writing a simple app. Works in background, also after that the app has been killed, since the discoverability setting is preserved. At the best of my knowledge, this is not possible in iOS.
Advertising a UUID in a BLE packet from the phone. This can be done by both Android and iOS devices. However, while in background, iPhones switch the advertising to a shrinked mode that makes the packet unidentifiable. The problem of identifying an advertising iOS devices in background is still open.
On the raspberry, I used PyBluez to scan and looking for the presence of smartphones running (1) or (2). I report a code example:
import bluetooth
import bluetooth._bluetooth as bluez
import struct, socket, sys, select
def hci_enable_le_scan(sock):
hci_toggle_le_scan(sock, 0x01)
#Discover name and RSS of enabled BLE devices
class MyDiscoverer(bluetooth.DeviceDiscoverer):
def pre_inquiry(self):
self.done = False
def device_discovered(self, address, device_class, rssi, name):
discovery_logger.info("Discovered %s" % (address, ))
if name == "YOUR-DEVICE-FRIENDLY_NAME":
#Use the RSS for your detection / localization system
def inquiry_complete(self):
self.done = True
#Performs inquiry for name request
def async_inquiry():
d = MyDiscoverer()
while True:
d.find_devices(lookup_names = True)
readfiles = [ d, ]
while True:
rfds = select.select( readfiles, [], [] )[0]
if d in rfds:
d.process_event()
if d.done:
break
time.sleep(DISCOVERY_INTERVAL)
#Parse received advertising packets
def parse_events(sock):
# save current filter
old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14)
flt = bluez.hci_filter_new()
bluez.hci_filter_all_events(flt)
bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT)
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt )
while True:
pkt = sock.recv(255)
ptype, event, plen = struct.unpack("BBB", pkt[:3])
if event == LE_META_EVENT:
subevent, = struct.unpack("B", pkt[3])
pkt = pkt[4:]
if subevent == EVT_LE_CONN_COMPLETE:
le_handle_connection_complete(pkt)
elif subevent == EVT_LE_ADVERTISING_REPORT:
#Check if the advertisement is the one we are searching for
if getASCII(pkt[start:end]) == "YOUR-UUID"
report_pkt_offset = 0
report_data_length, = struct.unpack("B", pkt[report_pkt_offset + 9])
# each report is 2 (event type, bdaddr type) + 6 (the address)
# + 1 (data length field) + report_data length + 1 (rssi)
report_pkt_offset = report_pkt_offset + 10 + report_data_length + 1
rssi, = struct.unpack("b", pkt[report_pkt_offset -1])
#Now you have the RSS indicator, use it for monitoring / localization
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter )
dev_id = 0
try:
sock = bluez.hci_open_dev(dev_id)
except:
print "error accessing bluetooth device..."
sys.exit(1)
p = threading.Thread(group=None, target=parse_events, name='parsing', args=(sock, ))
d = threading.Thread(group=None, target=async_inquiry, name='async_inquiry', args=())
try:
p.start()
except:
print "Error: unable to start parsing thread"
try:
d.start()
except:
print "Error: unable to start asynchronous discovery thread"

How to capture probe request data or probe response data sent from wireless router

I have a tplink-wr703n wireless router with OpenWrt.
I know I can capture all kinds of data when the adapter is in monitor mode.
I want to the adapter work in master mode, and I also want to capture probe request data sent from client or probe response data sent from my router.
I have tried to use libpcap to capture data, but I failed.
Can you tell me how I can get that data?
You can set up several modes on one radio card simultaneously.
Using the "iw" command you should be able to create a secondary wifi device interface with type monitor, I guess you could read all frame types from this one.
See http://wireless.kernel.org/en/users/Documentation/iw/vif/
I am also trying to prepare a scapy script to capture probe request only.
there is an Indian guy who made this nice video:https://www.youtube.com/watch?v=Z1MbpIkzQjU
His script seems to work in his enviroment but for some reason I cant get this to work for me.
I will appreciate your assistance.
The script is:
#!/usr/bin/python
import sys
from scapy.all import *
clientprobes = set()
def PacketHandler(pkt):
if pkt.haslayer(Dot11ProbeReq):
if len(pkt.info) > 0:
testcase = pkt.addr2 + '_ _ _' + pkt.info
if testcase not in clientprobes:
clientprobes.add(testcase)
print "New Probe Found: " + pkt.addr2 + ' ' + pkt.info
print "\n-----------Client Probes Table-------------\n"
counter = 1
for probe in clientprobes:
[client, ssid] = probe.split('---')
print counter, client, ssid
counter = counter + 1
print "\n--------------------------------------------\n"
sniff(iface = sys.argv[1], count = int(sys.argv[2]), prn = PacketHandler)

Resources