偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Linux網(wǎng)絡(luò)編程:原始套接字編程及實例分析

網(wǎng)絡(luò) 通信技術(shù)
原始套接字編程和之前的UDP 編程差不多,無非就是創(chuàng)建一個套接字后,通過這個套接字接收數(shù)據(jù)或者發(fā)送數(shù)據(jù)。區(qū)別在于,原始套接字可以自行組裝數(shù)據(jù)包(偽裝本地 IP,本地 MAC),可以接收本機網(wǎng)卡上所有的數(shù)據(jù)幀(數(shù)據(jù)包)。另外,必須在管理員權(quán)限下才能使用原始套接字。

一、原始套接字能干什么?

通常情況下程序員接所接觸到的套接字(Socket)為兩類:

(1)流式套接字(SOCK_STREAM):一種面向連接的Socket,針對于面向連接的TCP 服務(wù)應(yīng)用;

(2)數(shù)據(jù)報式套接字(SOCK_DGRAM):一種無連接的Socket,對應(yīng)于無連接的UDP 服務(wù)應(yīng)用。

從用戶的角度來看,SOCK_STREAM、SOCK_DGRAM 這兩類套接字似乎的確涵蓋了TCP/IP 應(yīng)用的全部,因為基于TCP/IP 的應(yīng)用,從協(xié)議棧的層次上講,在傳輸層的確只可能建立于TCP 或 UDP協(xié)議之上,而SOCK_STREAM、SOCK_DGRAM 又分別對應(yīng)于TCP和UDP,所以幾乎所有的應(yīng)用都可以用這兩類套接字實現(xiàn)。 

[[130856]] 

但是,當(dāng)我們面對如下問題時,SOCK_STREAM、SOCK_DGRAM 將顯得這樣無助:

(1)怎樣發(fā)送一個自定義的IP 包?

(2)怎樣發(fā)送一個ICMP 協(xié)議包?

(3)怎樣分析所有經(jīng)過網(wǎng)絡(luò)的包,而不管這樣包是否是發(fā)給自己的?

(4)怎樣偽裝本地的IP 地址?

這使得我們必須面對另外一個深刻的主題——原始套接字(SOCK_RAW)。原始套接字廣泛應(yīng)用于高級網(wǎng)絡(luò)編程,也是一種廣泛的黑客手段。著名的網(wǎng)絡(luò)sniffer(一種基于被動偵聽原理的網(wǎng)絡(luò)分析方式)、拒絕服務(wù)攻擊(DOS)、IP 欺騙等都可以通過原始套接字實現(xiàn)。

原始套接字(SOCK_RAW)可以用來自行組裝數(shù)據(jù)包,可以接收本機網(wǎng)卡上所有的數(shù)據(jù)幀(數(shù)據(jù)包),對于監(jiān)聽網(wǎng)絡(luò)流量和分析網(wǎng)絡(luò)數(shù)據(jù)很有作用。

原始套接字是基于IP 數(shù)據(jù)包的編程(SOCK_PACKET 是基于數(shù)據(jù)鏈路層的編程)。另外,必須在管理員權(quán)限下才能使用原始套接字。

原始套接字(SOCK_RAW)與標(biāo)準(zhǔn)套接字(SOCK_STREAM、SOCK_DGRAM)的區(qū)別在于原始套接字直接置“根”于操作系統(tǒng)網(wǎng)絡(luò)核心(Network Core),而 SOCK_STREAM、SOCK_DGRAM 則“懸浮”于 TCP 和 UDP 協(xié)議的外圍。 

[[130857]] 

流式套接字只能收發(fā) TCP 協(xié)議的數(shù)據(jù),數(shù)據(jù)報套接字只能收發(fā) UDP 協(xié)議的數(shù)據(jù),原始套接字可以收發(fā)內(nèi)核沒有處理的數(shù)據(jù)包。

#p#

二、原始套接字編程

