www.pudn.com > ntsniff.zip > ntsniff.c
/* * NtSniff by Davide Libenzi ( To rebuild NtSniff You need Microsoft SDK & DDK ) * Copyright (C) 1999 Davide Libenzi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Davide Libenzi* */ #define UNICODE 1 #include #include #include #include #include #include #include #include #include "packet32.h" #include "ntddndis.h" #define __LITTLE_ENDIAN_BITFIELD #define COUNTOF(a) (sizeof(a) / sizeof((a)[0])) #define SZERO(s) memset(&(s), 0, sizeof(s)) #define PACKETOF(p, r) (memcmp(p, r, sizeof(PACKET_LINK)) == 0) #define MAX_PACKET_SIZE 8192 #define ETH_ALEN 6 #define MAX_VICTIMS 64 #define CAPTLEN 512 #define TIMEOUT 15 #define MAX_LISTEN_PORTS 64 #define MATCH_OR -1 #define MATCH_AND -2 #define VF_RST (1 << 0) #define VF_FIN (1 << 1) #pragma pack(push) #pragma pack(1) typedef unsigned char __u8; typedef unsigned short __u16; typedef unsigned int __u32; /* INDENT OFF */ typedef struct _ETH_HEADER { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; unsigned short h_proto; } ETH_HEADER; typedef struct _IP_HEADER { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4; #endif __u8 tos; __u16 tot_len; __u16 id; __u16 frag_off; __u8 ttl; __u8 protocol; __u16 check; __u32 saddr; __u32 daddr; } IP_HEADER; typedef struct _TCP_HEADER { __u16 source; __u16 dest; __u32 seq; __u32 ack_seq; #if defined(__LITTLE_ENDIAN_BITFIELD) __u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, res2:2; #elif defined(__BIG_ENDIAN_BITFIELD) __u16 doff:4, res1:4, res2:2, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #endif __u16 window; __u16 check; __u16 urg_ptr; } TCP_HEADER; /* INDENT ON */ typedef struct _ETHER_PACKET { ETH_HEADER ETH; IP_HEADER IP; TCP_HEADER TCP; } ETHER_PACKET; typedef struct _CONTROL_BLOCK { PVOID hFile; HANDLE hEvent; TCHAR AdapterName[128]; ULONG PacketLength; ULONG LastReadSize; UINT BufferSize; BYTE PacketBuffer[MAX_PACKET_SIZE]; } CONTROL_BLOCK, *PCONTROL_BLOCK; typedef struct _PACKET_LINK { unsigned long saddr; unsigned long daddr; unsigned short sport; unsigned short dport; } PACKET_LINK, *PPACKET_LINK; typedef struct _VICTIM { PACKET_LINK pl; unsigned long flags; int bytes_read; int active; time_t start_time; char *buffer; } VICTIM; #pragma pack(pop) static int IsListenPorts(int iSrcPort, int iDstPort); static int IsListenAddresses(__u32 saddr, __u32 daddr); static int InitVictims(VICTIM * pVictim, int iNumVictims); static void FreeVictims(VICTIM * pVictim, int iNumVictims); static void FlushVictim(VICTIM * pVictim); static VICTIM *FilterPacket(IP_HEADER * pIpHdr, TCP_HEADER * pTcpHdr, VICTIM * pVictim, int iNumVictims); static void PrintHeader(VICTIM * pVictim); static char *HostLookup(unsigned long int in); static void StoreData(int iDataLenght, char *pszData, VICTIM * pVictim); static void DumpData(int iDataLenght, char *pszData); static void PrintData(int iDataLenght, char *pszData); static void ShowUsage(void); static int ParseCmdLine(int argc, char *argv[]); static BOOL CtrlC_Handler(DWORD dwEvent); static long lSniffedData = 0; static long lMaxSniffedData = 0; static int iStopSniff = 0; static int iResolveAddr = 0; static int iBinMode = 0; static FILE *pDumpFile = NULL; static char szDumpFile[MAX_PATH] = ""; static int iTimeout = TIMEOUT, iCapLenght = CAPTLEN; static CONTROL_BLOCK Adapter; static int iMatchMode = MATCH_OR; static __u32 spy_saddr = 0; static __u32 spy_daddr = 0; static VICTIM Victim[MAX_VICTIMS]; static int iSrcPortsCount = 0; static int iSrcPorts[MAX_LISTEN_PORTS]; static int iDstPortsCount = 0; static int iDstPorts[MAX_LISTEN_PORTS]; static int IsListenPorts(int iSrcPort, int iDstPort) { int ii, match = iMatchMode; if (iSrcPortsCount > 0) { for (ii = 0; ii < iSrcPortsCount; ii++) if (iSrcPorts[ii] == iSrcPort) { ++match; break; } } else ++match; if (iDstPortsCount > 0) { for (ii = 0; ii < iDstPortsCount; ii++) if (iDstPorts[ii] == iDstPort) { ++match; break; } } else ++match; return ((match >= 0) ? 1 : 0); } static int IsListenAddresses(__u32 saddr, __u32 daddr) { int match = iMatchMode; if ((spy_saddr == 0) || (saddr == spy_saddr)) ++match; if ((spy_daddr == 0) || (daddr == spy_daddr)) ++match; return ((match >= 0) ? 1 : 0); } static int InitVictims(VICTIM * pVictim, int iNumVictims) { int ii; for (ii = 0; ii < iNumVictims; ii++) { SZERO(pVictim[ii]); if ((pVictim[ii].buffer = (char *) LocalAlloc(LPTR, iCapLenght + 1)) == NULL) { _ftprintf(stderr, _T("Failed to alloc %d bytes\n"), iCapLenght + 1); for (--ii; ii >= 0; ii--) LocalFree((HLOCAL) pVictim[ii].buffer); return (-1); } } return (0); } static void FreeVictims(VICTIM * pVictim, int iNumVictims) { int ii; for (ii = 0; ii < iNumVictims; ii++) LocalFree((HLOCAL) pVictim[ii].buffer); } static void FlushVictim(VICTIM * pVictim) { if (pVictim->bytes_read > 0) { lSniffedData += pVictim->bytes_read; PrintHeader(pVictim); if (iBinMode) DumpData(pVictim->bytes_read, pVictim->buffer); else PrintData(pVictim->bytes_read, pVictim->buffer); } pVictim->pl.saddr = 0; pVictim->pl.daddr = 0; pVictim->pl.sport = 0; pVictim->pl.dport = 0; pVictim->flags = 0; pVictim->bytes_read = 0; pVictim->active = 0; pVictim->start_time = 0; } static VICTIM *FilterPacket(IP_HEADER * pIpHdr, TCP_HEADER * pTcpHdr, VICTIM * pVictim, int iNumVictims) { int ii; time_t tmcurr = time(NULL); VICTIM *pPktVictim = NULL, *pFreeVictim = NULL; if (pIpHdr->protocol != 6) return (NULL); for (ii = 0; ii < iNumVictims; ii++) { VICTIM *pCurrVictim = &pVictim[ii]; if (pCurrVictim->active != 0) { if (pCurrVictim->flags & VF_RST) { FlushVictim(pCurrVictim); _ftprintf(pDumpFile, _T("\n<<< [RST]\n")); if (pFreeVictim == NULL) pFreeVictim = pCurrVictim; } else if (pCurrVictim->flags & VF_FIN) { FlushVictim(pCurrVictim); _ftprintf(pDumpFile, _T("\n<<< [FIN]\n")); if (pFreeVictim == NULL) pFreeVictim = pCurrVictim; } else if (pCurrVictim->bytes_read > iCapLenght) { FlushVictim(pCurrVictim); _ftprintf(pDumpFile, _T("\n<<< [CAPLEN Exceeded]\n")); if (pFreeVictim == NULL) pFreeVictim = pCurrVictim; } else if (tmcurr > (pCurrVictim->start_time + iTimeout)) { FlushVictim(pCurrVictim); _ftprintf(pDumpFile, _T("\n<<< [Timed Out]\n")); if (pFreeVictim == NULL) pFreeVictim = pCurrVictim; } else if ((pTcpHdr->dest == pCurrVictim->pl.dport) && (pTcpHdr->source == pCurrVictim->pl.sport) && (pIpHdr->saddr == pCurrVictim->pl.saddr) && (pIpHdr->daddr == pCurrVictim->pl.daddr)) { pPktVictim = pCurrVictim; if (pTcpHdr->rst == 1) pPktVictim->flags |= VF_RST; if (pTcpHdr->fin == 1) pPktVictim->flags |= VF_FIN; } } else if (pFreeVictim == NULL) pFreeVictim = pCurrVictim; } if (pPktVictim != NULL) return (pPktVictim); if ((pFreeVictim != NULL) && IsListenPorts(ntohs(pTcpHdr->source), ntohs(pTcpHdr->dest)) && IsListenAddresses(pIpHdr->saddr, pIpHdr->daddr)) { if (pTcpHdr->syn == 1) { pFreeVictim->pl.saddr = pIpHdr->saddr; pFreeVictim->pl.daddr = pIpHdr->daddr; pFreeVictim->pl.sport = pTcpHdr->source; pFreeVictim->pl.dport = pTcpHdr->dest; pFreeVictim->flags = 0; pFreeVictim->active = 1; pFreeVictim->bytes_read = 0; pFreeVictim->start_time = time(NULL); if (pTcpHdr->rst == 1) pFreeVictim->flags |= VF_RST; if (pTcpHdr->fin == 1) pFreeVictim->flags |= VF_FIN; return (pFreeVictim); } } return (NULL); } static void PrintHeader(VICTIM * pVictim) { fprintf(pDumpFile, "\n>>> { %s [%d] => ", HostLookup(pVictim->pl.saddr), (int) ntohs(pVictim->pl.sport)); fprintf(pDumpFile, "%s [%d] }\n", HostLookup(pVictim->pl.daddr), (int) ntohs(pVictim->pl.dport)); } static char *HostLookup(unsigned long int in) { static char szHostName[512] = ""; struct in_addr iaddr; SZERO(iaddr); iaddr.s_addr = in; if (iResolveAddr) { struct hostent *he = gethostbyaddr((char *) &iaddr, sizeof(struct in_addr), AF_INET); if (he == NULL) strcpy(szHostName, inet_ntoa(iaddr)); else strcpy(szHostName, he->h_name); } else strcpy(szHostName, inet_ntoa(iaddr)); return (szHostName); } static void StoreData(int iDataLenght, char *pszData, VICTIM * pVictim) { int iStoreSize = min(iDataLenght, iCapLenght - pVictim->bytes_read); char *buffer = pVictim->buffer + pVictim->bytes_read; memcpy(buffer, pszData, iStoreSize); pVictim->bytes_read += iStoreSize; } static void DumpData(int iDataLenght, char *pszData) { int ii = 0; while (ii < iDataLenght) { int jj, iSize = min(16, iDataLenght - ii); for (jj = 0; jj < 16; jj++) if (jj < iSize) _ftprintf(pDumpFile, _T("%02X "), (unsigned int) pszData[ii + jj] & 0xff); else _ftprintf(pDumpFile, _T(" ")); _ftprintf(pDumpFile, _T("| ")); for (jj = 0; jj < iSize; jj++) if (isprint(pszData[ii + jj])) _ftprintf(pDumpFile, _T("%c"), pszData[ii + jj]); else _ftprintf(pDumpFile, _T(".")); _ftprintf(pDumpFile, _T("\n")); ii += iSize; } } static void PrintData(int iDataLenght, char *pszData) { int ii, tt = 0; for (ii = 0; ii < iDataLenght; ii++) { if (pszData[ii] == 13) { _ftprintf(pDumpFile, _T("\n")); tt = 0; } else if (isprint(pszData[ii])) { _ftprintf(pDumpFile, _T("%c"), pszData[ii]); tt++; } if (tt > 78) { tt = 0; _ftprintf(pDumpFile, _T("\n")); } } if (tt > 0) _ftprintf(pDumpFile, _T("\n")); } static void ShowUsage(void) { _ftprintf(stderr, _T("<<< NtSniff 1.5 by Davide Libenzi - davidel@maticad.it >>>\n" "Use: ntsniff [-hfbrARmcostST]\n" "-h = Show this help\n" "-f s = Set output file [ StdOut ]\n" "-b = Set binary mode\n" "-r = Resolve address names ( slower )\n" "-A = Set rules match mode to AND\n" "-R = Set rules match mode to OR [ Default ]\n" "-m i = Set max bytes x session [ Unlimited ]\n" "-c i = Set max bytes x packet capture [ %d ]\n" "-o i = Set sniff timeout [ %d ]\n" "-s s = Set sniffer victim ( source ) [ All ]\n" "-t s = Set sniffer victim ( target ) [ All ]\n" "-S i = Set port to sniff ( -S i1 -S i2 ... source ) [ All ]\n" "-T i = Set port to sniff ( -T i1 -T i2 ... target ) [ All ]\n"), CAPTLEN, TIMEOUT); } static int ParseCmdLine(int argc, char *argv[]) { int ii; for (ii = 1; ii < argc; ii++) { if (argv[ii][0] != '-') { ShowUsage(); return (-1); } switch (argv[ii][1]) { case ('S'): { if (++ii < argc) { if (iSrcPortsCount < (MAX_LISTEN_PORTS - 1)) { iSrcPorts[iSrcPortsCount] = atoi(argv[ii]); ++iSrcPortsCount; } } } break; case ('T'): { if (++ii < argc) { if (iDstPortsCount < (MAX_LISTEN_PORTS - 1)) { iDstPorts[iDstPortsCount] = atoi(argv[ii]); ++iDstPortsCount; } } } break; case ('s'): { if (++ii < argc) { __u32 spy_addr; struct hostent *he; he = gethostbyname(argv[ii]); if (he == NULL) spy_addr = inet_addr(argv[ii]); else spy_addr = *(__u32 *) he->h_addr_list[0]; spy_saddr = spy_addr; } } break; case ('t'): { if (++ii < argc) { __u32 spy_addr; struct hostent *he; he = gethostbyname(argv[ii]); if (he == NULL) spy_addr = inet_addr(argv[ii]); else spy_addr = *(__u32 *) he->h_addr_list[0]; spy_daddr = spy_addr; } } break; case ('o'): { if (++ii < argc) iTimeout = atoi(argv[ii]); } break; case ('c'): { if (++ii < argc) iCapLenght = atoi(argv[ii]); } break; case ('m'): { if (++ii < argc) lMaxSniffedData = atol(argv[ii]); } break; case ('f'): { if (++ii < argc) strcpy(szDumpFile, argv[ii]); } break; case ('r'): { iResolveAddr = 1; } break; case ('b'): { iBinMode = 1; } break; case ('R'): { iMatchMode = MATCH_OR; } break; case ('A'): { iMatchMode = MATCH_AND; } break; case ('h'): default: ShowUsage(); return (-1); } } return (0); } static BOOL CtrlC_Handler(DWORD dwEvent) { ++iStopSniff; return (TRUE); } int __cdecl main(int argc, char *argv[]) { int ii, iPacketCount = 0, iPacketSniffed = 0; WORD wVersionRequested = MAKEWORD(2, 0); ULONG NameLength = sizeof(Adapter.AdapterName); PVOID pPacket; ETHER_PACKET *pEthPkt = (ETHER_PACKET *) Adapter.PacketBuffer; IP_HEADER *pIpHdr = (IP_HEADER *) ((char *) &pEthPkt->IP); WSADATA wsaData; if (WSAStartup(wVersionRequested, &wsaData) != 0) { _ftprintf(stderr, _T("Unable to find socket library\n")); return (1); } if (ParseCmdLine(argc, argv) < 0) { WSACleanup(); return (1); } SZERO(Adapter); PacketGetAdapterNames(Adapter.AdapterName, &NameLength); Adapter.BufferSize = MAX_PACKET_SIZE; if ((Adapter.hFile = PacketOpenAdapter(Adapter.AdapterName)) == NULL) { _ftprintf(stderr, _T("Unable to open adapter %s\n"), Adapter.AdapterName); WSACleanup(); return (1); } PacketSetFilter(Adapter.hFile, NDIS_PACKET_TYPE_PROMISCUOUS); if ((pPacket = PacketAllocatePacket(Adapter.hFile)) == NULL) { _ftprintf(stderr, _T("Unable to allocate packet\n")); PacketCloseAdapter(Adapter.hFile); WSACleanup(); return (1); } SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlC_Handler, TRUE); if (InitVictims(Victim, COUNTOF(Victim)) < 0) { PacketFreePacket(pPacket); PacketCloseAdapter(Adapter.hFile); WSACleanup(); return (1); } if (strlen(szDumpFile) > 0) pDumpFile = fopen(szDumpFile, "wt"); else pDumpFile = stdout; while (!iStopSniff) { PacketInitPacket(pPacket, Adapter.PacketBuffer, Adapter.BufferSize); PacketReceivePacket(Adapter.hFile, pPacket, TRUE, &Adapter.PacketLength); ++iPacketCount; if (Adapter.PacketLength > (sizeof(ETH_HEADER) + sizeof(IP_HEADER) + sizeof(TCP_HEADER))) { int i_IPH_Size = pIpHdr->ihl * 4; TCP_HEADER *pTcpHdr = (TCP_HEADER *) ((char *) pIpHdr + i_IPH_Size); int i_TCPH_Size = pTcpHdr->doff * 4; VICTIM *pVictim = FilterPacket(pIpHdr, pTcpHdr, Victim, COUNTOF(Victim)); if (pVictim != NULL) { int iDataSize = ((int) ntohs(pIpHdr->tot_len) - i_IPH_Size - i_TCPH_Size); BYTE *pPktData = (BYTE *) pTcpHdr + i_TCPH_Size; ++iPacketSniffed; StoreData(iDataSize, (char *) pPktData, pVictim); } if ((lMaxSniffedData > 0) && (lSniffedData > lMaxSniffedData)) break; } } for (ii = 0; ii < COUNTOF(Victim); ii++) FlushVictim(&Victim[ii]); FreeVictims(Victim, COUNTOF(Victim)); if (pDumpFile != stdout) fclose(pDumpFile); _ftprintf(stderr, _T("Received %d packets - %d sniffed\n"), iPacketCount, iPacketSniffed); PacketFreePacket(pPacket); PacketResetAdapter(Adapter.hFile); PacketCloseAdapter(Adapter.hFile); WSACleanup(); return (0); }