原来的代码耦合性太高了,我重构了一下,模块化了。
扫描部分还待扩充
#ifndef lib_pcap_pcap_h #include "pcap.h" #endif #ifndef HAVE_PARAM_H #include "param.h" #endif #ifndef HAVE_CONFIG_H #define HAVE_CONFIG_H /* IPSIZE IP地址的长度 MACSIZE MAC地址的长度 PORTNUM PORT的个数 */ #define IPSIZE 16 #define MACSIZE 14 #define PORTNUM 65536 const int judge_ip_times = 4; // 设置判为可疑的次数 const int judge_port_times = 100; const char port_scan_log[] = "port_scan_log.txt"; #endif // CONFIG_H
#ifndef HAVE_CONFIG_H #include "config.h" #endif #ifndef HAVE_DNMC_PACKET_DATA_H #define HAVE_DNMC_PACKET_DATA_H typedef struct protocol_type { int dport_hash[PORTNUM]; int dport_last_time[PORTNUM]; // ??预想画出特征曲线 }protocol_type; typedef struct smac_info { char *dmac; struct protocol_type *pprot_type; struct smac_info* next; }smac_info; typedef struct list_head { char *smac; struct smac_info *psmac_info; struct list_head *next; }list_head; typedef struct rule_list_node { char *name; int mode; int rval; // 0表示不检测,1表示检测 struct rule_list_node* next; struct list_head* rule_list; }rule_list_node; #endif // DNMC_PACKET_DATA_H
#ifndef lib_pcap_pcap_h #include "pcap.h" #endif #ifdef WINDOWS #define unsigned (unsigned int) #endif #ifdef LINUX #define unsigned (unsigned long) #endif char *packet_filter; // 需要从文件中读取过滤数据参数 struct pcap_pkthdr **pool_header; // 数据包池 u_char **pool_pkt_data; u_int pool_in_index; u_int pool_out_index;
#ifndef HAVE_CONFIG_H #include "config.h" #define HAVE_CONFIG_H #endif #ifndef HAVE_PACKET_H #define HAVE_PACKET_H // 以太网协议格式的定义 typedef struct ether_header { u_char dhost[6]; // 目标地址 u_char shost[6]; // 源地址 u_short type; // 以太网类型 }ether_header; // 用户保存4字节的IP地址 typedef struct ip_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; }ip_address; // 用于保存IPV4的首部 typedef struct ip_header { #ifdef WORDS_BIGENDIAN u_char ip_version : 4, header_length : 4; #else u_char header_length : 4, ip_version : 4; #endif u_char ver_ihl; // 版本以及首部长度,各4位 u_char tos; // 服务质量 u_short tlen; // 总长度 u_short identification; // 身份识别 u_short offset; // 分组偏移 u_char ttl; // 生命周期 u_char protocol; // 协议类型 u_short checksum; // 包头测验码 ip_address saddr; // 源IP地址 ip_address daddr; // 目的IP地址 u_int op_pad; //可选 填充字段 }ip_header; // 保存TCP首部 typedef struct tcp_header { u_short sport; u_short dport; u_int sequence; // 序列码 u_int ack; // 回复码 #ifdef WORDS_BIGENDIAN u_char offset : 4, reserved : 4; // 偏移 预留 #else u_char reserved : 4, offset : 4; // 预留 偏移 #endif u_char flags; // 标志 u_short windows; // 窗口大小 u_short checksum; // 校验和 u_short urgent_pointer; // 紧急指针 }tcp_header; // 保存ICMP数据包 typedef struct icmp_header { u_char type; u_char code; u_short checksum; u_short id; u_short sequence; }icmp_header; #endif // PACKET_H
#ifndef lib_pcap_pcap_h #include "pcap.h" #endif #ifndef HAVE_PARAM_H #define HAVE_PARAM_H extern char *packet_filter; // 需要从文件中读取过滤数据参数 extern struct pcap_pkthdr **pool_header; // 数据包池 extern u_char **pool_pkt_data; extern u_int pool_in_index; extern u_int pool_out_index; #endif // PARAM_H
#ifndef HAVE_CONFIG_H #include "config.h" #endif extern void tcp_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ); extern void udp_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ); extern void icmp_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ); extern void ip_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ); extern void ethernet_protocol_packet_handle ( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content );
#ifndef HAVE_CONFIG_H #include "config.h" #endif #ifndef HAVE_PARAM_H #include "param.h" #endif unsigned _stdcall port_scanThreadFunc(void* pArguments);
#include <iostream>
#include <process.h>
#include "main.h"
#include "port_scan.h"
#include "protocol_packet_handle.h"
#include "dnmc_packet_data.h"
#include "packet.h"
#include "config.h"
#define HAVE_REMOTE
#include "remote-ext.h"
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "wpcap.lib")
int sys_init(pcap_t **adhandle) {
pcap_if_t *alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE];
int inum;
int i = 0;
u_int netmask;
char packet_filter[] = "ip and tcp";
struct bpf_program fcode;
pool_in_index = 0;
pool_out_index = 0;
// 获得设备列表 pcap_findalldevs_ex()
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
for(d = alldevs; d; d = d->next) {
printf("%d. %s", ++i, d->name);
if(d->description) {
printf("(%s)\n", d->description);
}
else {
printf("No description available\n");
}
}
if(0 == i) {
printf("\nNo interface found!Make sure WinPcap is installed\n");
return -1;
}
printf("Enter the interface number(1-%d):", i);
scanf_s("%d", &inum);
if(inum < 1 || inum > i) {
printf("\nInterface number out of range.\n");
pcap_freealldevs(alldevs);
return -1;
}
for(d = alldevs, i = 0; i < inum-1; d=d->next, i++);
// 跳转到该设备,打开适配器
// 设备名,要捕捉的数据包的部分(65536保证能捕获到不同数据链路层上的每个数据包的全部内容),混杂模式,读取超时时间,错误缓冲池
if((*adhandle = pcap_open_live(d->name, 65536, 1, 1000, errbuf)) == NULL) {
fprintf(stderr, "\nUnable to open the adapter.%s is not supported by WinPcap\n", errbuf);
pcap_freealldevs(alldevs);
return -1;
}
// 检查数据链路层(只考虑了以太网)
if(pcap_datalink(*adhandle) != DLT_EN10MB) {
fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
pcap_freealldevs(alldevs);
return -1;
}
if(d->addresses != NULL) {
// 获得接口的第一个地址的掩码
netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
}
else {
netmask = 0xffffff;
}
// 编译过滤器
if(pcap_compile(*adhandle, &fcode, packet_filter, 1, netmask) < 0) {
fprintf(stderr, "\nUnable to compile the packet filter.Check the syntax\n");
pcap_freealldevs(alldevs);
return -1;
}
// 设置过滤器
if(pcap_setfilter(*adhandle, &fcode) < 0) {
fprintf(stderr, "\nError setting the filter.\n");
pcap_freealldevs(alldevs);
return -1;
}
printf("\nlistenting on %s...\n", d->description);
pcap_freealldevs(alldevs);
return 0;
}
int sys_start(pcap_t *adhandle) {
struct pcap_pkthdr *header;
const u_char *pkt_data;
int res;
struct tm *ltime;
time_t local_tv_sec;
char timestr[16];
ip_header *ih;
while((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0) {
// 请求超时
if(0 == res) {
continue;
}
pool_header[pool_in_index] = header;
pool_pkt_data[pool_in_index] = const_cast<u_char*>(pkt_data);
pool_in_index++;
// 分析数据包
ethernet_protocol_packet_handle(NULL, header, pkt_data); 改为Thread
/*
// 将时间戳转换成可识别的格式
local_tv_sec = header->ts.tv_sec;
ltime = localtime(&local_tv_sec);
strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
ih = (ip_header *)(pkt_data + 14); //以太网头部长度
// 输出时间和IP信息
printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len);
printf("%d.%d.%d.%d -> %d.%d.%d.%d\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
*/
}
if(-1 == res) {
printf("Error reading the packet:%s\n", pcap_geterr(adhandle));
return -1;
}
return 0;
}
int main(int argc, char *argv[]) {
pcap_t *adhandle;
HANDLE hThread_portscan;
unsigned ps_threadID;
sys_init(&adhandle); // 系统初始化
sys_start(adhandle); // 启动抓包
hThread_portscan = (HANDLE)_beginthreadex(NULL, 0, &port_scanThreadFunc, NULL, 0, &ps_threadID); //端口扫描线程
return 0;
}
#ifndef HAVE_CONFIG_H #include "config.h" #endif #ifndef HAVE_PACKET_H #include "packet.h" #endif void tcp_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ) { struct tcp_header *tcp_protocol; u_short sport; u_short dport; int header_length; u_short windows; u_short urgent_pointer; u_int sequence; u_int acknowledgement; u_short checksum; u_char flags; printf("===========TCP Protocol===========\n"); tcp_protocol = (struct tcp_header*)(packet_content + 14 + 20); sport = ntohs(tcp_protocol->sport); dport = ntohs(tcp_protocol->dport); header_length = tcp_protocol->offset * 4; sequence = ntohl(tcp_protocol->sequence); acknowledgement = ntohl(tcp_protocol->ack); windows = ntohs(tcp_protocol->windows); urgent_pointer = ntohs(tcp_protocol->urgent_pointer); flags = tcp_protocol->flags; checksum = ntohs(tcp_protocol->checksum); if(flags & 0x08) printf("PSH"); if(flags & 0x10) printf("ACK"); if(flags & 0x02) printf("SYN"); if(flags & 0x20) printf("URG"); if(flags & 0x01) printf("FIN"); if(flags & 0x04) printf("RST"); printf("\n"); } void udp_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ) { } void icmp_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ) { struct icmp_header *icmp_protocol; icmp_protocol = (struct icmp_header*)(packet_content + 14 + 20); printf("===========ICMP Protocol==========\n"); printf("ICMP Type: %d\n", icmp_protocol->type); switch(icmp_protocol->type) { case 8: // 回显请求报文 break; case 0: // 回显应答报文 break; default: break; } } void ip_protocol_packet_handle( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ) { struct ip_header *ip_protocol; u_int header_length; u_int offset; u_char tos; u_short checksum; printf("===========IP Protocol===========\n"); ip_protocol = (struct ip_header*)(packet_content + 14); header_length = ip_protocol->header_length * 4; checksum = ntohs(ip_protocol->checksum); tos = ip_protocol->tos; offset = ntohs(ip_protocol->offset); switch(ip_protocol->protocol) { case 6: tcp_protocol_packet_handle(argument, packet_header, packet_content); break; case 17: udp_protocol_packet_handle(argument, packet_header, packet_content); break; case 1: icmp_protocol_packet_handle(argument, packet_header, packet_content); break; default: break; } } void ethernet_protocol_packet_handle ( u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content ) { u_short ethernet_type; // 以太网类型 struct ether_header *ethernet_protocol; // 以太网协议变量 u_char *mac_string; // 以太网地址 ethernet_protocol = (struct ether_header*)packet_content; // 获取以太网数据内容 printf("Ethernet type is : \n"); ethernet_type = ntohs(ethernet_protocol->type); // 获取以太网类型 printf(" %04x\n", ethernet_type); switch(ethernet_type) { case 0x0800: printf("The network layer is IP protocol\n"); break; case 0x0806: printf("The network layer is ARP protocol\n"); break; default: break; } // 获取以太网源地址 printf("MAC Source Address is : \n"); mac_string = ethernet_protocol->shost; printf (" %02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5) ); // 获取以太网目的地址 printf("MAC Target Address is : \n"); mac_string = ethernet_protocol->dhost; printf (" %02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5) ); switch(ethernet_type) { case 0x0800: ip_protocol_packet_handle(argument, packet_header, packet_content); break; default: break; } }
#ifndef HAVE_CONFIG_H #include "config.h" #endif #ifndef HAVE_PACKET_H #include "packet.h" #endif unsigned _stdcall port_scanThreadFunc(void* pArguments) { return 0; }