原始套接字編程和之前的UDP 編程差不多,無非就是創(chuàng)建一個套接字后,通過這個套接字接收數(shù)據(jù)或者發(fā)送數(shù)據(jù)。區(qū)別在于,原始套接字可以自行組裝數(shù)據(jù)包(偽裝本地 IP,本地 MAC),可以接收本機網(wǎng)卡上所有的數(shù)據(jù)幀(數(shù)據(jù)包)。另外,必須在管理員權(quán)限下才能使用原始套接字。

原始套接字的創(chuàng)建:

int socket ( int family, int type, int protocol );

參數(shù):

family:協(xié)議族 這里寫 PF_PACKET

type: 套接字類,這里寫 SOCK_RAW

protocol:協(xié)議類別,指定可以接收或發(fā)送的數(shù)據(jù)包類型,不能寫 “0”,取值如下,注意,傳參時需要用 htons() 進(jìn)行字節(jié)序轉(zhuǎn)換。

ETH_P_IP:IPV4數(shù)據(jù)包

ETH_P_ARP:ARP數(shù)據(jù)包

ETH_P_ALL:任何協(xié)議類型的數(shù)據(jù)包

返回值:

成功( >0 ):套接字,這里為鏈路層的套接字

失敗( <0 ):出錯

實例如下:

  1. // 所需頭文件    
  2. #include <sys/socket.h>    
  3. #include <netinet/ether.h>    
  4. #include <stdio.h>  // perror    
  5.     
  6. int main(int argc,charchar *argv[])    
  7. {    
  8.     int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );    
  9.     
  10.     if(sock_raw_fd < 0){    
  11.         perror("socket");    
  12.         return -1;    
  13.     }    
  14.         
  15.     return 0;    
  16. }   

獲取鏈路層的數(shù)據(jù)包:

ssize_t recvfrom( int sockfd,

void *buf,

size_t nbytes,

int flags,

struct sockaddr *from,

socklen_t *addrlen );

參數(shù):

sockfd: 原始套接字

buf: 接收數(shù)據(jù)緩沖區(qū)

nbytes: 接收數(shù)據(jù)緩沖區(qū)的大小

flags: 套接字標(biāo)志(常為0)

from: 這里沒有用,寫 NULL

addrlen:這里沒有用,寫 NULL

返回值:

成功:接收到的字符數(shù)

失?。?1

實例如下:

  1. #include <stdio.h>    
  2. #include <netinet/in.h>    
  3. #include <sys/socket.h>    
  4. #include <netinet/ether.h>    
  5.     
  6. int main(int argc,charchar *argv[])    
  7. {    
  8.     unsigned char buf[1024] = {0};    
  9.     int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));    
  10.     
  11.     //獲取鏈路層的數(shù)據(jù)包    
  12.     int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);    
  13.     printf("len = %d\n", len);    
  14.     
  15.     return 0;    
  16. }   

混雜模式

默認(rèn)的情況下,我們接收數(shù)據(jù),目的地址是本地地址,才會接收。有時候我們想接收所有經(jīng)過網(wǎng)卡的所有數(shù)據(jù)流,而不論其目的地址是否是它,這時候我們需要設(shè)置網(wǎng)卡為混雜模式。

網(wǎng)卡的混雜模式一般在網(wǎng)絡(luò)管理員分析網(wǎng)絡(luò)數(shù)據(jù)作為網(wǎng)絡(luò)故障診斷手段時用到,同時這個模式也被網(wǎng)絡(luò)黑客利用來作為網(wǎng)絡(luò)數(shù)據(jù)竊聽的入口。在 Linux 操作系統(tǒng)中設(shè)置網(wǎng)卡混雜模式時需要管理員權(quán)限。在 Windows 操作系統(tǒng)和 Linux 操作系統(tǒng)中都有使用混雜模式的抓包工具,比如著名的開源軟件 Wireshark。

通過命令給 Linux 網(wǎng)卡設(shè)置混雜模式(需要管理員權(quán)限)

設(shè)置混雜模式:ifconfig eth0 promisc 

[[130858]] 

取消混雜模式:ifconfig eth0 -promisc 

[[130859]] 

通過代碼給 Linux 網(wǎng)卡設(shè)置混雜模式 

