Unable to send packets via RAW_SOCK on OSX - python

After quite a bit of searching and reading docs, I've hit a bit of a wall when using RAW_SOCK on OSX to send custom IPv4 + UDP packets using family AF_INET
Given the sample code (in python) below:
import socket
ip_packet = <full code below>
raw_sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
raw_sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
raw_sock.sendto(ip_header + udp_header, ("1.1.1.1", 0))
I'm getting OSError: [Errno 22] Invalid argument. I suspect there is something slightly off with how I'm constructing the IP packet, however given this works on Linux and all other BSDs, I'm not entirely sure which parts of the header I've constructed incorrectly. The only field
Are there any docs covering Darwins RAW_SOCK? Specifically what headers should be what values(And endianness?)
I pulled some rough code together here which illustrates what Im trying to do: link

Related

About the issue that the character string is broken in TCP/IP communication between different machines

I tried TCP/IP communication between the same machine and TCP/IP communication between different machines.
First of all, I tried communication in the same Windows machine.The server and client code used is:
TCP_server.py
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('', 50001))
s.listen(1)
while True:
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(30000)
if not data:
break
if len(data.decode('utf-8')) < 35:
print("error")
break
print(data.decode('utf-8')+"\n")
TCP_client.py
# -*- coding : UTF-8 -*-
import socket
target_ip = "192.168.1.5"
target_port = 50001
buffer_size = 4096
tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_client.connect((target_ip,target_port))
message = b'123456789101112131415161718192021222324252627282930\n'
while True:
tcp_client.send(message)
The IP address of my Windows machine is 192.168.1.5, so the above code works. And it executed successfully without any error. The printed string is shown in the image below.
But when I tried to communicate with Mac and Windows using the exact same code, I had a problem. I used a Mac for the client and Windows for the server.The character string output on the server side is as follows.
As you can see from the image above, it is normally printed normally, but sometimes a line break is made and the character string is divided.
And my server-side code says that if the number of characters is less than 35, it will print error. However, error is not printed in this execution result.In other words, communication is not performed twice, but line breaks are inserted in one communication.
Is it possible to avoid this problem? Do I always have to be aware of line breaks when sending from another machine over TCP/IP?
I'm only using Python in this sample, but I had a similar problem using iOS's Swift for client-side code. So I would like to know a general solution.
There is no line break added by transmission of the data. This line break is instead added by the server code:
print(data.decode('utf-8')+"\n")
Both the print itself causes a line break and then you also add another one.
In general you are assuming that each send has a matching recv. This assumption is wrong. TCP is a byte stream and not a message stream and the payloads from multiple send might be merged together to reduce the overhead of sending and it might also cause a "split" into a single "message".
This is especially true when sending traffic between machines since the bandwidth between the machines is less than the local bandwidth and the MTU of the data layer is also much smaller.
Given that you have to first collect your "messages" at the server side. Only after you've got a complete "message" (whatever this is in your case) you should decode('utf-8'). Otherwise your code might crash when trying to decode a character which has a multi-byte UTF-8 encoding but where not all bytes were received yet.

Raw load found, how to access?

To start off, I have read through other raw answers pertaining to scapy on here, however none have been useful, maybe I am just doing something wrong and thats what has brought me here today.
So, for starters, I have a pcap file, which started corrupted with some retransmissions, to my belief I have gotten it back to gether correctly.
It contains Radiotap header, IEEE 802.11 (dot11), logical-link control, IPv4, UDP, and DNS.
To my understanding, the udp packets being transmitted hold this raw data, however, do to a some recent quirks, maybe the raw is in Radiotap/raw.
Using scapy, I'm iterating through the packets, and when a packet with the Raw layer is found, I am using the .show() function of scapy to view it.
As such, I can see that there is a raw load available
###[ Raw ]###
\load \
|###[ Raw ]###
| load = '#\x00\x00\x00\xff\xff\xff\xff\xff\xff\x10h?'
So, I suppose my question is, how can I capture this payload to receive whatever this may be, To my knowledge the load is supposed to be an image file, however I have trouble believing such, so I assume I have misstepped somewhere.
Here is the code I'm using to achieve the above result
from scapy.all import *
from scapy.utils import *
pack = rdpcap('/home/username/Downloads/new.pcap')
for packet in pack:
if packet.getlayer(Raw):
print '[+] Found Raw' + '\n'
l = packet.getlayer(Raw)
rawr = Raw(l)
rawr.show()
Any help, or insight for further reading would be appreciated, I am new to scapy and no expert in packet dissection.
*Side note, previously I had tried (using separate code and server) to replay the packets and send them to myself, to no avail. However I feel thats due to my lack of knowledge in receipt of UDP packets.
UPDATES - I have now tested my pcap file with a scapy reassembler, and I've confirmed I have no fragmented packets, or anything of the sort, so I assume all should go smoothly...
Upon opening my pcap in wireshark, I can see that there are retransmissions, but I'm not sure how much that will affect my goals since no fragmentation occurred?
Also, I have tried the getlayer(Raw).load, if I use print on it I get some gibberish to the screen, I'm assuming its the data to my would-be-image, however I need to now get it into a usable format.
You can do:
data = packet[Raw].load
You should be able to access the field in this way:
l = packet.getlayer(Raw).load
Using Scapy’s interactive shell I was successful doing this:
pcap = rdpcap('sniffed_packets.pcap')
s = pcap.sessions()
for key, value in s.iteritems():
# Looking for telnet sessions
if ':23' in key:
for v in value:
try:
v.getlayer(Raw).load
except AttributeError:
pass
If you are trying to get the load part of the packet only, you can try :
def handle_pkt(pkt):
if TCP in pkt and pkt[TCP].dport == 5201:
#print("got a packet")
print(pkt[IP])
load_part = pkt[IP].load
print("Load#",load_part)
pkt.show2()
sys.stdout.flush()

