python: using raw socket with OSX - python

I found this code online and found that it doesn't work on OSX. Does anyone know the correct method without using a third party library?
import socket
import struct
import binascii
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
while True:
packet = rawSocket.recvfrom(2048)
ethernet_header = packet[0][0:14]
ethernet_detailed = struct.unpack(“!6s6s2s”, ethernet_header)
arp_header = packet[0][14:42]
arp_detailed = struct.unpack(“2s2s1s1s2s6s4s6s4s”, arp_header)
# skip non-ARP packets
ethertype = ethernet_detailed[2]
if ethertype != ‘\x08\x06’:
continue
source_mac = binascii.hexlify(arp_detailed[5])
dest_ip = socket.inet_ntoa(arp_detailed[8])
if source_mac == ‘74c24671971c’:
print “Tide button pressed!, IP = “ + dest_ip
apparantly OSX does not have AF_PACKET or PF_PACKET and AF_INET is too high level for this I think, or at the very least requires more recoding than a drop in replacement.
Thanks

ok I figured this one out, on a mac I have to use pcap library. Here is the code I came up with.
#!/usr/bin/env python2.7
import sys, binascii, subprocess
import dpkt, pcap, socket
cottonelle = 'f0272d8b52c0'
def main():
name = pcap.lookupdev()
try:
pc = pcap.pcap(name)
except:
print pc.geterr()
try:
print 'listening on %s' % (pc.name)
for ts, pkt in pc:
eth = dpkt.ethernet.Ethernet(pkt)
ip_hdr = eth.data
if eth.type != dpkt.ethernet.ETH_TYPE_ARP:
continue
if binascii.hexlify(eth.src) == cottonelle:
subprocess.call("/usr/local/bin/stopsim", shell=True)
except Exception as e:
print e, pc.geterr()
if __name__ == '__main__':
main()

Related

Python xbee library no output for incoming frames

I am using 2 XBee pro S1, I want to read the packets received by the co-ordinator on my PC , it is enabled with API_2 and all other connections are done properly, I can see the packets with XCTU, I am using the python xbee library , but it gives no output :
The Code :
import serial.tools.list_ports
from xbee import XBee
import serial
ports = list(serial.tools.list_ports.comports())
for p in ports: #print the list of ports
print p
def toHex(s):
lst = []
for ch in s:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0'+hv
hv = '0x' + hv
lst.append(hv)
def decodeReceivedFrame(data):
source_addr_long = toHex(data['source_addr_long'])
source_addr = toHex(data['source_addr'])
id = data['id']
samples = data['samples']
options = toHex(data['options'])
return [source_addr_long, source_addr, id, samples]
PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
ser = serial.Serial(PORT, BAUD_RATE)
print "Serial ports initialised...."
xbee = XBee(ser,escaped=True)
print "XBee object created"
while True:
try:
response = xbee.wait_read_frame()
sleep(0.5)
decodedData = decodeReceivedFrame(response)
print decodedData
print "data decoded"
except KeyboardInterrupt:
break
ser.close()
The port number and baudrate are connect, I change it to the appropriate portnumber every time I replug the coordinator to my PC.
My output looks like :
Serial ports initialised....
XBee object created
It stays like that and gives no output, even if I see the RX led blinking.
Below is the code written with only pyserial :
import serial
from time import sleep
port = '/dev/ttyUSB0'
baud = 9600
ser = serial.Serial(port, baud)
data = ""
while True:
try:
while ser.in_waiting:
sleep(1)
data = ser.read()
print data
except KeyboardInterrupt:
break
ser.close()
It gives the following output.
Could someone kindly help.
Are you sure you have the correct serial port and baud rate? Does the xbee package support API mode 2? It might only work with API mode 1.
Does that package have methods for accessing the raw byte stream instead of trying to read frames? Can you configure it to throw exceptions on parsing errors?
I would start with just printing response until you see that you're receiving data. And why include the sleep() call in that loop?
I'm not sure what you're trying to accomplish in toHex() but you might want to look at the Python method struct.unpack() or replace all of the work you do on hv with '0x%02X' % ord(ch).

Sending numerous packets instead of 1 SSL Python

