views:

337

answers:

3

Hi,

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);
}
+3  A: 

You might want to checkout the source code for this C# network sniffer, here.

BrainCore
Thanks, I've had a look at this but I think it just returns the data as a byte array, not as a string. Is the data in the header likely to be causing an issue converting to a string?
James
@James: Yes, see my post.
Matt Davis
A: 

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);
            }
        }
Mark Byers
+3  A: 

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.

Matt Davis
Cheers Matt, I'll look into this now
James
It now shows the HTTP headers in full! Thanks again!
James