Python raw sockets sniffing & pcap saving

Even though we are pretty used to it, libpcap is not always present on systems. Usually, regardless of your goal, looking at traffic is actually pretty useful. In my experience this applies to offensive (pentesting, red team) work as well as defensive (incident response, network monitoring) work.

One of the first things that comes to mind, when libpcap is not available, is of course raw sockets, since these seem to be always available as long as you have the correct privileges. I’ve written previously about them as well as created some POC for backdoor purposes. Up until now raw sockets haven’t failed me, so when during a recent assignment I had to sniff traffic without libpcap I decided to write some Python code to achieve this. In case you are wondering, yes this was to further gather juicy information from unencrypted protocols like telnet, http and ftp.

A script nowadays never starts without a quick google query to save yourself the trouble of writing everything from scratch. So even though I enjoy writing a lot of things from scratch to learn, in this case I mainly adjusted an excellent example script from: http://askldjd.com/2014/01/15/a-reasonably-fast-python-ip-sniffer/

Adjusting the above script to save the data in pcap format was an easy undertaking and immediately useful. After waiting for a couple of minutes I got myself a nice pcap file which I could analyse on another machine with regular tools like tcpdump or wireshark.

You can find the script on the following gist

Quick POC to mitm RDP ssl

So the other day I stumbled upon this great article from Portcullis Labs. The article explains how you can man-in-the-middle an RDP SSL connection. This can be helpful in obtaining the user’s password, like Portcullis explains in their article. As far as I could tell they didn’t release their tool, so I decided to see if I could whip up a quick POC script with a twist of saving the entire decrypted stream to a pcap file. This would put you in the position to maybe retrieve more sensitive data then just the password. Turns out the only modification from regular SSL intercepting code is more or less the following:

    #read client rdp data
    serversock.sendall(clientsock.recv(19))
    #read server rdp data and check if ssl
    temp = serversock.recv(19)
    clientsock.sendall(temp)
    if(temp[15] == '\x01'):

Like you can see we just pass through the initial packet and then just check the response packet for the ‘SSL’ byte before we start intercepting. The output is pretty boring, since everything is saved to the file ‘output.pcap’:

sudo ./rdps2rdp_pcap.py 
waiting for connection...
('...connected from:', ('10.50.0.123', 1044))
waiting for connection...
Intercepting rdp session from 10.50.0.123
some error happend
some error happend

You can ignore the errors, that’s just me being lazy for this POC. The output is saved in ‘output.pcap’ which you can then open with wireshark or further process to extract all the key strokes. If you want to play around with the POC you can find it on my github as usual. If you plan on extracting the key strokes make sure you look for the key scan codes and not for the hex representation of the character that the victim typed. In case you are wondering, yes , extracting the key strokes is left as an excersise for the user :)

 

raw sockets, pcap files & wireshark quirks?

So this is one of those things that you don’t stumble upon until you are playing with it. When writing sniffers you can use libpcap or it’s win32 version winpcap. Now that doesn’t really do the job in all circumstances, since sometimes you don’t want to install an additional library. Lucky for us you can also sniff traffic by using raw sockets(I’m assuming win32, for the rest of the blog entry). Usually when sniffing with raw sockets you are looking for something specific in the stream of data and can just output it to a good old plain text file…however sometimes you’d just like to capture everything that comes through the network interface. That’s when it becomes interesting to save packets in the PCAP format, so I decided to write my own quick & dirty implementation.

Now here comes the fun part, when sniffing the packets you get everything above the Physical Layer. This means that the Ethernet header is lost and you directly receive the IP header. I did not realize this until I had written the packets into a PCAP file. When trying to open the file with Wireshark, it tries to interpret the first bytes as a Ethernet header which fails horribly. So I came up with two possible solutions:

  • Understand / Configure wireshark to start directly with the IP interpretation
    • Tried this for a while, then decided to go for the second option just for fun.
  • Add a fake Ethernet header to each packet.
    • As previously stated this was the final choice

Well it worked like a charm, Wireshark correctly interpreted the packets and dissected the rest of the contents just as I was used to with normal captures. If anyone knows how to correct the problem WITHOUT writing the fake Ethernet header, by just configuring wireshark correctly DO share.

Here is one last and small warning/readme, before I post the src, for those wanting to play with raw sockets…I’ve noticed some weird behavior myself when testing the sniffer on Win7.

http://www.nirsoft.net/utils/smsniff.html#problems

Under Windows 2000/XP (or greater), SmartSniff also allows you to capture TCP/IP packets without installing any capture driver, by using ‘Raw Sockets’ method. However, this capture method has some limitations and problems:

  • Outgoing UDP and ICMP packets are not captured.
  • On Windows XP SP1 outgoing packets are not captured at all – Thanks to Microsoft’s bug that appeared in SP1 update…
    This bug was fixed on SP2 update, but under Vista, Microsoft returned back the outgoing packets bug of XP/SP1.
  • On Windows Vista with SP1, only UDP packets are captured. TCP packets are not captured at all.
  • On Windows 7, it seems that ‘Raw Sockets’ method works properly again, at least for now…

