I already programmed several tools in Windows that
make use of raw sockets as Windows NT 5.0 and later
OS (those include 2k and XP) support raw sockets in the
Winsock 2 API. I used C/C++ for programming them
mainly, but I figured python had the better builtin tools
for building custom packets. However, I witnessed
several problems when trying to create and use raw
sockets in Python (Version 2.3, Windows interpreter):
The raw socket was created, but the IP_HDRINCL
option, for instance, could not be set once the socket
was bound. This one and similar problems were indicating
that the raw sockets implementation was either
unavailable or had some strange bug.
After I had tried to find the problem in socketmodule.c
for a while, I realized the problem was not the code, it
was the library that had been linked with _socket.pyd. It
looks like _socket.pyd links to wsock32.dll by default,
which is the DLL that implements Winsock 1 for 32-bit
windows. However, it should link to ws2_32.dll to provide
access to the more up-to-date Winsock 2 API. The fix I
suggest is fairly simple. The key is the WSAStartup()
function which will let you use the Winsock2 API if it is
available or use Winsock1 if Winsock2 is not available.
For this purpose, I link using ws2_32.lib as recommended
by MSDN and call WSAStartup() by requesting a Winsock
Version of 2.0. MSDN says that if Winsock 2.0 is
unavailable, the call will succeed and the Winsock 1 DLL
will be used.
This fix works pretty well on my Windows 2k machine - I
am unfortunately not able to test it on other machines
as well. While messing with the problem, I got a lot of
help from Matt Cowles [matt@mondoinfo.com] and he
also suggested that I should post this request here, so
that's what I am doing.
by_the_way:
As I was already messing with the _socket.pyd dll
directly, I also added a new member function for python
sockets called ioctl() to manually ioctl() the socket.
Moreover, I added the integer constants IP_HDRINCL
and SIO_RCVALL to be defined always, so that this code
works and provides pretty satisfying results on my Win2k
box (a simple sniffer):
from socket import *
s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW)
s.bind((gethostbyname(gethostname()),0))
s.setsockopt(IPPROTO_IP,IP_HDRINCL,1)
s.ioctl(SIO_RCVALL,1)
while(1): print s.recvfrom(4000)[0],"\n------------"
The files I changed (including socket.py with the new
ioctl function) can be found at:
http://rs.fromadia.com/pysockraw/
It would be very kind if the next version of the Python
interpreter for windows would include this feature by
default as it would allow developers like me to build
python tools that make use of raw sockets in
Windows ... I can see not many developers are
interested in this particular feature, but more support is
better than less support.
|