Implementation of simple network sniffer

Source: Internet
Author: User

This article introduces a simple network Sniffer implemented by using C language and network data packet analysis and development tools. Currently, many Sniff tools are available, such as Netxray and Sniffer pro in Windows. It is very convenient to capture packets in Windows. It is common in UNIX environments such as Sniffit, Snoop, Tcpdump, and Dsniff. This section describes a simple network Sniffer implemented using C language and network data packets and analysis development tools libpcap and winpcap.
Network sniffer program diagram
First, process 1 is provided.

Figure 1 Flowchart
 Network sniffer program implementation
Programming in c environment, the source code is as follows:

/* Jun 2nd, 2002
* Project for graduation qualification By lobby Team 19 */
# Include <stdio. h>
# Include <conio. h>
// The path must be added. The header file packet32.h must be included.
# Include "... Includepacket32.h"
# Include "... Includentddndis. h"
# Define Max_Num_Adapter 10
// Prototypes prototype
// Send packets
Void PrintPackets (LPPACKET lpPacket );
// Device List
Char AdapterList [Max_Num_Adapter] [1024];
// Start the main program
Int main ()
{
// Define a pointer to an ADAPTER structure device pointer
LPADAPTER lpAdapter = 0;
// Define a pointer to a PACKET structure package pointer
LPPACKET lpPacket;
Int I;
DWORD dwErrorCode;
DWORD dwVersion;
DWORD dwWindowsMajorVersion;
// Unicode strings (WinNT)
WCHAR AdapterName [8192]; // list of network adapter devices
WCHAR * temp, * temp1;
// ASCII strings (Win9x)
Char AdapterNamea [8192]; // list of network adapter devices
Char * tempa, * temp1a;
Int AdapterNum = 0, Open;
ULONG AdapterLength;
Char buffer [256000]; // buffer that holds data from the drive
Struct bpf_stat stat;
// Obtain the local Nic name
AdapterLength = 4096;
Printf ("Packet. dll test application. Library version: % sn", PacketGetVersion ());
Printf ("Adapters installed: n ");
I = 0;

The following code is used to obtain the network adapter name in different versions:
The NIC names in Win9x and WinNT are implemented using ASCII and UNICODE, respectively,
Therefore, you must first obtain the Local Operating System
Version:
DwVersion = GetVersion ();
DwWindowsMajorVersion = (DWORD) (LOBYTE (LOWORD (dwVersion )));

The Packet. dll function used here is PacketGetAdapterNamesPTSTR pStr,
PULONG BufferSize, usually the first function that communicates with the driver and is called,
It will be installed in the Local System of the returned user
The name of the network adapter is placed in
Buffer pStr; BufferSize is the length of the buffer:
If (! (DwVersion> = 0x80000000 & dwWindowsMajorVersion> = 4 ))
{
// Windows NT
// Unable to find the device list
If (PacketGetAdapterNames (AdapterName, & AdapterLength) = FALSE ){
Printf ("Unable to retrieve the list of the adapters! N ");
Return-1;
}
// Find the device list
Temp = AdapterName;
Temp1 = AdapterName;
While (* temp! = '') | (* (Temp-1 )! = ''))
{
If (* temp = '')
{
Memcpy (AdapterList [I], temp1, (temp-temp1) * 2 );
Temp1 = temp + 1;
I ++;
}
Temp ++;
}
// Display the list of adapters
AdapterNum = I;
For (I = 0; I <AdapterNum; I ++)
Wprintf (L "n % d-% sn", I + 1, AdapterList [I]);
Printf ("n ");
}
Else // otherwise, it is windows 9x. The method for obtaining the adapter name is the same as that in WinNT
{
If (PacketGetAdapterNames (AdapterNamea, & AdapterLength) = FALSE ){
Printf ("Unable to retrieve the list of the adapters! N ");
Return-1;
}
Tempa = AdapterNamea;
Temp1a = AdapterNamea;
While (* tempa! = '') | (* (Tempa-1 )! = ''))
{
If (* tempa = '')
{
Memcpy (AdapterList [I], temp1a, tempa-temp1a );
Temp1a = tempa + 1;
I ++;
}
Tempa ++;
}
AdapterNum = I;
For (I = 0; I <AdapterNum; I ++)
Printf ("n % d-% sn", I + 1, AdapterList [I]);
Printf ("n ");
}

The following code allows the user to select the network adapter Number of the listener:
// Select a device
Do
{
Printf ("Select the number of the adapter to open :");
Scanf ("% d", & Open );
If (Open> AdapterNum)
Printf ("nThe number must be smaller than % d", AdapterNum );
} While (Open> AdapterNum );

Then, open the selected device. Here, you can set it to "hybrid" mode,
It can also be opened in "direct" mode.
The Code is as follows:
// Open the device
LpAdapter = PacketOpenAdapter (AdapterList [Open-1]);
// When the device cannot be opened, the following error message is displayed:
If (! LpAdapter | (lpAdapter-> hFile = INVALID_HANDLE_VALUE ))
{
DwErrorCode = GetLastError ();
Printf ("Unable to open the adapter, Error Code: % lxn", dwErrorCode );
Return-1;
}