I have set up an experiment where I pass Modbus traffic over a SSL tunnel (this being the first thing I've ever done in python). I am able to send and receive data but when I send one request numerous requests are actually sent (see screenshot)
I've tried numerous configurations including (in both client and server):
send()--no change
sendall() --no change
setblocking(1)
setblocking(0)--doesn't read all the data
On the server side:
if data == Read_Coils_Answer-- I don't think I'm converting the big endian properly for comparison and this didn't work
while data: --the while loop seems to be the only way to prevent either side from stopping short with a "Broken Pipe" error. So this is what I'm using.
I eventually plan to use a for loop (now commented out and set to 4).
My Server code:
from ModLib import *
import socket, ssl, sys, pprint
try:
bindsocket = socket.socket()
bindsocket.bind(('', 502))
bindsocket.listen(5)
bindsocket.setblocking(1)
def do_something(connstream, data):
readCoilsReq = str('\x01\x01\x00')
answer = str(ModbusPDU01_Read_Coils_Answer)
while data:
print ("Request Recevied from Client:")
print pprint.pformat(data)
connstream.send(answer)
print ("Answer Sent to Client")
print pprint.pformat(answer)
return False
def deal_with_client(connstream):
data = connstream.recv(64)
while data:
if not do_something(connstream, data):
break
data = connstream.recv(64)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile="server.crt",
keyfile="server.key",
ssl_version=ssl.PROTOCOL_TLSv1)
try:
deal_with_client(connstream)
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
except KeyboardInterrupt:
print ("\nTerminating Session at User Request")
print ("No More Data Will be Sent/Recieved\n")
sys.exit(1)
My Client Side code:
from ModLib import *
from time import sleep
import socket, ssl, pprint
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s,
ca_certs="server.crt",
cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('localhost', 502))
ssl_sock.setblocking(1)
readCoils = ModbusPDU01_Read_Coils()
#for i in range(4):
sleep(2)
ssl_sock.sendall(str(readCoils))
print ("Request for Read Coils Sent")
#start receive
data = ssl_sock.recv(64)
print ("Response from Server:")
print pprint.pformat(data)
if False: #from the python docs
ssl_sock.write("""GET / HTTP/1.0\r
Host: www.verisign.com\n\n""")
data = ssl_sock.read()
ssl_sock.close()
The do_something() loop was not necessary, as the deal_with_client() loop was doing the same thing. I removed do_something() and put the code in deal_with_client() which allows me to keep the connection open (see below)
from ModLib import *
import socket, ssl, sys, pprint
try:
bindsocket = socket.socket()
bindsocket.bind(('', 502))
bindsocket.listen(5)
bindsocket.setblocking(1)
def deal_with_client(connstream):
data = connstream.recv(1120)
answer = str(ModbusPDU01_Read_Coils_Answer())
while data:
print ("Request Received from Client:")
print pprint.pformat(data)
connstream.send(answer)
print ("Answer Sent to Client")
print pprint.pformat(answer)
data = connstream.recv(1120)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile="server.crt",
keyfile="server.key",
ssl_version=ssl.PROTOCOL_TLSv1)
try:
deal_with_client(connstream)
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
except KeyboardInterrupt:
print ("\nTerminating Session at User Request")
print ("No More Data Will be Sent/Received\n")
sys.exit(1)

Sending DHCP Discover using python scapy