[[130860]] 

代碼如下:

  1. struct ifreq ethreq;    //網(wǎng)絡(luò)接口地址    
  2.         
  3. strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);         //指定網(wǎng)卡名稱    
  4. if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &ethreq)) //獲取網(wǎng)絡(luò)接口    
  5. {    
  6.     perror("ioctl");    
  7.     close(sock_raw_fd);    
  8.     exit(-1);    
  9. }    
  10.     
  11. ethreq.ifr_flags |= IFF_PROMISC;    
  12. if(-1 == ioctl(sock_raw_fd, SIOCSIFINDEX, &ethreq)) //網(wǎng)卡設(shè)置混雜模式    
  13. {    
  14.     perror("ioctl");    
  15.     close(sock_raw_fd);    
  16.     exit(-1);    
  17. }   

發(fā)送自定義的數(shù)據(jù)包:

ssize_t sendto( int sockfd,

const void *buf,

size_t nbytes,int flags,

const struct sockaddr *to,

socklen_t addrlen );

參數(shù):

sockfd: 原始套接字

buf: 發(fā)送數(shù)據(jù)緩沖區(qū)

nbytes: 發(fā)送數(shù)據(jù)緩沖區(qū)的大小

flags: 一般為 0

to: 本機網(wǎng)絡(luò)接口,指發(fā)送的數(shù)據(jù)應(yīng)該從本機的哪個網(wǎng)卡出去,而不是以前的目的地址

addrlen:to 所指向內(nèi)容的長度

返回值:

成功:發(fā)送數(shù)據(jù)的字符數(shù)

失?。?-1

本機網(wǎng)絡(luò)接口的定義 

[[130861]] 

發(fā)送完整代碼如下:

  1. struct sockaddr_ll sll;                 //原始套接字地址結(jié)構(gòu)    
  2. struct ifreq ethreq;                    //網(wǎng)絡(luò)接口地址    
  3.     
  4. strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);         //指定網(wǎng)卡名稱    
  5. if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, ðreq))    //獲取網(wǎng)絡(luò)接口    
  6. {    
  7.     perror("ioctl");    
  8.     close(sock_raw_fd);    
  9.     exit(-1);    
  10. }    
  11.     
  12. /*將網(wǎng)絡(luò)接口賦值給原始套接字地址結(jié)構(gòu)*/    
  13. bzero(&sll, sizeof(sll));    
  14. sll.sll_ifindex = ethreq.ifr_ifindex;    
  15.     
  16. // 發(fā)送數(shù)據(jù)    
  17. // send_msg, msg_len 這里還沒有定義,模擬一下    
  18. int len = sendto(sock_raw_fd, send_msg, msg_len, 0 , (struct sockaddr *)&sll, sizeof(sll));    
  19. if(len == -1)    
  20. {    
  21.     perror("sendto");    
  22. }   

這里頭文件情況如下:

  1. #include <net/if.h>// struct ifreq    
  2. #include <sys/ioctl.h> // ioctl、SIOCGIFADDR    
  3. #include <sys/socket.h> // socket    
  4. #include <netinet/ether.h> // ETH_P_ALL    
  5. #include <netpacket/packet.h> // struct sockaddr_ll 

#p#

三、原始套接字實例:MAC頭部報文分析

由上得知,我們可以通過原始套接字以及 recvfrom( ) 可以獲取鏈路層的數(shù)據(jù)包,那我們接收的鏈路層數(shù)據(jù)包到底長什么樣的呢?

鏈路層封包格式 

[[130862]] 

MAC 頭部(有線局域網(wǎng)) 

[[130863]] 

注意:CRC、PAD 在組包時可以忽略

鏈路層數(shù)據(jù)包的其中一種情況:

  1. unsigned char msg[1024] = {    
  2.     //--------------組MAC--------14------    
  3.     0xb8, 0x88, 0xe3, 0xe1, 0x10, 0xe6, // dst_mac: b8:88:e3:e1:10:e6    
  4.     0xc8, 0x9c, 0xdc, 0xb7, 0x0f, 0x19, // src_mac: c8:9c:dc:b7:0f:19    
  5.     0x08, 0x00,                         // 類型:0x0800 IP協(xié)議    
  6.     // …… ……    
  7.     // …… ……    
  8. };   

