0
点赞
收藏
分享

微信扫一扫

协议分析之TCP旁路阻断


一、阻断未建立起来的连接

      我们知道TCP的建立要经过3次握手,假设客户端C向服务器S请求连接

      1、C发送带有SEQ_C(随机)初始序列号的SYN报文给S

      2、S回复带有SEQ_S(随机)初始序列号和确认序列号ACK_S(必须是SEQ_C+1)的SYN报文给C

      3、C回复确认序列号ACK_C(取值为SEQ_S)给S

      整个过程如果正确的话,连接将会建立。

      通常需要进行阻断的情况是审计控制系统旁路监听内网。旁路监听的方式一般是将主交换机的数据镜像到控制系统,控制系统可以采用

libpcap捕获数据包。

     在这种情况下要阻断tcp连接的建立只要在监听到第一次握手的时候,控制系统伪造服务器发起第二次握手回应,就能阻断客户端与服务器连接的建立。因为我们的系统在内网,发出的报文肯定比服务器快,这样客户端接收到我们伪造的报文以后会回应第三次握手,当服务器真正的报文到达的时候客户端将不再处理,此时客户端再向服务器请求数据,因为seq号和ack号出错,服务器不会受理客户端的请求。

    


1. typedef struct tcp_header {  
2. /* source port */  
3. /* destination port */  
4. /* sequence number */  
5. /* acknowledgement number */  
6. /* data offset, rsvd */  
7. #define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4)  
8.     u_int8_t    th_flags;  
9. #define TH_FIN  0x01  
10. #define TH_SYN  0x02  
11. #define TH_RST  0x04  
12. #define TH_PUSH 0x08  
13. #define TH_ACK  0x10  
14. #define TH_URG  0x20  
15. #define TH_ECNECHO  0x40    /* ECN Echo */  
16. #define TH_CWR      0x80    /* ECN Cwnd Reduced */  
17. /* window */  
18. /* checksum */  
19. /* urgent pointer */  
20. }tcp_header;

 

 

    判断第一次握手的方式flag = tcp_h->th_flags;当flag等于0x02的时候说明客户端发起tcp握手,伪装第二次握手的代码:

  

1. int ForgedSYN(char *srcIP, char *dstIP, int srcPort, int dstPort)  
2. {  
3. char buff[2048] = {0};  
4. char *ptr = buff;  
5. char options[4] = {0x02, 0x04, 0x05, 0x64};  
6.     ip_header iph;  
7.     tcp_header tcph;  
8.     psd_header psdh;  
9. int num = 0;  
10. int isrcip;  
11. int idstip;  
12. short iIPSize = sizeof(ip_header) / sizeof(unsigned long);  
13. short iIPVersion = 4;  
14. short iTotalSize = sizeof(ip_header) + sizeof(tcp_header) + 4;  
15. short iTcpSize = sizeof(tcp_header) + 4;  
16. struct sockaddr_in server;  
17.       
18. if(createSocket()<0) return -1;  
19.       
20.     iph.ip_vhl = (iIPVersion << 4) | iIPSize;  
21.     iph.ip_tos = 0;  
22.     iph.ip_len = htons(iTotalSize);  
23.     iph.ip_id = htons(17393);  
24.     iph.ip_off = 0;  
25.     iph.ip_ttl = 118;  
26.     iph.ip_p = IPPROTO_TCP;  
27.     iph.ip_sum = 0;  
28.     isrcip = inet_addr(srcIP);  
29.     idstip = inet_addr(dstIP);  
30.     memcpy(&iph.ip_src, &isrcip, 4);  
31.     memcpy(&iph.ip_dst, &idstip, 4);  
32. short *)&iph, 20);  
33.   
34.     tcph.th_sport = htons(srcPort);  
35.     tcph.th_dport = htons(dstPort);  
36.     tcph.th_seq = htonl(0x581A784D);  
37.     tcph.th_ack = htonl(g_seq+1);  
38.     tcph.th_offx2 = (24/4<<4|0);  
39.     tcph.th_flags = 0x12;  
40.     tcph.th_win = htons(16384);  
41.     tcph.th_sum = 0;  
42.     tcph.th_urp = 0;  
43.   
44.     psdh.s_addr = isrcip;  
45.     psdh.d_addr = idstip;  
46.     psdh.mbz = 0;  
47.     psdh.protocol = IPPROTO_TCP;  
48.     psdh.tcpl = htons(iTcpSize);  
49.    
50. sizeof(psd_header));  
51. sizeof(psd_header), &tcph, sizeof(tcp_header));  
52. sizeof(psd_header)+sizeof(tcp_header), options, 4);  
53. short *)buff, sizeof(psd_header)+sizeof(tcp_header)+4);  
54.   
55.     memset(buff, 0x00, 2048);  
56.     ptr = buff;  
57. sizeof(ip_header));  
58. sizeof(ip_header);  
59. sizeof(tcp_header));  
60. sizeof(tcp_header);  
61.     memcpy(ptr, options, 4);  
62.   
63.     server.sin_family = AF_INET;  
64.     server.sin_port = htons(dstPort);  
65.     server.sin_addr.s_addr = inet_addr(dstIP);  
66.       
67. struct sockaddr *)&server, sizeof(struct sockaddr));  
68.   
69. return num;  
70. }

 

  数据伪造的时候ip头部和tcp头部要进行校验:

 

  

1. unsigned short checksum(unsigned short *buffer, int size)  
2. {  
3. long cksum=0;  
4.    
5. while (size > 1)  
6.     {  
7.         cksum += *buffer++;  
8. sizeof(unsigned short);    
9.     }  
10. if (size)  
11.     {  
12. char *)buffer;    
13.     }  
14.     cksum = (cksum >> 16) + (cksum & 0xffff);  
15.     cksum += (cksum >>16);  
16.    
17. return (unsigned short)(~cksum);  
18. }

 

 

二、阻断已经建立起来的连接

      对于已经建立起来的连接只要伪造服务器发送rst包迫使客户端重新进行连接,或者fin包直接中断连接。

      正常通行中的tcp报文seq和ack存在如下关系,假设C向S请求数据,seq是seq1,ack是ack1,服务器返回给客户端的seq2和ack2必须存在这种关系:

      seq2 = ack1

      ack2 = seq1+datalen(服务返回报文的长度,不包括ip头和tcp头)

举报

相关推荐

0 条评论