I am new to python and learning some network programming, I wish to send an DHCP Packet through my tap interface to my DHCP server and expecting some response from it. I tried with several packet building techniques such a structs and ctypes and ended up with using scapy. Here I am able to send DHCP Packet but unable to get any response from the DHCP server(Analyzed using wireshark and tcpdump)..My packet looked like same as original DHCP packet but failed to get response. Here is my code
import socket
from scapy.all import *
def main():
if len(sys.argv)<3:
print " fewer arguments."
sys.exit(1)
else:
tap_interface = sys.argv[1]
src_mac_address = sys.argv[2]
ethernet = Ether(dst='ff:ff:ff:ff:ff:ff',src=src_mac_address,type=0x800)
ip = IP(src ='0.0.0.0',dst='255.255.255.255')
udp =UDP (sport=68,dport=67)
fam,hw = get_if_raw_hwaddr(tap_interface)
bootp = BOOTP(chaddr = hw, ciaddr = '0.0.0.0',xid = 0x01020304,flags= 1)
dhcp = DHCP(options=[("message-type","discover"),"end"])
packet = ethernet / ip / udp / bootp / dhcp
fd = open('/dev/net/tun','r+')
TUNSETIFF = 0x400454ca
IFF_TAP = 0x0002
IFF_NO_PI = 0x1000
mode = IFF_TAP | IFF_NO_PI
ifr = struct.pack('16sH', tap_interface, IFF_TAP | IFF_NO_PI)
fcntl.ioctl(fd,TUNSETIFF,ifr)
while True:
sendp(packet, iface = tap_interface)
time.sleep(10)
if __name__ == '__main__':
main()
Is there any other ways of achieving this? If so please do mention them as well.
Thanks in Advance.
Solved ! I had the same problem,
The problem I think was on the srp() function, it can't receive packets on port 68, but I've created a new function with a new thread that sniffs BOOTP messages and displays the packet fields.
you can simulate it :
sniff(iface=myiface, filter="port 68 and port 67")
then send the packet using srp() or sendp() func :)
NOTE:
I have used multithreading mechanism cause my program sends messages and sniffs if a rogue DHCP Server is on the network
I am not sure if this would qualify as an answer, but we use scapy to simulate DHCP server/client exchange, and the following does the job for us:
discover = Ether(dst='ff:ff:ff:ff:ff:ff', src=cliMAC, type=0x0800) / IP(src='0.0.0.0', dst='255.255.255.255') / UDP(dport=67,sport=68) / BOOTP(op=1, chaddr=cliMACchaddr) / DHCP(options=[('message-type','discover'), ('end')])
The main difference between my code and yours seem to be how the BOOTP header is defined. Maybe you could try my packet definition and see if it works?
Here is an example that I did that gets a dhcp address and assigns it to an ip interface:
My rough POC, while creating code for my project:
#!/usr/bin/python
from scapy.all import Ether,IP,UDP,DHCP,BOOTP,get_if_raw_hwaddr,get_if_hwaddr,conf,sniff,sendp
from pyroute2 import IPDB
from Queue import Empty
from multiprocessing import Process, Queue, Manager
from wpa_supplicant.core import WpaSupplicantDriver
from twisted.internet.selectreactor import SelectReactor
import threading
import time
import errno
import sys
import types
import netifaces
import dbus
import json
import re
class PythonDHCPScanner:
def change_ip(self,ipObject,netInterface):
ipdb = IPDB()
ips= ipdb.interfaces[self.get_interface(netInterface)]
ipAddrs = ips.ipaddr.ipv4[0]
ips.del_ip(ipAddrs['address'],ipAddrs['prefixlen'])
ips.add_ip(ipObject['ipAddr'],24)
ipdb.commit()
ipdb.routes.add(dst="default",gateway=ipObject['router'])
ipdb.commit()
def queue_get_all(self):
items = []
maxItems = 50
for numOfItemsRetrieved in range(0, maxItems):
try:
items.append(self.q.get_nowait())
except Empty, e:
break
return items
def __init__(self):
self.net_iface = netifaces.interfaces()
def dhcp_print(self,pkt):
self.q.put(str(pkt))
def get_interface(self,number):
return str(self.net_iface[number].decode())
def get_interfaces(self):
return self.net_iface
def get_dhcp_object(self,interfaceNumber):
self.q = Manager().Queue()
c = Process(target=self.callSniffer,args=(interfaceNumber,)).start()
time.sleep(0.1)
p = Process(target=self.callPacket(interfaceNumber)).start()
time.sleep(5)
if c is not None:
c.join()
dhcp = {}
for strPkt in self.queue_get_all():
try:
pkt = Ether(strPkt)
pkt.show()
if pkt[Ether].dst == get_if_hwaddr(self.get_interface(interfaceNumber)):
if pkt[DHCP]:
if pkt.getlayer(DHCP).fields['options'][0][1] == 2:
if pkt[IP]:
dhcp['ipAddr'] = pkt[IP].dst
for option in pkt.getlayer(DHCP).fields['options']:
if option == 'end':
break
dhcp[option[0]] = option[1]
print dhcp['router']
print dhcp['subnet_mask']
break
except:
continue
return dhcp
def callSniffer(self,interfaceNumber):
inter = self.get_interface(interfaceNumber)
conf.iface = inter
print inter
sniff(iface=inter,filter="udp",prn=self.dhcp_print, timeout=10)
def callPacket(self,interfaceNumber):
inter = self.get_interface(interfaceNumber)
print inter
fam,hw = get_if_raw_hwaddr(inter)
macaddress= get_if_hwaddr(inter)
conf.iface = inter
ethernet = Ether(dst="ff:ff:ff:ff:ff:ff",src=macaddress,type=0x800)
ip = IP(src="0.0.0.0",dst="255.255.255.255")
udp = UDP(sport=68,dport=67)
bootp = BOOTP(chaddr =hw,xid=0x10000000)
dhcp = DHCP(options=[("message-type","discover"),("end")])
packet=ethernet/ip/udp/bootp/dhcp
sendp(packet,iface=inter)
# get dhcp object
dave = PythonDHCPScanner()
dhcpObject = dave.get_dhcp_object(3)
# Pick interface number 3 on my box
time.sleep(1)
for dhcpKey in dhcpObject.keys():
print str(dhcpKey) + ":" + str(dhcpObject[dhcpKey])
time.sleep(1)
dave.change_ip(dhcpObject,3)