Set the NIC to "mixed" mode. The Code is as follows:
The PacketSetHwFilterLPADAPTER AdapterObject and ULONG Filter functions are used here ),
It sets a hardware filter on the incoming package. If the operation is successful, TRUE is returned.
AdapterObject is the network card of the filter.
Device pointer; the constant Filter of the Filter is defined in the header file ntddndis. h, including:
· NDIS-PACKET-TYPE-PROMISCUOUS: sets the hybrid mode. Each incoming package will be accepted by the NIC;
· NDIS-PACKET-TYPE-DIRECTED: only packets DIRECTED to the host NIC are accepted;
· NDIS-PACKET-TYPE-BROADCAST: Only BROADCAST packets are accepted;
· NDIS-PACKET-TYPE-MULTICAST: only receives multicast packets from the group where the host is located;
· NDIS-PACKET-TYPE-ALL-MULTICAS: accept each multicast package.
// Set the network adapter in promiscuous mode
// If the mixed mode fails to be set, an error is prompted:
If (PacketSetHwFilter (lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS) = FALSE ){
Printf ("Warning: unable to set promiscuous mode! N ");
}

Then set the buffer of K in the driver:
The function PacketSetBuffLPADAPTER AdapterObject, int dim) is used here ),
It is used to set the buffer of the driver of the adapter to which the AdapterObject points. If it succeeds, TRUE is returned.
Dim is the size of the new buffer,
When it is set, the data in the old buffer zone will be discarded, and the stored package will also be lost.
Note: whether the size of the drive buffer is set properly affects the performance of the packet capture process,
The setting should ensure fast operation without packet loss. Here we set 512000 bytes.
// Set a 512 K buffer in the driver
// When the buffer cannot be set, an error is prompted:
If (PacketSetBuff (lpAdapter, 512000) = FALSE ){
Printf ("Unable to set the kernel buffer! N ");
Return-1;
}

PacketSetReadTimeoutLPADAPTER AdapterObject, int timeout)
The function is used to set the read operation timeout value bound to the specified network adapter with AdapterObject. The timeout is measured in milliseconds,
0 indicates no timeout,
When no package exists, read will not be returned.
// Set a 1 second read timeout
// Set 1 second read operation timeout
If (PacketSetReadTimeout (lpAdapter, 1000) = FALSE ){
Printf ("Warning: unable to set the read tiemout! N ");
}


Next, locate the device. The Code is as follows:
The PacketAllocatePacketVoid function is used here. a packet structure is allocated in the memory and a pointer to it is returned. However, the Buffer field of this structure is not set yet, therefore, you should call the PacketInitPacket function to initialize it.
// Allocate and initialize a packet structure that will be used
// Receive the packets.
// When positioning fails, an error is prompted:
If (lpPacket = PacketAllocatePacket () = NULL ){
Printf ("nError: failed to allocate the LPPACKET structure .");
Return (-1 );
}

Then, you can initialize the device and start to accept the network package:
Use the PacketInitPacketLPPACKET lpPacket, PVOID Buffer, UINT Length) function to initialize the PACKET structure. LpPacket is the pointer to be initialized. Buffer is the pointer to the Buffer that points to the data that contains the package allocated by the user. Length is the Buffer Length.
Note: The buffer zone associated with the PACKET structure stores packages intercepted by the packet capture driver. The number of packages is limited by the buffer size, the maximum buffer size is the amount of data that the application can read from the drive once. Therefore, setting a large buffer area can reduce the number of system calls and improve the interception efficiency. The value is 256 kb.
PacketInitPacket (lpPacket, (char *) buffer, 256000 );

Next, the main loop of packet capture:
// Main capture loop

The PacketReceivePacketLPADAPTER AdapterObject, LPPACKET lpPacket, BOOLEAN Sync) function is used to intercept a collection of packages. The parameter includes an ADAPTER structure pointer pointing to the NIC used to specify the PACKET capture, a pointer pointing to the PACKET structure used to hold the PACKET, and a flag indicating synchronous or asynchronous operations. During synchronous operations, the function locks the program. When asynchronous operations are performed, the function does not lock the program. You must call the PacketWaitPacket process to check whether the program is completed correctly. Generally, the synchronization mode is used.
// Until you have a keyboard:
While (! Kbhit ())
{
// Capture the packets capture package
// When a packet fails to be captured, an error is prompted:
If (PacketReceivePacket (lpAdapter, lpPacket, TRUE) = FALSE ){
Printf ("Error: PacketReceivePacket failed ");
Return (-1 );
}
// Print the data in the package and call the custom function PrintPackets)
PrintPackets (lpPacket );
}

Finally, print the statistical data. The Code is as follows:
The PacketGetStatsLPADAPTER AdapterObject function, struct bpf_star * s, is used to obtain the internal variable values of the two drivers: the number of packages received by the specified Nic starting from the PacketOpenAdapter call; and the number of packets received by the NIC but discarded by the kernel. These two values are copied to the bpf_stat structure provided by the application by the driver.
// Print the capture statistics
// Obtain the statistical value
// When the status cannot be read from the kernel, an error is prompted:
If (PacketGetStats (lpAdapter, & stat) = FALSE ){
Printf ("Warning: unable to get stats from the kernel! N ");
}
// Print "XX packet capture; XX packet discard ":
Else
Printf ("nn % d packets received. n % d Packets lost", stat. bs_recv, stat. bs_drop );

The PacketFreePacket (LPPACKET lpPacket) function is used to release the structure pointed to by lpPacket:
// Release space
PacketFreePacket (lpPacket );
Use the PacketCloseAdapter (LPADAPTER lpAdapter) function to release the lpAdapter structure of the ADAPTER and disable the NIC pointer:
// Close the adapter and exit
// Disable the device and exit
PacketCloseAdapter (lpAdapter );
Return (0 );
} // The main program ends

The code of the custom function PrintPackets used to print the datagram is not described in detail here.
Conclusion
The compilation of network sniffer aims to make everyone aware of the importance of network management, pay attention to network information security issues, and encrypt and decrypt information.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.