// #include
// #include
#include
#include
#include
#include
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "ws2_32.lib")
#define IPLEN 32 // Ip len
#define MAXLINE 65535 // Max pack
typedef struct ipheadr { /* ip header */
unsigned char vers_l; // version and len
unsigned char s_type; // server type
unsigned short t_len; // total-len
unsigned short sign; // flags
unsigned short mark; // sign and slice offset
unsigned char ttl; // time to live
unsigned char proto; // protocol
unsigned short c_code; // checksum
unsigned int sourceip; // source ip
unsigned int destip; // dest ip
} IpPack;
typedef struct tcpheadr { /* tcp header */
unsigned short s_port; // source port
unsigned short d_port; // dest port
unsigned int seq_n; // seq number
unsigned int ack_n; // ack numbert
unsigned short m_s_offset; // offset, save, mark
unsigned short windows; // window size
unsigned short check_sum; // checksum
unsigned short urg_point; // urg point
} TcpPack;
typedef struct udpheadr { /* udp header */
unsigned short s_port; // source port
unsigned short d_port; // dest port
unsigned short t_len; // total len
unsigned short check_sum; // checksum
} UdpPack;
void decode_ip(char *pdata);
void decode_tcp(char *pdata, char *source, char *dest);
void decode_udp(char *pdata, char *source, char *dest);
void my_vprint(char *source, unsigned short s_port,
char *dest, unsigned short d_port);
int main()
{
WSADATA wsaData;
WORD Version = MAKEWORD(2, 2);
if (WSAStartup(Version, &wsaData) != 0) {
fprintf(stderr, "Can't open socket(v2.2)-Lib.\n");
exit(0);
}
char hostname[32];
struct hostent *pHost;
struct sockaddr_in addr_in;
/* get-hostname */
gethostname(hostname, 32);
if ((pHost = gethostbyname(hostname)) == NULL) {
fprintf(stderr, "Can't get local hostname.\n");
return -1;
}
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(0);
memcpy(&addr_in.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length);
/* socket is set to the original stream */
int fd = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (fd < 0) {
fprintf(stderr, "Can't create socket.\n");
exit(0);
}
if (bind(fd, (struct sockaddr*)&addr_in, sizeof(struct sockaddr)) != 0) {
fprintf(stderr, "Bind %s is error.\n", pHost->h_addr_list[0]);
closesocket(fd);
exit(0);
}
/* set network card is confounding */
DWORD dwValue = 1;
if (ioctlsocket(fd, SIO_RCVALL, &dwValue) != 0) {
fprintf(stderr, "Could not be set to promiscuous mode.\n");
closesocket(fd);
exit(0);
}
printf("\nActive Connections\n\n");
printf("%7s%15s%25s\r\n", "Proto", "Local Address", "Foreign Address");
char srcp[MAXLINE];
int nRet;
while (1) {
if ((nRet = recv(fd, srcp, MAXLINE, 0)) > 0)
decode_ip(srcp);
}
closesocket(fd);
WSACleanup();
return 0;
}
void decode_ip(char *pdata)
{
IpPack *ip = (IpPack*)pdata;
in_addr source_ip, dest_ip;
char sourcename[32], destname[32];
source_ip.S_un.S_addr = ip->sourceip;
dest_ip.S_un.S_addr = ip->destip;
strcpy_s(sourcename, IPLEN, inet_ntoa(source_ip));
strcpy_s(destname, IPLEN, inet_ntoa(dest_ip));
switch (ip->proto)
{
case IPPROTO_TCP:
decode_tcp(pdata + 20, sourcename, destname);
break;
case IPPROTO_UDP:
decode_udp(pdata + 20, sourcename, destname);
break;
}
}
void decode_tcp(char *pdata, char *source, char *dest)
{
TcpPack *tcp = (TcpPack *)pdata;
printf(" TCP ");
my_vprint(source, ntohs(tcp->s_port), dest, ntohs(tcp->d_port));
switch (tcp->d_port) {
case 21:
case 22:
case 23:
case 80:
// save to i/o ...
break;
}
}
void decode_udp(char *pdata, char *source, char *dest)
{
UdpPack *udp = (UdpPack *)pdata;
printf(" UDP ");
my_vprint(source, ntohs(udp->s_port), dest, ntohs(udp->d_port));
switch(udp->d_port) {
case 53:
// save to i/o
}
}
void my_vprint(char *source, unsigned short s_port,
char *dest, unsigned short d_port)
{
char tmp[7];
char buff1[22], buff2[22]; // 255.255.255.255:65535-
/* Formatter */
itoa(s_port, tmp, 10); // number turn into string
strcpy(buff1, "");
strcat(buff1, source);
strcat(buff1, ":");
strcat(buff1, tmp);
itoa(d_port, tmp, 10);
strcpy(buff2, "");
strcat(buff2, dest);
strcat(buff2, ":");
strcat(buff2, tmp);
strcpy(tmp, "");
printf("%-21s %-21s\n", buff1, buff2);
}
其实代码很简单,只不过多用了一个ioctlsocket函数,此函数设置网卡模式,剩下就是简单的拆包工作。大家可以对这个简单的嗅探器进行扩展,这里面只分析了TCP和UDP的包,而且TCP更详细的拆包(应用层)并没有给出,例如http,ssh等。
代码运行环境:vs2017,代码运行效果如下: