利用原始套接字实现一个简单的采集网络数据包

//利用原始套接字实现一个简单的采集网络数据包,并进行反向解析IP,MAC地址#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/if_ether.h>
#include <linux/in.h>

#define BUFFER_MAX 2048

int main(int argc, char **argv)
{
    int rawsock;
    char buffer[BUFFER_MAX];
    char *ethhead;
    char *iphead;
    char *phead;
   
    //创建原始套接字
    if((rawsock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP)))<0){
        printf("error:create raw socket!\n");
        exit(0);
    }
   
    long framecount =0;
   
    while(1){
        int readnum = recvfrom(rawsock,buffer,2048,0,NULL,NULL);
       
        if(readnum<42){
            printf("error:header is incomplete!\n");
            exit(0);
        }
       
        ethhead=(char*)buffer;
        phead=ethhead;
        int ethernetmask=0XFF;
        framecount++;
       
        printf("---------------AnalysisiPacket[%d]---------------\n",framecount);
        printf("MAC:");
        int i=6;
        for(;i<=11;i++)
            printf("%.2X:",phead[i]&ethernetmask);
        printf("------->");
        for(i=0;i<=5;i++)
            printf("%.2X:",phead[i]&ethernetmask);
        printf("\n");
       
        iphead=ethhead+14;
        phead=iphead+12;
       
        printf("IP:");
        for(i=0;i<=3;i++){
            printf("%d",phead[i]&ethernetmask);
            if(i!=3)
                printf(".");
        }
        printf("------->");
        for(i=4;i<=7;i++){
            printf("%d",phead[i]&ethernetmask);
            if(i!=7)
                printf(".");
        }
        printf("\n");
       
        int prototype=(iphead+9)[0];
        phead=iphead+20;
       
        printf("Protocol:");
        switch(prototype){
        case IPPROTO_ICMP:
            printf("ICMP\n");
            break;
        case IPPROTO_IGMP:
            printf("IGMP\n");
            break;
        case IPPROTO_IPIP:
            printf("IP");
            break;
        case IPPROTO_TCP:
            printf("TCP|source port: %u |",(phead[0]<<8)&0XFF00|phead[1]&0XFF);
            printf("destport: %u\n",(phead[2]<<8)&0XFF00|phead[3]&0XFF);
            break;
        case IPPROTO_UDP:
            printf("UDP|source port: %u |",(phead[0]<<8)&0XFF00|phead[1]&0XFF);
            printf("destport: %u\n",(phead[2]<<8)&0XFF00|phead[3]&0XFF);
            break;
        case IPPROTO_RAW:
            printf("RAW\n");
            break;
        default:
            printf("Unkown\n");   
        }
        printf("-----------------end--------------------");
    }
   
    return 0;
}

时间: 2024-10-07 23:35:32

利用原始套接字实现一个简单的采集网络数据包的相关文章

Windows下利用原始套接字实现的一个抓包程序Demo

早就学过了套接字编程,但是原始套接字还没用过.最近听了网络安全老师的课,心血来潮,写了个抓包程序Demo,把代码分享给大家,感兴趣的可以看看.引用一句网络安全老师的话:"你们要本着技术的心态去实践,哎,一部分人,写着写着就成黑客了". #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <WinSock2.h> #include <WS2tcpip.h> #include <s

Linux网络编程——原始套接字实例:简单版网络数据分析器

通过<Linux网络编程--原始套接字编程>得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢? 链路层封包格式 MAC 头部(有线局域网) 注意:CRC.PAD 在组包时可以忽略 链路层数据包的其中一种情况: unsigned char msg[1024] = { //--------------组MAC--------14------ 0xb8, 0x88, 0xe3, 0xe1, 0x10, 0xe6, // dst

原始套接字学习笔记(1)

一般来说,我们会用到如下三种套接字: TCP:SOCK_STREAM套接字 UDP:SOCK_DGRAM套接字 原始套接字:SOCK_RAW套接字 对于TCP和UDP两种套接字,相对来说只要配置好IP地址和端口号就可以了,比较简单,这里我们主要介绍原始套接字的使用. 1.原始套接字简介 原始套接字的强大之处在于,不同与UDP和TCP套接字只能访问传输层和传输层以上的数据包,原始套接字可以访问传输层以下的数据包,实现上至应用层下至链路层的数据操作,尤其适合用来进行抓包等工作. 2.原始套接字的建立

Linux网络编程——原始套接字能干什么?

通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK_DGRAM):一种无连接的 Socket,对应于无连接的 UDP 服务应用. 从用户的角度来看,SOCK_STREAM.SOCK_DGRAM 这两类套接字似乎的确涵盖了 TCP/IP 应用的全部,因为基于 TCP/IP 的应用,从协议栈的层次上讲,在传输层的确只可能建立于 TCP 或 UDP 协议

原始套接字SOCK_RAW

原始套接字SOCK_RAW 实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包都是由系统提供的协议栈实现,用户只需要填充应用层报文即可,由系统完成底层报文头的填充并发送.然而在某些情况下需要执行更底层的操作,比如修改报文头.避开系统协议栈等.这个时候就需要使用其他的方式来实现. 一 原始套接字 原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGR

Linux 网络编程——原始套接字实例:发送 UDP 数据包

以太网报文格式: 详细的说明,请看<MAC 头部报文分析>. IP 报文格式: 详细的说明,请看<IP 数据报格式详解>. UDP 报文格式: 详细的说明,请看<UDP 数据报格式详解>. 校验和函数: /******************************************************* 功能: 校验和函数 参数: buf: 需要校验数据的首地址 nword: 需要校验数据长度的一半 返回值: 校验和 ********************

LINUX 网络编程 原始套接字

一 原始套接字 原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGRAM的套接字,它实现于系统核心.然而,原始套接字能做什么呢?首先来说,普通的套接字无法处理ICMP.IGMP等网络报文,而SOCK_RAW可以:其次,SOCK_RAW也可以处理特殊的IPv4报文:此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头.总体来说,SOCK_RAW可以处理普通的网络报文之外,还可以处理一些特殊协议报文以及操作IP层及其以上的数据. 既然SOCK_R

原始套接字基础(原始套接字系列二)

在进入Raw Socket多种强大的应用之前,我们先讲解怎样建立一个Raw Socket及怎样用建立的Raw Socket发送和接收IP包. 建立Raw Socket 在Windows平台上,为了使用Raw Socket,需先初始化WINSOCK: // 启动 WinsockWSAData wsaData;if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0){ cerr << "Failed to find Winsock 2.1 or

Linux Socket 原始套接字编程

对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发之自己构建协议头.对于原始套接字编程有些细节性的东西还是需要注意的. 1. 原始套接字创建 原始套接字的编程和udp网络编程的流程有点类似,但是原始套接字编程中不需要bind操作,因为在数据接收和发送过程中使用sendto和recvfrom函数实现数据的接收和发送.不过不是说原始套接字不能使用bin