The header file:


/*

DiabloHorn, fun with pcap and raw sockets

*/

#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <time.h>

typedef struct pcap_hdr_s {
 unsigned int magic_number;   /* magic number */
 unsigned short version_major;  /* major version number */
 unsigned short version_minor;  /* minor version number */
 int  thiszone;       /* GMT to local correction */
 unsigned int sigfigs;        /* accuracy of timestamps */
 unsigned int snaplen;        /* max length of captured packets, in octets */
 unsigned int network;        /* data link type */
} pcap_hdr;

typedef struct pcaprec_hdr_s {
 unsigned int ts_sec;         /* timestamp seconds */
 unsigned int ts_usec;        /* timestamp microseconds */
 unsigned int incl_len;       /* number of octets of packet saved in file */
 unsigned int orig_len;       /* actual length of packet */
} pcaprec_hdr;

HANDLE openpcap(LPCWSTR);
void writepcaprec(HANDLE,void *,int);
void closepcap(HANDLE);

The C file


/*

 DiabloHorn, fun with pcap and raw sockets

 */
#include "pcap.h"

/*
 Opens a pcap file for appending, file is set to +S +H.
 Writes the general header.
*/
HANDLE openpcap(LPCWSTR filename){
 HANDLE hFile = NULL;
 pcap_hdr *genHeader;
 DWORD numWritten;
 //create file with shared read access and set it's attrib to +S +H
 hFile = CreateFile(filename,FILE_APPEND_DATA,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,NULL);
 if(hFile == INVALID_HANDLE_VALUE){
 return hFile;
 }else if(GetLastError() == ERROR_ALREADY_EXISTS){
 printf("Appending to existing pcap file\n");
 return hFile;
 }
 printf("Created empty pcap file\n");
 genHeader = (pcap_hdr *)malloc(sizeof(pcap_hdr));
 memset(genHeader,0,sizeof(pcap_hdr));
 genHeader->magic_number = 0xa1b2c3d4;
 genHeader->network = 1;//ethernet
 genHeader->sigfigs = 0;
 genHeader->snaplen = 65535;
 genHeader->thiszone = 0;
 genHeader->version_major = 2;
 genHeader->version_minor = 4;
 printf("Writing general pcap header\n");

 if(WriteFile(hFile,genHeader,sizeof(pcap_hdr),&numWritten,NULL) == 0){
 //need something more sexy here
 return INVALID_HANDLE_VALUE;
 }
 free(genHeader);
 return hFile;
}

/*
 Write the record of the pcap file
 Write record header (does not take into account the time stuff)
 Write fake eth header
 Write actual ip load data
 NOTE: supplied data must be max size 65521, due to specs in general header
 reason cause of fakeeth and me liking 65535 as a number :-)
*/
void writepcaprec(HANDLE hFile,void *data,int datalen){
 pcaprec_hdr *recHeader;
 DWORD numWritten;
 time_t seconds;
 //fake eth header
 byte fakeeth[14] = {0xde,0xde,0xde,0xde,0xde,0xad,0xbe,0xbe,0xbe,0xbe,0xbe,0xef,0x08,0x00};
 seconds = time(NULL);
 //write pcap record header stuff
 recHeader = (pcaprec_hdr *)malloc(sizeof(pcaprec_hdr));
 memset(recHeader,0,sizeof(pcaprec_hdr));
 recHeader->incl_len = datalen+sizeof(fakeeth);
 recHeader->orig_len = datalen+sizeof(fakeeth);
 recHeader->ts_sec = (unsigned int)seconds;
 recHeader->ts_usec = 0;
 printf("Writing record pcap header\n");
 WriteFile(hFile,recHeader,sizeof(pcaprec_hdr),&numWritten,NULL);
 free(recHeader);
 printf("Writing fake eth header\n");
 //write fake eth header, to fix wireshark
 WriteFile(hFile,fakeeth,sizeof(fakeeth),&numWritten,NULL);
 printf("Writing record data\n");
 //write pcap data stuff
 WriteFile(hFile,data,datalen,&numWritten,NULL);
}

/*
 Prolly hardly used but ohwell...
*/
void closepcap(HANDLE hFile){
 CloseHandle(hFile);
}

and another google password dork

Just when you think that all possible google password dorks have been found and documented. For the ones still not familiar with the google hacking database (just click it) :)

I just stumbled upon this new dork to find passwords(and all other kind of interesting network related data(just enter the following into google):

ext:pcap password

example stuff you can find(I have censored the sensitive information using ***):

+OK Hello there.

AUTH

-ERR Invalid command.

USER ***

+OK Password required.

PASS ***

+OK logged in.

STAT

+OK 0 0

QUIT

+OK Bye-bye.

This was just a quick post…cause I honestly didn’t think people would STILL let google index their sensitive stuff.