Python - AttributeError: 'tuple' object has no attribute 'read'

I am working on a simple python client and server that can write code to a file as its sent. So far I have been stuck on this error: AttributeError: 'tuple' object has no attribute 'read'
Here is the client's code:
# CCSP Client
# (C) Chris Dorman - 2013 - GPLv2
import socket
import sys
# Some settings
host = raw_input('Enter the Host: ')
port = 7700
buff = 24
connectionmax = 10
# Connect to server
server = socket.socket()
server.connect((host, port))
print 'Connected!'
while True:
open_file = raw_input("File (include path): ")
fcode = open(open_file, "rb")
while True:
readcode = fcode.read(buff)
server.send(readcode)
if not fcode:
server.send("OK\n")
print "Transfer complete"
break
Server:
# CCSP Server
# (C) Chris Dorman - 2013 - GPLv2
import socket
import sys
import string
import random
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for x in range(size))
host = "0.0.0.0"
port = 7700
buff = 1024
filepath = "/home/chris/"
extension = ".txt"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
print "Server Started"
while True:
server.listen(1)
conn = server.accept()
print 'Client' + str(conn)
print 'Generating a random file'
filename = filepath + str(id_generator()) + extension
fcode = open(filename, "wb")
while True:
if conn != 0:
code = conn.read(buff)
fcode.write(buff)
if conn == "DONE":
print 'Transfer complete'
break #EOT
Any help with getting this to work would be awesome. I just keep getting that dumb error when it gets down to: code = conn.read(buff) on the servers script
You should read some doc. accept() returns a tuple not a file-like object.
As others have pointed out, accept() returns a tuple. It looks like you want the first item in the tuple, which will be a new socket object.
Of course, sockets don't have a read() method either. I'm guessing that what you actually want is:
code = conn.recv(buff)
As recv() returns data that has been written to a socket's connection.

Python DNS finder

Hello I have gotten this code of a gist on github and added my own little adjustments but Its quite slow Is there any way I could speed it up? I have tried threads but it just creates more trouble with writing to the file so how could I speed it up?
# dnsfind.py <startip> <endip>
import sys
import socket
import struct
import threading
import os
import time
# basic DNS header for 1 query
def buildDNSQuery(host):
packet=struct.pack("!HHHHHH", 0x0001, 0x0100, 1, 0, 0, 0)
for name in host:
query=struct.pack("!b"+str(len(name))+"s", len(name), name)
packet=packet+query
packet=packet+struct.pack("!bHH",0,1,1)
return packet
# just ask for www.google.com
TEST_QUERY=buildDNSQuery(["www","google","com"])
DNS_PORT=53
TIMEOUT=2
# scan a server for DNS
def ScanDNS(addr, timeout):
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
s.settimeout(TIMEOUT)
# send DNS question to server
sendcount=s.sendto(TEST_QUERY, 0, (addr,DNS_PORT))
if sendcount <= 0:
return False
# wait for response
try:
recvdata=s.recvfrom(1024)
except socket.error, e:
return False
return True
# extract an ip address into a tuple of integers
def ExtractIP(ip):
partip=ip.split(".")
if len(partip) != 4:
print "Invalid ip address: "+ip
try:
iptuple=(int(partip[0]),int(partip[1]),int(partip[2]),int(partip[3]))
except ValueError:
print "Invalid ip address: "+ip
return iptuple
if len(sys.argv) < 2:
print "Not enough parameters supplied!"
# convert ip address to integer tuple
STARTs_IP=ExtractIP(sys.argv[1])
ENDs_IP=ExtractIP(sys.argv[2])
File = open("file.txt","wb")
def main(START_IP,END_IP):
# store found DNS servers
foundDNS=[]
# scan all the ip addresses in the range
for i0 in range(START_IP[0], END_IP[0]+1):
for i1 in range(START_IP[1], END_IP[1]+1):
for i2 in range(START_IP[2], END_IP[2]+1):
for i3 in range(START_IP[3], END_IP[3]+1):
# build ip addres
ipaddr=str(i0)+"."+str(i1)+"."+str(i2)+"."+str(i3)
print "Scanning "+ipaddr+"...",
# scan address
ret=ScanDNS(ipaddr, 10)
if ret==True:
foundDNS.append(ipaddr)
print "Found!"
File.write(ipaddr)
File.write("\n")
else:
print
# print out all found servers
if __name__ == "__main__":
main(STARTs_IP,ENDs_IP)
Socket library has a function for this
import socket
print socket.gethostbyaddr('8.8.8.8')

Categories