I've been trying to write a script that will sniff HTTP headers. So far I've got the socket bound to port 80 and packets seem to be received, but I can't get them into string form. All that outputs is "E" continuously. I changed the bytes into hex earlier and there seems to be some data coming in, but the current code is unable to change the bytes into a string. Is there some other way of decoding the bytes that will give a proper string?
byte[] input = BitConverter.GetBytes(1);
byte[] buffer = new byte[4096];
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
s.Bind(new IPEndPoint(IPAddress.Parse(strIP), 80));
s.IOControl(IOControlCode.ReceiveAll, input, null);
int bytes;
bytes = s.Receive(buffer);
while (bytes > 0)
{
log(System.Text.Encoding.ASCII.GetString(buffer, 0, bytes));
bytes = s.Receive(buffer);
}
When you sniff data using a raw socket, you're receiving Internet Protocol (IP) packets. Each IP packet begins with an IP header. This header is typically 20 bytes long, but it can be longer than that. Following the IP header is the header for the Transport Layer, e.g., the Transmission Control Protocol (TCP) header or the User Datagram Protocol (UDP) header. After this header comes the data you're looking for, i.e., the HTTP. So when you're parsing the data, you need to skip past the IP header and the Transport Layer header first.
You might want to checkout the source code for this C# network sniffer, here.
Firstly, why are you writing this using raw sockets and changing the IOControl? I tried running your code on Vista and it wouldn't work, even as administrator. Can you use a higher level of abstraction, such as TcpClient instead?
Secondly, you need to send a request before you get a response. The simplest request you can send is "GET /\n" where \n is the character for a new line.
Here is some code that you could use (the Write method needs to check the return value too, but this is omitted for simplicity):
using (TcpClient tcpClient = new TcpClient(strIP, 80))
{
using (Stream s = tcpClient.GetStream())
{
byte[] bytesToSend = Encoding.ASCII.GetBytes("GET /\n");
s.Write(bytesToSend, 0, bytesToSend.Length);
int bytes;
byte[] buffer = new byte[4096];
do
{
bytes = s.Read(buffer, 0, buffer.Length);
Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytes));
} while (bytes > 0);
}
}