网络嗅探器 sniffer 很多,不过自己做的有很多好处。window2000, XP 支持 raw socket,可以用 raw socket 构造一些特殊用途的工具.
#include
<windows.h>
#include
"winsock2.h"
#include
"IPHeader.h"
class
CRawSocket
{
SOCKET m_InSocket;
SOCKET m_OutSocket;
DWORD m_LocalIPAddress;
WORD m_LocalPort;
DWORD m_RemoteIPAddress;
WORD m_RemotePort;
int m_SendProtocal;
public
:
CRawSocket();
virtual ~CRawSocket();
void FinalIPHeader(char* pIpAndDataBuffer, int length);
void ConstructIPHeader(IPHEADER* pIpHeader, int dataLength);
void FinalTCPHeader(char* pTcpAndDataBuffer, int length);
void ConstructTCPHeader(TCPHEADER* pTcpHeader);
bool SendRawData(char* buffer, int length);
bool Receive(char* buffer, int bufferSize, int& receivedLength);
bool CreateSendSocket(LPCTSTR protocal);
bool CreateReceiveSocket(int port=-1);
DWORD GetLocalIPAddress();
void SetLocalPort(int port);
void SetRemote(DWORD remoteIP, int remotePort);
protected
:
unsigned short CalculateChecksum(char* buffer1, int len1, char* buffer2, int len2);
};
CPP
文件,在
thread
中使用
Receive
函数,可以获取网络中的数据包。
SendRawData
是发送一个自己构造数据包,仅仅是发送,不管
ack
应答,也不管
remote IP and port
。其余几个函数用于构造
Raw TCP/IP data.
#include
"stdafx.h"
#include
"RawSocket.h"
#include
<ws2tcpip.h>
#include
"IPHeader.h"
#define
SIO_RCVALL
_WSAIOW(IOC_VENDOR,1)
#define
RCVALL_OFF 0
#define
RCVALL_ON 1
#define
RCVALL_SOCKETLEVELONLY 2
CRawSocket::CRawSocket()
{
WSADATA wsaData;
char szHostName[128];
m_InSocket = INVALID_SOCKET;
m_OutSocket = INVALID_SOCKET;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
CString s;
s.Format("Error socket()= %ld", ::GetLastError());
::AfxMessageBox(s);
}
::gethostname(szHostName, sizeof(szHostName));
HOSTENT* pHostEnt = ::gethostbyname(szHostName);
if (pHostEnt != NULL)
m_LocalIPAddress = *((DWORD*) pHostEnt->h_addr_list[0]);
else
m_LocalIPAddress = 0;
}
CRawSocket::~CRawSocket()
{
::WSACleanup();
}
void
CRawSocket::SetRemote(DWORD remoteIP, int remotePort)
{
m_RemoteIPAddress = remoteIP;
m_RemotePort = ::htons(remotePort);
}
void
CRawSocket::SetLocalPort(int port)
{
m_LocalPort = ::htons(port);
}
DWORD CRawSocket::GetLocalIPAddress() { return m_LocalIPAddress; }
bool
CRawSocket::CreateReceiveSocket(int port)
{
CString s;
m_InSocket = ::WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (m_InSocket == INVALID_SOCKET) {
s.Format("Error socket()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_InSocket);
return false;
}
int rcvTimeout = 5000;
if (::setsockopt(m_InSocket, SOL_SOCKET, SO_RCVTIMEO,
(const char*) &rcvTimeout, sizeof(rcvTimeout))
== SOCKET_ERROR)
{
s.Format("Error WSA IO Ctrl= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_InSocket);
return false;
}
SOCKADDR_IN sa;
sa.sin_family = AF_INET;
sa.sin_port = port < 0 ? m_LocalPort : (::htons(port));
sa.sin_addr.S_un.S_addr = m_LocalIPAddress;
if (::bind(m_InSocket, (PSOCKADDR) &sa, sizeof(sa)) == SOCKET_ERROR) {
s.Format("Error bind()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_InSocket);
return false;
}
DWORD dwBufferLen[10];
DWORD dwBufferInLen = 1;
DWORD dwBytesReturned = 0;
if (::WSAIoctl( m_InSocket, SIO_RCVALL,
&dwBufferInLen, sizeof(dwBufferInLen),
&dwBufferLen, sizeof(dwBufferLen),
&dwBytesReturned, NULL, NULL)
== SOCKET_ERROR)
{
s.Format("Error WSAIoctl()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_InSocket);
return false;
}
return true;
}
bool
CRawSocket::CreateSendSocket(LPCTSTR protocal)
{
CString s(protocal);
if (s == "TCP")
m_SendProtocal = IPPROTO_TCP;
else if (s == "UDP")
m_SendProtocal = IPPROTO_UDP;
else if (s == "ICMP")
m_SendProtocal = IPPROTO_ICMP;
else
m_SendProtocal = IPPROTO_IP;
m_OutSocket = ::WSASocket(AF_INET, SOCK_RAW, m_SendProtocal, NULL, 0, WSA_FLAG_OVERLAPPED);
if (m_OutSocket == INVALID_SOCKET) {
s.Format("Error socket()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_OutSocket);
return false;
}
BOOL flag = TRUE;
if (::setsockopt(m_OutSocket, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR) {
s.Format("Error setsockopt()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_OutSocket);
return false;
}
int nTimeOver=1000;
if (::setsockopt(m_OutSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR)
{
s.Format("Error setsockopt()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
::closesocket(m_OutSocket);
return false;
}
return true;
}
bool
CRawSocket::Receive(char* buffer, int bufferSize, int& receivedLength)
{
if (m_OutSocket == m_InSocket) return false;
receivedLength = ::recv(m_InSocket, buffer, bufferSize, 0);
return receivedLength != SOCKET_ERROR;
}
bool
CRawSocket::SendRawData(char *buffer, int length)
{
if (m_OutSocket == INVALID_SOCKET) return false;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = m_RemoteIPAddress;
sin.sin_port = m_RemotePort;
if (::sendto(m_OutSocket,
buffer,
length, 0,
(struct sockaddr*) &sin,
sizeof(struct sockaddr_in)
) == SOCKET_ERROR)
{
CString s;
s.Format("Error sendto()= %ld", ::WSAGetLastError());
::AfxMessageBox(s);
return false;
}
return true;
}
unsigned
short CRawSocket::CalculateChecksum(char *buffer1, int len1, char *buffer2, int len2)
{
ASSERT((len1 & 1) == 0);
unsigned long checksum=0;
unsigned short* buffer;
buffer = (unsigned short*) buffer1;
for (int i=0; i<int(len1/sizeof(unsigned short)); i++)
checksum += buffer[i];
buffer = (unsigned short*) buffer2;
for (int i=0; i<int(len2/sizeof(unsigned short)); i++)
checksum += buffer[i];
if ((len2 & 0x1) != 0)
checksum += (unsigned char) buffer2[len2-1];
checksum = (checksum >> 16) + (checksum & 0xffff);
checksum += (checksum >>16);
return (unsigned short)(~checksum);
}
void
CRawSocket::ConstructTCPHeader(TCPHEADER *pTcpHeader)
{
pTcpHeader->destPort = m_RemotePort;
pTcpHeader->sourcePort = m_LocalPort;
pTcpHeader->sequence = ::htons(::rand());
pTcpHeader->acknowledge = 0;
pTcpHeader->lengthres = ((sizeof(TCPHEADER)/4 )<< 4);
pTcpHeader->flags = 2;
pTcpHeader->window_size = ::htons(512);
pTcpHeader->urp = 0;
}
void
CRawSocket::FinalTCPHeader(char *pTcpAndDataBuffer, int length)
{
ASSERT(length >= sizeof(TCPHEADER));
struct PSDHEADER{
unsigned long saddr;
unsigned long daddr;
char mbz;
char ptcl;
unsigned short tcpl;
} psdHeader;
TCPHEADER* pTcpHeader = (TCPHEADER*) pTcpAndDataBuffer;
char* pDataBuffer = pTcpAndDataBuffer + sizeof(TCPHEADER);
int dataLen = length - sizeof(TCPHEADER);
psdHeader.saddr = m_LocalIPAddress;
psdHeader.daddr = m_RemoteIPAddress;
psdHeader.mbz = 0;
psdHeader.ptcl = IPPROTO_TCP;
psdHeader.tcpl = ::htons(length);
pTcpHeader->checksum = CalculateChecksum((char*) &psdHeader, sizeof(psdHeader), pTcpAndDataBuffer, length);
}
void
CRawSocket::ConstructIPHeader(IPHEADER *pIpHeader, int dataLength)
{
pIpHeader->version_length = (4<<4 | sizeof(IPHEADER)/sizeof(unsigned long));
pIpHeader->type_of_service = 0;
pIpHeader->total_length = ::htons(dataLength);
pIpHeader->id = ::htons(::rand());
pIpHeader->offset = 0;
pIpHeader->ttl = 128;
pIpHeader->protocol = m_SendProtocal;
pIpHeader->checksum = 0;
pIpHeader->sourceIP = m_LocalIPAddress;
pIpHeader->destIP = m_RemoteIPAddress;
}
void
CRawSocket::FinalIPHeader(char *pIpAndDataBuffer, int length)
{
ASSERT(length > sizeof(IPHEADER));
IPHEADER* pIpHeader = (IPHEADER*) pIpAndDataBuffer;
char* pDataBuffer = pIpAndDataBuffer + sizeof(IPHEADER);
int dataLen = length - sizeof(IPHEADER);
pIpHeader->checksum = CalculateChecksum(pIpAndDataBuffer, sizeof(IPHEADER), pDataBuffer, dataLen);
pIpHeader->checksum = CalculateChecksum(pIpAndDataBuffer, sizeof(IPHEADER), pDataBuffer, 0);
}