接收的鏈路層數(shù)據(jù)包,并對其進(jìn)行簡單分析:

  1. #include <stdio.h>    
  2. #include <string.h>    
  3. #include <stdlib.h>    
  4. #include <sys/socket.h>    
  5. #include <netinet/in.h>    
  6. #include <arpa/inet.h>    
  7. #include <netinet/ether.h>    
  8.     
  9. int main(int argc,charchar *argv[])    
  10. {    
  11.     int i = 0;    
  12.     unsigned char buf[1024] = "";    
  13.     int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));    
  14.     while(1)    
  15.     {    
  16.         unsigned char src_mac[18] = "";    
  17.         unsigned char dst_mac[18] = "";    
  18.         //獲取鏈路層的數(shù)據(jù)幀    
  19.         recvfrom(sock_raw_fd, buf, sizeof(buf),0,NULL,NULL);    
  20.         //從buf里提取目的mac、源mac    
  21.         sprintf(dst_mac,"%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);    
  22.         sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);    
  23.         //判斷是否為IP數(shù)據(jù)包    
  24.         if(buf[12]==0x08 && buf[13]==0x00)    
  25.         {       
  26.             printf("______________IP數(shù)據(jù)報_______________\n");    
  27.             printf("MAC:%s >> %s\n",src_mac,dst_mac);    
  28.         }//判斷是否為ARP數(shù)據(jù)包    
  29.         else if(buf[12]==0x08 && buf[13]==0x06)    
  30.         {    
  31.             printf("______________ARP數(shù)據(jù)報_______________\n");    
  32.             printf("MAC:%s >> %s\n",src_mac,dst_mac);    
  33.         }//判斷是否為RARP數(shù)據(jù)包    
  34.         else if(buf[12]==0x80 && buf[13]==0x35)    
  35.         {    
  36.             printf("______________RARP數(shù)據(jù)報_______________\n");    
  37.             printf("MAC:%s>>%s\n",src_mac,dst_mac);    
  38.         }    
  39.     }    
  40.     return 0;    
  41. }   

記得以管理者權(quán)限運行程序:

 

[[130864]]
責(zé)任編輯:藍(lán)雨淚 來源: CSDN博客
相關(guān)推薦

2021-02-05 15:20:06

網(wǎng)絡(luò)安全套接字命令

2014-12-15 09:28:54

UDP

2015-05-28 10:47:38

Unix網(wǎng)絡(luò)編程TCP

2014-12-11 09:20:30

TCP

2012-01-06 13:58:47

JavaTCP

2009-03-10 13:59:41

C#套接字編程

2020-10-15 19:10:05

LinuxAPI函數(shù)

2015-10-16 09:33:26

TCPIP網(wǎng)絡(luò)協(xié)議

2021-03-14 18:22:23

套接字網(wǎng)絡(luò)通信

2014-12-17 09:22:10

網(wǎng)絡(luò)·安全技術(shù)周刊

2013-12-27 13:39:23

Java套接字

2009-06-30 16:51:56

2021-04-30 18:50:44

網(wǎng)絡(luò)安全PE編程添加節(jié)區(qū)

2021-04-26 10:32:38

網(wǎng)絡(luò)安全PE編程工具

2024-08-13 08:27:24

PythonTCP協(xié)議網(wǎng)絡(luò)編程

2021-04-25 21:25:09

網(wǎng)絡(luò)安全網(wǎng)絡(luò)安全編程PE編程

2021-04-28 14:35:48

網(wǎng)絡(luò)安全PE編程代碼

2009-12-18 09:54:10

Linux Shell

2009-07-06 18:24:56

Servlet實例

2021-01-18 10:35:18

網(wǎng)絡(luò)安全Windows代碼
點贊
收藏

51CTO技術(shù)棧公眾號