Python sniffer using pypcap and dpkt on OS X

I'm actually trying to sniff packets with python (using pypcap and dpkt).
I tried the following :
import dpkt, pcap
pc = pcap.pcap() # construct pcap object
pc.setfilter('src host X.X.X.X or dst host X.X.X.X')
for timestamp, packet in pc:
print dpkt.ethernet.Ethernet(packet)
But nothing happens when I launch the script... Did I miss something ?
Using Python 2.7
On OS X Yosemite (10.10)
The question is old but for new people who might hit this. The github 'chains' project uses both pypcap and dpkt for exactly this kind of thing (Disclaimer: I'm involved with all three projects :) https://github.com/SuperCowPowers/chains
chains/sources/packet_streamer.py (code showing use of pypcap for 'sniffing')
chains/links/packet_meta.py (code showing use of dpkt for packet parsing)
For those that just want to use pypcap/dpkt here's a working code snippet:
import pcap
import dpkt
sniffer = pcap.pcap(name=None, promisc=True, immediate=True)
for timestamp, raw_buf in sniffer:
output = {}
# Unpack the Ethernet frame (mac src/dst, ethertype)
eth = dpkt.ethernet.Ethernet(raw_buf)
output['eth'] = {'src': eth.src, 'dst': eth.dst, 'type':eth.type}
# It this an IP packet?
if not isinstance(eth.data, dpkt.ip.IP):
print 'Non IP Packet type not supported %s\n' % eth.data.__class__.__name__
continue
# Grab ip packet
packet = eth.data
# Pull out fragment information
df = bool(packet.off & dpkt.ip.IP_DF)
mf = bool(packet.off & dpkt.ip.IP_MF)
offset = packet.off & dpkt.ip.IP_OFFMASK
# Pulling out src, dst, length, fragment info, TTL, checksum and Protocol
output['ip'] = {'src':packet.src, 'dst':packet.dst, 'p': packet.p,
'len':packet.len, 'ttl':packet.ttl,
'df':df, 'mf': mf, 'offset': offset,
'checksum': packet.sum}
print output
You should check out Scapy. Its a powerful networking tool, that can be used interactivly as well. Its written in python, hence you can use it in your scripts as well.
In scapy its as easy as (but you can easily add filters as well):
sniff(iface='eth0')
If you didn't place the path to a file in pcap.pcap(), there's no pcap for it to parse.
I ran your script with a glob of from a pcap directory I have and replaced the IP with one in my network, seemed like it worked.
You sure you installed pypcap and dpkt?
Here's exactly what I did with your script.
import dpkt, pcap, glob
for i in glob.glob("/pcap/*.pcap"):
pc = pcap.pcap(i)
pc.setfilter('src host 192.168.1.140 or dst host 192.168.1.140')
for timestamp, packet in pc:
print dpkt.ethernet.Ethernet(packet)
It printed a lot of stuff.
Nothing jumps out at the code, so I'm wondering if it is just the network.
Can you double check the IP addresses and also maybe run tcpdump as a sanity check to make sure you can see traffic?
For tcpdump something like this
$ sudo tcpdump -i en1 "src host 10.0.0.2 or dst host 10.0.0.2"

How to send bytes using python (example please!)

I'm trying to create a simple thingermajigger in python at the moment just to test out sending UDP packets over a socket. I think that I'm getting my script perfectly fine other than using the socket.sendto command. I keep getting errors regarding the portion where "bytes" would go... either TypeError: an interget is required, or when I make it an interget TypeError: a string is required. Could someone provide me with an example of how to send a byte?
the point in my script where I'm getting the error is as follows... please fill out an example as well as a possible explanation / documentation for a newbie.
#full script as requested
import socket
import random
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
butes = random._urandom(1024)
#originally found this as a way to generate bytes to send, but it didn't work out
print("target IP: ")
ip = input()
print("port: ")
port = input()
while 1:
sock.sendto(butes, (ip, port))
print("Sent %s amount of packets to %s at port %s." % (sent,ip,port))
sent += 1
In your posted code, port is a str, you should use port = int(input())
Aside: b'0x2E' which you had in the original question is 4 characters. If you mean chr(0x2E) you can also write '\x2E'

Send raw ethernet packet with data field length in type field

I'm trying to send a raw ethernet frame with the length of my data written in the type field. This should be a valid ethernet frame. My code for this looks like this:
ethData = "foobar"
proto =len(ethData)
if proto < 46:
proto = 46
soc = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, proto)
soc.bind((iface, proto))
For some reason I cant read package on the other end. I wonder why. I try to get this package in the interrupt handler of my wireless driver, so this packet has to be droped by my hardware directly or it doesn't get send at all. The question is why.
Sorry, my fault. I just parsed the wrong portion of the packet and didn't get any output. My bad. The package gets there just like it is supposed to.

Categories

Resources