网络流量数据包捕获是网络安全领域的重要部分,而pcap文件则是这一过程的常见载体。为了深入解析pcap文件中潜在的可疑网络流量,我们需要运用强大的网络安全威胁评估与审计工具。这些工具能够帮助我们捕捉、记录、检测和诊断网络中的数据传输问题,及时发现异常活动,保护我们的网络安全。
在处理pcap文件时,我们主要关注的是那些可能表明潜在威胁的特征。例如,TTL(Time To Live)过期攻击是一种常见的网络攻击方式,除此之外,ARP(Address Resolution Protocol)中毒也是一种常见的网络威胁,TCP重传是一种利用TCP协议缺陷进行的攻击,重叠碎片攻击是一种利用IP分片漏洞进行的攻击,除了以上提到的几种攻击方式外,我们还需要关注多个TTL值的问题等等。
TTL过期攻击
ARP中毒
TCP重传与重叠碎片
多个TTL值的识别与应对
深入剖析pcap中的网络异常:TTL过期攻击、ARP中毒、TCP重传与重叠碎片等(C/C++代码实现)
void my_packet_handler(u_char *args,const struct pcap_pkthdr *header,const u_char *packet);
int help();
void activate_verbose();
void activate_debug();
void activate_linux_cooked();
void analysis(char* file_in, char* file_out);
void print_flag(int flag);
void print_flag_json(FILE *fp, int flag);
void exclude(char* excl);
void save_json(char* filename);
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[D_HOST_MAC_ADDR]; /* destination host address */
u_char ether_shost; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
const struct sniff_ip *ip_layer;
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
typedef uint32_t tcp_seq;
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
u_char th_flags; /* flags */
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
struct Session {
struct MAC_address *last_mac_src, *last_mac_dst;
char ip_src[20], ip_dst[20];
int port_src, port_dst;
long int seq_keepalive;
char hash_src[SHA_DIGEST_LENGTH*2+1];
char hash_dst[SHA_DIGEST_LENGTH*2+1];
struct TCP_Packet *last_p;
struct TCP_Packet *first_p;
struct Session *previous_s;
struct TTL *last_ttl;
};
struct TCP_Packet {
char hash_src[SHA_DIGEST_LENGTH*2+1];
char hash_dst[SHA_DIGEST_LENGTH*2+1];
long int ack, seq;
int number, flags, len, ttl;
bool keepalive, retransmitted;
struct TCP_Packet *next_p;
};
struct MAC_address {
char address[20];
struct MAC_address *previous_mac;
};
struct TTL {
int val;
struct TTL *previous_ttl;
};
...
int nbr_digits(int a) {
/*
* 返回一个相对较小的正整数中的位数
*/
if (a<0) return -1;
if (a<10) return 1;
if (a<100) return 2;
if (a<1000) return 3;
if (a<10000) return 4;
if (a<100000) return 5;
if (a<1000000) return 6;
if (a<10000000) return 7;
if (a<100000000) return 8;
if (a<1000000000) return 9;
if (a<10000000000) return 10;
return -1;
}
void sha(char ip[20], int port, char* hash_string) {
/*
* Returns sha1(<ip>, <port>) in <hash_string>
*/
unsigned char hash[SHA_DIGEST_LENGTH];
char port_str[nbr_digits(port)];
sprintf(port_str, "%d", port);
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, ip, strlen(ip));
SHA1_Update(&ctx, port_str, strlen(port_str));
SHA1_Final(hash, &ctx);
for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
sprintf(&hash_string[i*2], "%02x", (unsigned int)hash[i]);
}
}
void add_packet_to_session(struct Session *s, struct TCP_Packet *new_packet, char mac_src[20], char mac_dst[20]) {
...
if (s->seq_keepalive==0) {
struct TCP_Packet* previous = s->last_p;
while (previous != NULL && strcmp(new_packet->hash_src, previous->hash_src) != 0) {
previous = previous->next_p;
}
if (previous != NULL) {
if (previous->seq-1 == new_packet->seq && new_packet->len==0 && new_packet->flags == TH_ACK) {
new_packet->keepalive = true;
s->seq_keepalive = new_packet->seq;
}
}
} else {
if (new_packet->seq == s->seq_keepalive && new_packet->flags == TH_ACK && new_packet->len == 0) {
new_packet->keepalive = true; // KeepAlive
} else if (new_packet->ack == s->seq_keepalive+1 && new_packet->flags == TH_ACK) {
new_packet->keepalive = true; // KeepAlive ACK
}
}
...
while (m_dst!=NULL) {
if (strcmp(m_dst->address, mac_dst)==0) {
found_mac_dst=true;
break;
}
m_dst=m_dst->previous_mac;
}
while (m_src!=NULL) {
if (strcmp(m_src->address, mac_src)==0) {
found_mac_src=true;
break;
}
m_src=m_src->previous_mac;
}
// 检查不同的TTL值
...
// 如果数据包的MAC地址不在会话的MAC地址中,请将其添加到MAC地址列表中
...
// 如果找不到TTL,请将if添加到TTL列表中
if (!found_ttl) {
new_ttl = (struct TTL*)malloc(sizeof(struct TTL)); // allocate TTL struct in heap
new_ttl->previous_ttl = s->last_ttl;
new_ttl->val = new_packet->ttl;
s->last_ttl = new_ttl;
}
}
void exclude(char* excl)
{
...
while (pt != NULL) {
if (strcmp(pt, "ret")==0) {
EXCLUDE_RET=true;
printf(GRN "[INFO]" RESET " Excluding RET ambiguities\n");
} else if (strcmp(pt, "ttl")==0) {
EXCLUDE_TTL=true;
printf(GRN "[INFO]" RESET " Excluding TTL ambiguities\n");
} else if (strcmp(pt, "mac")==0) {
EXCLUDE_MAC=true;
printf(GRN "[INFO]" RESET " Excluding MAC ambiguities\n");
} else {
printf(RED "[ERROR]" RESET " Unexpected 'exclude' value: %s\n", pt);
help();
exit(1);
}
pt = strtok (NULL, ",");
}
}
int main(int argc, char **argv)
{
...
int long_index = 0;
while ((opt = getopt_long(argc, argv,"hvdlxs", long_options, &long_index)) != -1) {
switch (opt) {
case 'h': help();
break;
case 'v': activate_verbose();
break;
case 'd': activate_debug();
break;
case 'l': activate_linux_cooked();
break;
case 'x':
if (optarg==NULL) {
exclude(argv[optind++]);
} else {
exclude(optarg);
}
break;
case 's':
if (optarg==NULL)
{
printf("OPT: %d %s\n", optind, argv[optind]);
if (strlen(argv[optind])>45)
{
printf(YLW "[ERROR]" RESET "Please choose a shorter filename where to save the results..\n");
exit(1);
}
strncpy(file_out, argv[optind], strlen(argv[optind]));
optind++;
}
else
{
printf("OPT: %d %s %ld\n", optind, optarg, strlen(optarg));
if (strlen(optarg)>45)
{
printf(YLW "[ERROR]" RESET "Please choose a shorter filename where to save the results..\n");
exit(1);
}
strncpy(file_out, optarg, strlen(optarg));
}
save_json(file_out);
break;
default: return help();
}
}
...
// 检查参数中的pcap文件
if (arg_nbr==-1) {
printf(RED "[Error]" RESET " Missing capture file\n!");
return help();
}
printf(GRN "[INFO]" RESET " Parsing pcap file...\n");
pcap_t *handle = pcap_open_offline(argv[arg_nbr], errbuf);
if(handle == NULL){
printf(RED "[ERROR]" RESET " %s\n", errbuf);
help();
exit(1);
}
pcap_loop(handle, 0, my_packet_handler, NULL);
analysis(argv[arg_nbr], file_out);
return 0;
}
If you need the complete source code, please add the WeChat number (c17865354792)
编译运行:
ARP中毒在于欺骗主机,让其相信我们是默认网关。受害者定期向默认网关询问其MAC地址(ARP协议)。但攻击者可以向受害者发送数据包,说明默认网关位于另一个MAC地址(例如,攻击的MAC地址)。攻击者只需要“定期”发送这些数据包,这样受害者就可以“丢弃”来自默认网关的真实消息。
TCP重传,在TCP连接中发送的每个数据字节都有一个相关的序列号。这在TCP标头的序列号字段中指示。
当接收套接字检测到传入的数据段时,它会使用TCP标头中的确认号来指示接收。发送数据包后,发送方将启动可变长度的重传定时器。如果在定时器到期之前没有收到确认,则发送方将认为该段已丢失,并将重新发送。
当另一个数据包拥有与当前数据包相同的确认和序列号时,我们可以看到TCP重传。
TTL过期攻击: IP数据包的生存时间(TTL)字段对应于该数据包在被路由器丢弃之前“允许”在网络中传播的时间。它是一个8位值,通常在每跳一次时减少一个。
JSON format:
总结
网络异常是指网络通信过程中出现的不正常的情况,其中包括TTL过期攻击、ARP中毒、TCP重传与重叠碎片、多个TTL值的识别与应对等问题。
综上所述,深入剖析pcap中的网络异常需要结合网络原理、协议知识和数据包解析技术,以及对常见的网络故障排除方法的理解。这样才能有效地分析并解决网络异常问题。
Welcome to follow WeChat official account【程序猿编码】