前言

最近在做一些关于TCP/IP协议相关的网络安全编程实验,还是收获了不少心得,这里给大家分享一下。


0x01 网络套接字编程

网络套接字编程主要是面向应用层做文章,使用封装好的套接字足以完成应用层上的各种功能。这是学习网络编程的必经之路,他也能带领我们快速入门。
就拿一个典型的C/S模式的通讯模型来说,从创建套接字、设置套接字参数、绑定套接字到套接字的监听以及最后数据的传输,其中并不需要太多的TCP/IP协议的相关知识便可以实现。因此如果存在协议上的漏洞,仅仅掌握这些是远远不够的。

0x02 DDos攻击

DDos攻击方式有很多种,比如UDP Flood、SYN Flood以及DNS放大攻击等等。这些攻击方式都是利用了TCP/IP协议的特性进行。
比如UDP Flood攻击,它利用UDP协议的无连接状态,只要向目标机发送UDP数据包,目标主机就会返回数据包,因此可以伪造大量不同源IP地址向目标主机发送恶意数据包,而目标机均会对这些请求做出响应从而引发DDos攻击。
再比如DNS放大攻击,它是利用请求的DNS数据包小于响应的DNS数据包的特点,因此可以利用该特点伪造源地址为受害者的IP,然后不断地向DNS服务器发送请求,从而将响应请求引向目标主机,完成DNS放大攻击。这里以DNS放大攻击为例简单说一下编程与DDos攻击。

0x03 DDos攻击与编程

通过上述攻击原理可以看出,我们必须要学会的一项基本技能就是伪造。我们需要剖开已经封装好的数据包,把它转化为想要的格式,因此这样就确定了编程的思路。

  1. 首先要了解TCP/IP协议的结构体,根据协议中各结构体的字段名称以及大小构造需要的数据包结构体,比如DNS报文格式如下:
    1.jpg

关于DNS的头部12个字节,我们就可以这样构造:

typedef struct{
unsigned short id; // 标识
unsigned short flags; // 标志位
unsigned short qcount; // 问题数目
unsigned short ans; // 回答数目
unsigned short auth; // 授权应答
unsigned short add; // 附加信息
}dns_header;

其中unsigned short表示声明长度为16位。

  1. 第二步需要做的就是伪造数据,给结构体进行赋值操作。这里一般会给该结构体创建一个空间,然后为该空间中各个变量进行赋值操作。
    比如本例中DNS头结构体的赋值如下:
void MakeDNSHeader(dns_header *header){
header->id = 1;
header->flags = htons(256);
header->qcount = htons(1);
header->ans = 0;
header->auth = 0;
header->add = 0;
}
  1. 第三步就是调用sendto函数直接发送伪造好的结构体,sendto函数是面向的是IP报文,它无需建立连接。之后便是使用一些抓包工具比如wireshark等分析发送的数据包格式是否正确。
  2. 在编程的最后便是加入一些线程,优化一些参数提升攻击效率。

0x04 后记
在DNS数据报文中,DNS数据报的大小最多为512,过长就会发生截断,因此普通的DNS放大攻击最多放大倍数为7倍左右。但是DNS协议中还存在一种EDNS0扩展协议,它允许数据报大小超出512个字节而不会发生截断,所以我们可以利用这个特点来增加DNS放大攻击倍数。通过了解该拓展协议协议EDNS0可以类似修改之前的数据报,比如上述中的header->add的值变为htons(1),同时增加OPT结构体,便可完成扩展攻击。
OPT结构体如下:


// 设置字节对齐
#pragma pack(push, 1)
typedef struct
{
    unsigned char name; // domain name,默认为空
    uint16_t type; // OPT,一般为41
    uint16_t payload_size; // 额外信息长度
    uint8_t rcode; // 返回状态码
    uint8_t version; // EDNS0版本
    uint16_t z; // 一般置为0
    uint16_t data_len; 
}res_record;
#pragma pack(pop)

最终两者的效果图对比如下:
普通DNS
4.PNG

扩展DNS
2.png