First off all, my first post.
This is a sniffer Class that currently only sniffs TCP packets.
It doesn't need PCap at all.
In process_packet() you can change the port you want to sniff on.
Works under Windows 7 64bit, compiled it with MS Visual studio 2010.
Linux, Mac not supported ( but with a bit of hacking you can
probably make it work )
Hint Only works on administrator, means you have to open up the
command prompt with administrator rights..
You can copy/paste and do what you ever like with the class.
Keep in mind I did not 100% tested the class for any bugs
Here we go and goodluck
CSniffer.h
Code:
#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <time.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
using namespace std;
/* packet header structures */
#pragma pack(push, 1)
struct iphdr {
unsigned char ihl:4;
unsigned char ver:4;
unsigned char tos;
unsigned short totlen;
unsigned short id;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int src;
unsigned int dst;
};
struct tcphdr {
unsigned short sport;
unsigned short dport;
unsigned int seq;
unsigned int acknum;
unsigned char unused:4;
unsigned char tcphl:4;
unsigned char Flags;
unsigned short Windows;
unsigned short cksum;
unsigned short UrgPointer;
};
#pragma pack(pop)
#pragma comment(lib, "ws2_32.lib")
#define HOSTNAME_LEN 1024
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define Packet_Size 65536
class CSniffer
{
private:
string uchar2hex(unsigned char inchar);
SOCKET n_SniffSocket;
void Process_Packet(unsigned char *pak, int len);
bool init_winsock();
void Exit(string s_Message);
public:
void Start_Sniffing();
CSniffer(void);
~CSniffer(void);
};
CSniffer.cpp
Code:
#include "CSniffer.h"
CSniffer::CSniffer(void)
{
if( init_winsock() )
{
cout << "init_winsock returned True()" << endl;
cout << "Sniffing all TCP data ()" << endl;
Start_Sniffing();
}
}
CSniffer::~CSniffer(void)
{
}
void CSniffer::Start_Sniffing()
{
// ok no thread we just while loop
unsigned char pak[Packet_Size];
int bytes = 0 ;
while(1)
{
if ((bytes = recv(n_SniffSocket, (char*)pak, sizeof(pak), 0)) == SOCKET_ERROR)
{
Exit("socket error on recv\n");
}else{
Process_Packet(pak, bytes);
}
}
}
void CSniffer::Exit(string s_Message)
{
WSACleanup();
cout << "Exit on ()" << s_Message << endl;
exit(-1);
}
bool CSniffer::init_winsock()
{
WSADATA w;
SOCKADDR_IN sa;
DWORD bytes;
char hostname[HOSTNAME_LEN];
struct hostent *h;
unsigned int opt = 1;
// For windows you need WSAStartup
if (WSAStartup(MAKEWORD(2,2), &w) != 0)
Exit("WSAStartup failed");
// Setting m_SniffSocket to RAW
if ((n_SniffSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
Exit("unable to open raw socket\n");
// use default interface
if ((gethostname(hostname, HOSTNAME_LEN)) == SOCKET_ERROR)
Exit("unable to gethostname\n");
if ((h = gethostbyname(hostname)) == NULL)
Exit("unable to gethostbyname\n");
sa.sin_family = AF_INET;
sa.sin_port = htons(6000);
memcpy(&sa.sin_addr.S_un.S_addr, h->h_addr_list[0], h->h_length);
if ((bind(n_SniffSocket, (SOCKADDR *)&sa, sizeof(sa))) == SOCKET_ERROR)
Exit("unable to bind() socket\n");
// Set promiscuous
if ((WSAIoctl(n_SniffSocket, SIO_RCVALL, &opt, sizeof(opt), NULL, 0, &bytes, NULL, NULL)) == SOCKET_ERROR)
Exit("failed to set promiscuous mode\n");
// all went fine so return true ;)
return true;
}
string CSniffer::uchar2hex(unsigned char inchar)
{
ostringstream oss (ostringstream::out);
oss << setw(2) << setfill('0') << hex <<uppercase << (int)(inchar);
return oss.str();
}
void CSniffer::Process_Packet(unsigned char *pak, int len)
{
struct iphdr *ip;
struct tcphdr *tcp;
unsigned char *data;
unsigned char proto; /* to avoid repeated dereferencing */
int i, datasize;
ip = (struct iphdr *) pak;
proto = ip->proto;
if(proto == IPPROTO_TCP)
{
tcp = (struct tcphdr *) (pak + (ip->ihl * 4));
data = pak + (ip->ihl * 4) + (tcp->tcphl * 4);
datasize = ntohs(ip->totlen) - (ip->ihl*4) - (tcp->tcphl*4);
// Uncomment this if you want to sniff on a Port!
//if( ntohs(tcp->dport ) != PORT NUMBER HERE )
// return ;
cout << "Data size of Packet : " << datasize << endl;
// Print all data to the file.
char a , line[17] , c;
int j;
//loop over each character and print
for(i=0 ; i < datasize ; i++)
{
c = data[i];
//Print the hex value for every character , with a space. Important to make unsigned
cout << " " << uchar2hex(c) ;
//Add the character to data line. Important to make unsigned
a = ( c >=32 && c <=128) ? (unsigned char) c : '.';
line[i%16] = a;
//if last character of a line , then print the line - 16 characters in 1 line
if( (i!=0 && (i+1)%16==0) || i == datasize - 1)
{
line[i%16 + 1] = '\0';
//print a big gap of 10 characters between hex and characters
cout << " ";
//Print additional spaces for last lines which might be less than 16 characters in length
for( j = strlen(line) ; j < 16; j++)
{
cout << " ";
}
cout << line <<endl;
}
}
}
}