Click here to Skip to main content
15,886,258 members
Articles / Desktop Programming / MFC

Internet Traffic Firewall and Sniffer

Rate me:
Please Sign up or sign in to vote.
4.91/5 (26 votes)
23 Oct 2007GPL33 min read 100.9K   9.1K   133  
The article demonstrates internet packets interception with firewall capabilities based on IpFilterDriver driver and sending TCP/UDP/ICMP packets using raw sockets with IP spoofing support.

#include "StdAfx.h"
#include ".\packet.h"

CPacket::CPacket(void): packet(0), icmp(0), ip4(0), udp(0), tcp(0), data(0), datasize(0),
                fakepack(0)
{
}                // ip packet     size      (struct ippack)
CPacket::CPacket(u_char *packet, int size, ippacket *ippack): icmp(0), ip4(0), udp(0), tcp(0), data(0), datasize(0),
                fakepack(0)
{
        this->packet = packet;
        this->size = size;
        this->ippack = ippack;
        parsepacket();
}
CPacket::~CPacket(void)
{
        if (packet)
                delete[] packet;
}


void CPacket::parsepacket()
{
        WCHAR port[256];
        in_addr addr;

        int ip4hdrlen = 0;           //ip4 hdr length
        int tcphdrlen = 0;           //tcp hdr len


        _wstrtime(ippack->time);
        _wstrdate(ippack->date);

        if ((packet[0] & 0xF0) == 0x40) {         //ip4
                ip4 = (ip4_header *)packet;
                ip4hdrlen = int(ip4->ver_ihl & 0x0F) * 4;

                protoent *proto = getprotobynumber(ip4->proto);
                if (proto)
                        MultiByteToWideChar(CP_ACP, 0, proto->p_name, (int)strlen(proto->p_name) + 1, ippack->proto, sizeof(ippack->proto) / sizeof(ippack->proto[0]));
                else
                        wsprintf(ippack->proto, L"%u", ip4->proto);

                wsprintf(ippack->ident, L"%u", ntohs(ip4->identification));
                wsprintf(ippack->ttl, L"%u", ip4->ttl);
                wsprintf(ippack->foffs, L"%u", ntohs(ip4->flags_fo)&0x1FFF);
                MultiByteToWideChar(CP_ACP, 0, inet_ntoa(ip4->saddr), (int)strlen(inet_ntoa(ip4->saddr)) + 1, ippack->saddr, sizeof(ippack->saddr) / sizeof(ippack->saddr[0]));
                MultiByteToWideChar(CP_ACP, 0, inet_ntoa(ip4->daddr), (int)strlen(inet_ntoa(ip4->daddr)) + 1, ippack->daddr, sizeof(ippack->daddr) / sizeof(ippack->daddr[0]));


                switch (ip4->proto) {
                case 1:                              //icmp
                        icmp = (icmp_header *)(packet + ip4hdrlen);
                        wsprintf(ippack->itype, L"%u", icmp->type);
                        wsprintf(ippack->icode, L"%u", icmp->code);
                        if (icmp->type != 5) {
                                wsprintf(ippack->iident, L"%u", ntohs(icmp->ident));
                                wsprintf(ippack->iseq, L"%u", ntohs(icmp->seqnum));
                        }

                        data = (u_char *)icmp + sizeof(icmp_header);
                        datasize = size - int(data - packet);
                        if (datasize <= 0) {
                                datasize = 0;
                                data = 0;
                        }

                        switch (icmp->type) {
                        case 17:
                        case 18:
                                addr.S_un.S_addr = *((u_long *)data);
                                MultiByteToWideChar(CP_ACP, 0, inet_ntoa(addr), (int)strlen(inet_ntoa(addr)) + 1, ippack->iaddr, sizeof(ippack->iaddr) / sizeof(ippack->iaddr[0]));
                                break;
                        case 5:
                                addr.S_un.S_addr = *((u_long *) & icmp->ident);
                                MultiByteToWideChar(CP_ACP, 0, inet_ntoa(addr), (int)strlen(inet_ntoa(addr)) + 1, ippack->iaddr, sizeof(ippack->iaddr) / sizeof(ippack->iaddr[0]));
                                break;
                        case 13:
                        case 14:
                                wsprintf(ippack->iorigt, L"%u", *((u_long *)data));
                                wsprintf(ippack->irecvt, L"%u", *((u_long *)data + 1));
                                wsprintf(ippack->itrant, L"%u", *((u_long *)data + 2));
                                break;
                        }
                        break;

                case 6:                              //tcp
                        tcp = (tcp_header *)(packet + ip4hdrlen);
                        if (tcp->dataoffs >> 4) {
                                data = (u_char *)tcp + int(tcp->dataoffs >> 4) * 4;
                                datasize = size - int(data - packet);
                                if (datasize <= 0) {
                                        datasize = 0;
                                        data = 0;
                                }
                        }

                        wsprintf(port, L"(%u)", ntohs(tcp->sport));
                        lstrcat(ippack->saddr, port);
                        wsprintf(port, L"(%u)", ntohs(tcp->dport));
                        lstrcat(ippack->daddr, port);
                        wsprintf(ippack->seqnum, L"%u", ntohl(tcp->seqnum));
                        wsprintf(ippack->acknum, L"%u", ntohl(tcp->acknum));
                        for (int i = 0; i < 6; i++) {
                                if (u_char(1 << i) & tcp->ctrlbits)
                                        lstrcat(ippack->ctrlbits, BITS[i].bits);
                        }
                        wsprintf(ippack->window, L"%u", ntohs(tcp->window));
                        break;

                case 17:                             //udp
                        udp = (udp_header *)(packet + ip4hdrlen);
                        if (ntohs(udp->len) - sizeof(udp_header)) {
                                if ((size - ip4hdrlen) < ntohs(udp->len)) {
                                        data = 0;
                                        datasize = ntohs(udp->len) - sizeof(udp_header);
                                        fakepack = true;
                                } else {
                                        data = (u_char *)(udp) + sizeof(udp_header);
                                        datasize = ntohs(udp->len) - sizeof(udp_header);
                                }
                        }

                        wsprintf(port, L"(%u)", ntohs(udp->sport));
                        lstrcat(ippack->saddr, port);
                        wsprintf(port, L"(%u)", ntohs(udp->dport));
                        lstrcat(ippack->daddr, port);
                        break;

                default:

                        break;
                }

                wsprintf(ippack->size, L"%u", size);
                wsprintf(port, L"(%u", datasize);
                lstrcat(ippack->size, port);
                if (fakepack)lstrcat(ippack->size, L"?");
                lstrcat(ippack->size, L")");

                if (size != ntohs(ip4->tlen)) {
                        wsprintf(port, L" %u?", ntohs(ip4->tlen));
                        lstrcat(ippack->size, port);
                }
        }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////




///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
int CPacket::sendicmp(SOCKET s, ip4_header *ip4, icmp_header *icmp)
{
        int status = 0, size = 0;
        u_char *packet = 0;
        char *data = 0, mess[] = "helo there.";


        switch (icmp->type) {
        case 0:
        case 8:                                           //Echo
                data = new char[sizeof(mess) + 1000];
                size = sizeof(mess);
                memcpy(data, &mess, size);
                break;
        case 13:
        case 14:                                          //Time stamp
                data = new char[4*3 + 1000];                  //12 bytes for time stamps
                size = 4 * 3;
                memset(data, 0, 12);
                break;
        case 17:
        case 18:                                          //Addr mask
                data = new char[4 + 1000];
                size = 4;
                memset(data, 0, 4);
                break;

        case 15:
        case 16:
                break;

        default:
                data = new char[sizeof(ip4_header) + 8];      //ip4hdr + 64bit
                size = sizeof(ip4_header) + 8;
                memset(data, 0, 4);
                break;
        }

        if (data && size) {
                int len = ntohs(ip4->tlen);
                ip4->tlen = htons(len + size);
        }


        packet = new u_char[sizeof(ip4_header) + sizeof(icmp_header) + size];

        /*                   CRC's                                */
        ip4->crc = ipchksum((u_short *)ip4, sizeof(ip4_header));
        icmp->crc = icmpchksum(icmp, data, size);
        /*                   CRC's                                */

        memcpy(packet, ip4, sizeof(ip4_header));
        memcpy(packet + sizeof(ip4_header), icmp, sizeof(icmp_header));
        if (data && size)
                memcpy(packet + sizeof(ip4_header) + sizeof(icmp_header), data, size);



        sockaddr_in saddr;
        saddr.sin_family = AF_INET;
        saddr.sin_port = 0;
        saddr.sin_addr.S_un.S_addr = ip4->daddr.S_un.S_addr;
        status = sendto(s, (char *)packet, sizeof(ip4_header) + sizeof(icmp_header) + size,
                        0, (sockaddr *) & saddr, sizeof(saddr));



        if (data) delete[] data;
        if (packet) delete[] packet;
        return status;
}

int CPacket::sendudp(SOCKET s, ip4_header *ip4, udp_header *udp, char *data, int size)
{
        int status = 0;
        u_char *packet = new u_char[sizeof(ip4_header) + sizeof(udp_header) + size];


        /*                   CRC's                                */
        ip4->crc = ipchksum((u_short *)ip4, sizeof(ip4_header));           //?
        udp->crc = udpchksum(ip4, udp, data, size);                        //?
        /*                   CRC's                                */



        memcpy(packet, ip4, sizeof(ip4_header));
        memcpy(packet + sizeof(ip4_header), udp, sizeof(udp_header));
        if (data && size)
                memcpy(packet + sizeof(ip4_header) + sizeof(udp_header), data, size);



        sockaddr_in saddr;
        saddr.sin_family = AF_INET;
        saddr.sin_port = udp->dport;     //already htons()
        saddr.sin_addr.S_un.S_addr = ip4->daddr.S_un.S_addr;
        status = sendto(s, (char *)packet, sizeof(ip4_header) + sizeof(udp_header) + size,
                        0, (sockaddr *) & saddr, sizeof(saddr));



        delete[] packet;
        return status;
}

int CPacket::sendtcp(SOCKET s, ip4_header *ip4, tcp_header *tcp, char *data, int size)
{
        int status = 0;
        u_char *packet = new u_char[sizeof(ip4_header) + sizeof(tcp_header) + size];


        //                   CRC's                                //
        ip4->crc = ipchksum((u_short *)ip4, sizeof(ip4_header));                //no htons ?
        tcp->crc = tcpchksum(ip4, tcp, data, size);                             //??????????
        //                   CRC's                                //



        memcpy(packet, ip4, sizeof(ip4_header));
        memcpy(packet + sizeof(ip4_header), tcp, sizeof(tcp_header));
        if (data && size)
                memcpy(packet + sizeof(ip4_header) + sizeof(tcp_header), data, size);



        sockaddr_in daddr;
        daddr.sin_family = AF_INET;
        daddr.sin_port = tcp->dport;     //already htons()
        daddr.sin_addr.S_un.S_addr = ip4->daddr.S_un.S_addr;
        status = sendto(s, (char *)packet, sizeof(ip4_header) + sizeof(tcp_header) + size,
                        0, (sockaddr *) & daddr, sizeof(daddr));



        delete[] packet;
        return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/*FILE *fp = fopen("pack00.pck","wb");
			fwrite(packet,1, sizeof(ip4_header) + sizeof(udp_header) + size, fp);
	    fclose(fp);*/





///////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////CRC's//////////////////////////////////////////////////////////////////////
u_short CPacket::ipchksum(u_short *addr, int len)
{
        int sum = chksum(addr, len);

        sum = (sum >> 16) + (sum & 0xffff);
        return u_short(~sum);
}

u_short CPacket::udpchksum(ip4_header *ip4, udp_header *udp, char *data, int size)
{
        int sum = chksum((u_short *) & ip4->saddr, 8);                   //saddr + daddr
        sum += htons(ip4->proto);                                      //proto
        sum += udp->len;                                               //len already htons()

        sum += chksum((u_short *)udp, sizeof(udp_header));            //udp header
        if (data && size)
                sum += chksum((u_short *)data, size);                         //udp data

        sum = (sum >> 16) + (sum & 0xffff);
        return u_short(~sum);
}

u_short CPacket::tcpchksum(ip4_header *ip4, tcp_header *tcp, char *data, int size)
{
        int sum = chksum((u_short *) & ip4->saddr, 8);                   //saddr + daddr
        sum += htons(ip4->proto);                                      //proto
        sum += htons(u_short(sizeof(tcp_header) + size));

        sum += chksum((u_short *)tcp, sizeof(tcp_header));            //udp header
        if (data && size)
                sum += chksum((u_short *)data, size);                         //udp data

        sum = (sum >> 16) + (sum & 0xffff);
        return u_short(~sum);
}

u_short CPacket::icmpchksum(icmp_header *icmp, char *data, int size)
{
        int sum = chksum((u_short *)icmp, sizeof(icmp_header));            //icmp header

        if (data && size)
                sum += chksum((u_short *)data, size);                         //udp data

        sum = (sum >> 16) + (sum & 0xffff);
        return u_short(~sum);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
int CPacket::chksum(u_short *addr, int len)
{
        int nleft = len;
        int sum = 0;

        while (nleft > 1)  {
                sum += *addr++;
                nleft -= 2;
        }
        /* mop up an odd byte, if necessary */
        if (nleft == 1) {
                u_short	u = 0;

                *(u_char *)(&u) = *(u_char *)addr ;
                sum += u;
        }

        return sum;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
LPCTSTR CPacket::geterror()
{
        switch (WSAGetLastError()) {
        case WSAEINTR:
                return L"Interrupted function call.";
        case WSAEACCES:
                return L"Permission denied.";
        case WSAEFAULT:
                return L"Bad address.";
        case WSAEINVAL:
                return L"Invalid argument.";
        case WSAEMFILE:
                return L"Too many open files.";
        case WSAEWOULDBLOCK:
                return 0;
        case WSAEINPROGRESS:
                return L"Operation now in progress.";
        case WSAEALREADY:
                return L"Operation already in progress.";
        case WSAENOTSOCK:
                return L"Socket operation on nonsocket.";
        case WSAEDESTADDRREQ:
                return L"Destination address required.";
        case WSAEMSGSIZE:
                return L"Message too long.";
        case WSAEPROTOTYPE:
                return L"Protocol wrong type for socket.";
        case WSAENOPROTOOPT:
                return L"Bad protocol option.";
        case WSAEPROTONOSUPPORT:
                return L"Protocol not supported.";
        case WSAESOCKTNOSUPPORT:
                return L"Socket type not supported.";
        case WSAEOPNOTSUPP:
                return L"Operation not supported.";
        case WSAEPFNOSUPPORT:
                return L"Protocol family not supported.";
        case WSAEAFNOSUPPORT:
                return L"Address family not supported by protocol family.";
        case WSAEADDRINUSE:
                return L"Address already in use.";
        case WSAEADDRNOTAVAIL:
                return L"Cannot assign requested address.";
        case WSAENETDOWN:
                return L"Network is down.";
        case WSAENETUNREACH:
                return L"Network is unreachable.";
        case WSAENETRESET:
                return L"Network dropped connection on reset.";
        case WSAECONNABORTED:
                return L"Software caused connection abort.";
        case WSAECONNRESET:
                return L"Connection reset by peer.";
        case WSAENOBUFS:
                return L"No buffer space available.";
        case WSAEISCONN:
                return L"Socket is already connected.";
        case WSAENOTCONN:
                return L"Socket is not connected.";
        case WSAESHUTDOWN:
                return L"Cannot send after socket shutdown.";
        case WSAETIMEDOUT:
                return L"Connection timed out.";
        case WSAECONNREFUSED:
                return L"Connection refused.";
        case WSAEHOSTDOWN:
                return L"Host is down.";
        case WSAEHOSTUNREACH:
                return L"No route to host.";
        case WSAEPROCLIM:
                return L"Too many processes.";
        case WSASYSNOTREADY:
                return L"Network subsystem is unavailable.";
        case WSAVERNOTSUPPORTED:
                return L"Winsock.dll version out of range.";
        case WSANOTINITIALISED:
                return L"Successful WSAStartup not yet performed.";
        case WSAEDISCON:
                return L"Graceful shutdown in progress.";
        case WSATYPE_NOT_FOUND:
                return L"Class type not found.";
        case WSAHOST_NOT_FOUND:
                return L"Host not found.";
        case WSATRY_AGAIN:
                return L"Nonauthoritative host not found.";
        case WSANO_RECOVERY:
                return L"This is a nonrecoverable error.";
        case WSANO_DATA:
                return L"Valid name, no data record of requested type.";
        case WSA_INVALID_HANDLE:
                return L"Specified event object handle is invalid.";
        case WSA_INVALID_PARAMETER:
                return L"One or more parameters are invalid.";
        case WSA_IO_INCOMPLETE:
                return L"Overlapped I/O event object not in signaled state.";
        case WSA_IO_PENDING:
                return L"Overlapped operations will complete later.";
        case WSA_NOT_ENOUGH_MEMORY:
                return L"Insufficient memory available.";
        case WSA_OPERATION_ABORTED:
                return L"Overlapped operation aborted.";
                //case WSAINVALIDPROCTABLE:                                            //not in Visual C++ 7.0
                // return "Invalid procedure table from service provider.";
                //case WSAINVALIDPROVIDER:
                // return "Invalid service provider version number.";
                //case WSAPROVIDERFAILEDINIT:
                // return "Unable to initialize a service provider.";
        case WSASYSCALLFAILURE:
                return L"System call failure.";
        default:
                return L"Unknown code?";
        }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Engineer
Russian Federation Russian Federation
Highly skilled Engineer with 14 years of experience in academia, R&D and commercial product development supporting full software life-cycle from idea to implementation and further support. During my academic career I was able to succeed in MIT Computers in Cardiology 2006 international challenge, as a R&D and SW engineer gain CodeProject MVP, find algorithmic solutions to quickly resolve tough customer problems to pass product requirements in tight deadlines. My key areas of expertise involve Object-Oriented
Analysis and Design OOAD, OOP, machine learning, natural language processing, face recognition, computer vision and image processing, wavelet analysis, digital signal processing in cardiology.

Comments and Discussions