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

📄 sp_respond2.c

📁 著名的入侵检测系统snort的最新版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        else if (!strcasecmp(toks[i], "icmp_all"))        {            response_flag |= (RESP_BAD_NET | RESP_BAD_HOST | RESP_BAD_PORT);            if (!make_icmp)                make_icmp = 1;            i++;        }        else            FatalError("%s: %s(%d): invalid response modifier: %s\n",                     MODNAME, file_name, file_line, toks[i]);    }    if (make_tcp)        PrecacheTCP();    if (make_icmp)        PrecacheICMP();    mSplitFree(&toks, num_toks);    return response_flag;}/* ######## CORE respond2 section ######## *//** * Respond to hostile connection attempts * * @param p pointer to a Snort packet structure * @param fp_list pointer to a response list node * * @return void function */static int Respond2(Packet *p, RspFpList *fp_list){    RespondData *rd = (RespondData *)fp_list->params;    if (p->iph == NULL)        return 0;    /* check the dampen cache before responding */    if ((dampen_response(p)) == 1)        return 0;    if (rd->response_flag)    {        /* if reset_both was used, receiver is reset first */        if ((rd->response_flag & (RESP_RST_RCV | RESP_RST_SND)) &&                 IsRSTCandidate(p))        {            SendReset(RESP_RST_RCV, p, &config);            SendReset(RESP_RST_SND, p, &config);        }        if ((rd->response_flag & RESP_RST_RCV) && IsRSTCandidate(p))            SendReset(RESP_RST_RCV, p, &config);        if ((rd->response_flag & RESP_RST_SND) && IsRSTCandidate(p))            SendReset(RESP_RST_SND, p, &config);        if (rd->response_flag & RESP_BAD_NET && IsUNRCandidate(p))            SendUnreach(ICMP_UNREACH_NET, p, &config);        if (rd->response_flag & RESP_BAD_HOST && IsUNRCandidate(p))            SendUnreach(ICMP_UNREACH_HOST, p, &config);        if (rd->response_flag & RESP_BAD_PORT && IsUNRCandidate(p))            SendUnreach(ICMP_UNREACH_PORT, p, &config);    }    return 1;   /* injection functions do not return an error */}/** * TCP reset response function * * @param flag flag describing whom to respond to (sender/receiver) * @param p Pointer to a Snort packet structure * @param data pointer to a RESPOND2_CONFIG data structure * * @return void function */static void SendReset(const int mode, Packet *p, RESPOND2_CONFIG *conf){    size_t sz = IP_HDR_LEN + TCP_HDR_LEN;    ssize_t n;    int reversed;    u_int32_t i, ack, seq;    u_int16_t window, dsize;    EtherHdr *eh;    IPHdr *iph;    TCPHdr *tcp;#if defined(DEBUG)    char *source, *dest;#endif    if(IS_IP6(p)) return;    if (mode == RESP_RST_SND)        reversed = 1;    else        reversed = 0;    iph = (IPHdr *)(tcp_pkt + link_offset);    tcp = (TCPHdr *)(tcp_pkt + IP_HDR_LEN + link_offset);    if (link_offset)    {        if (!IsLinkCandidate(p))        {            ErrorMessage("%s: link-layer response only works on Ethernet!\n"                    "Remove \"config flexresp2_interface\" from snort.conf.\n",                    MODNAME);            return;        }        else        {            DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: setting up link-layer "                    "header on TCP packet: %p.\n.", MODNAME, p););            /* setup the Ethernet header */            eh = (EtherHdr *)tcp_pkt;            if (reversed)            {                memcpy(eh->ether_src, p->eh->ether_dst, 6);                memcpy(eh->ether_dst, p->eh->ether_src, 6);            }            else            {                memcpy(eh->ether_src, p->eh->ether_src, 6);                memcpy(eh->ether_dst, p->eh->ether_dst, 6);            }        }    }    /* save p->dsize */    dsize = p->dsize;    /* Reverse the source and destination IP addr for attack-response rules */    if (reversed)    {        iph->ip_src.s_addr = GET_SRC_IP(p);        iph->ip_dst.s_addr = GET_DST_IP(p);        tcp->th_sport = p->tcph->th_dport;        tcp->th_dport = p->tcph->th_sport;        seq = ntohl(p->tcph->th_ack);        ack = ntohl(p->tcph->th_seq) + p->dsize;    }    else    {        iph->ip_src.s_addr = GET_SRC_IP(p);        iph->ip_dst.s_addr = GET_DST_IP(p);        tcp->th_sport = p->tcph->th_sport;        tcp->th_dport = p->tcph->th_dport;        seq = ntohl(p->tcph->th_seq);        ack = ntohl(p->tcph->th_ack) + p->dsize;    }    iph->ip_ttl = CalcOriginalTTL(p);    tcp->th_win = 0;    /* save the window size for all calculations */    window = ntohs(p->tcph->th_win);    for (i = 0; i < conf->respond_attempts; i++)    {        if (link_offset)            iph->ip_id = RandID(&config);        /* As Dug Song pointed out, if you can't determine the rate of          * SEQ and ACK number consumption, do the next best thing and try to         * "land" a reset within the acceptable window of sequence numbers.         *         * sp_respond2 uses data sent in the offending packet and the window         * size of the offending packet to 'predict' an acceptable SEQ and          * ACK number.           *         * A minimum of four responses are sent per trigger using the          * following algorithm:         *         * (the numbers represent iterations through a loop starting at 0)         *         * 0:         *   SEQ = seq         *   ACK = ack + data         *         * 1:         *   SEQ += data         *         * 2:         *   SEQ += (data * 2)         *   ACK += (data * 2)         *         * 3:         *   SEQ += (data * 2)         *   ACK += (data * 2)         *         * 4:         *   SEQ += (data * 4)         *   ACK += (data * 4)         *         * n:         *         *   SEQ += (window / 2)         *   ACK += (window / 2)         *            *         * I refer to the above as "sequence strafing", whereby sp_respond2          * iteratively brute forces sequence and ack numbers into an         * acceptable window         */        switch (i)        {            case 0:                break;            case 1:                seq += dsize;                break;            case 2:                seq += (dsize << 1);                ack += (dsize << 1);                break;            case 3:                seq += (dsize << 1);                ack += (dsize << 1);                break;            case 4:                seq += (dsize << 2);                ack += (dsize << 2);                break;            default:                seq += (window >> 1);                ack += (window >> 1);                break;        }        tcp->th_seq = htonl(seq);        tcp->th_ack = htonl(ack);        iph->ip_len = htons(sz);        ip_checksum(tcp_pkt + link_offset, sz);    #if defined(DEBUG)        DEBUG_WRAP(#ifndef SUP_IP6                source = strdup(inet_ntoa(*(struct in_addr *)&iph->ip_src.s_addr));                dest = strdup(inet_ntoa(*(struct in_addr *)&iph->ip_dst.s_addr));#else                source = "";                dest = "";#endif                DebugMessage(DEBUG_PLUGIN, "%s: firing TCP response packet.\n",                        MODNAME);                DebugMessage(DEBUG_PLUGIN, "%s:%u -> %s:%d\n(seq: %#lX "                        "ack: %#lX win: %hu)\n\n", source,                         ntohs(tcp->th_sport), dest, ntohs(tcp->th_dport),                         ntohl(tcp->th_seq), ntohl(tcp->th_ack),                         ntohs(tcp->th_win));                PrintNetData(stdout, (u_char *)tcp_pkt, sz);                //ClearDumpBuf();                free(source);                free(dest);        );#endif /* defined(DEBUG) */        if (link_offset)            n = eth_send(conf->ethdev, tcp_pkt, sz + link_offset);        else            n = ip_send(conf->rawdev, tcp_pkt, sz);        if (n < sz)            ErrorMessage("%s: failed to send TCP reset (%s).\n", MODNAME,                     ((link_offset == 0) ? "raw socket" : "link-layer"));    }    return;}/** * ICMP unreachable response function * * @param code ICMP unreachable type * @param p Pointer to a Snort packet structure * @param data pointer to a RESPOND2_CONFIG data structure * * @return void function */static void SendUnreach(const int code, Packet *p, RESPOND2_CONFIG *conf){    u_int16_t payload_len;    size_t sz;    ssize_t n;    EtherHdr *eh;    IPHdr *iph;    ICMPHdr *icmph;#if defined(DEBUG)    char *source, *dest, *icmp_rtype;#endif    if(IS_IP6(p)) return;    /* only send ICMP port unreachable responses for TCP and UDP */    if (GET_IPH_PROTO(p) == IPPROTO_ICMP && code == ICMP_UNREACH_PORT)    {        ErrorMessage("%s: ignoring icmp_port set on ICMP packet.\n", MODNAME);        return;    }    iph = (IPHdr *)(icmp_pkt + link_offset);    icmph = (ICMPHdr *)(icmp_pkt + IP_HDR_LEN + link_offset);    iph->ip_src.s_addr = GET_DST_IP(p);    iph->ip_dst.s_addr = GET_SRC_IP(p);    iph->ip_ttl = CalcOriginalTTL(p);    icmph->code = code;    if (link_offset)    {        if (!IsLinkCandidate(p))        {            ErrorMessage("%s: link-layer response only works on Ethernet!\n"                    "Remove \"config flexresp2_interface\" from snort.conf.\n",                     MODNAME);            return;        }        else        {            DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "%s: setting up link-layer "                    "header on ICMP packet: %p.\n.", MODNAME, p););            /* setup the Ethernet header */            eh = (EtherHdr *)icmp_pkt;            memcpy(eh->ether_src, p->eh->ether_dst, 6);            memcpy(eh->ether_dst, p->eh->ether_src, 6);            /* With a raw socket, the kernel automatically sets the IP ID when             * it's 0.  With link-layer injection, an IP ID must be specified.             * A randomly generated IP ID is used here to evade fingerprinting.             */            iph->ip_id = RandID(&config);        }    }    if ((payload_len = ntohs(GET_IPH_LEN(p)) - (GET_IPH_HLEN(p) << 2)) > 8)        payload_len = 8;    memcpy((char *)icmph + ICMP_LEN_MIN, p->iph, (IP_HLEN(p->iph) << 2)              + payload_len);    sz = IP_HDR_LEN + ICMP_LEN_MIN + (IP_HLEN(p->iph) << 2) + payload_len;    iph->ip_len = htons(sz);    ip_checksum(icmp_pkt + link_offset, sz);    sz += link_offset;#if defined(DEBUG)    DEBUG_WRAP(#ifdef SUP_IP6            source = strdup(sfip_ntoa(iph->ip_src.s_addr));            dest = strdup(sfip_ntoa(iph->ip_dst.s_addr));#else            source = strdup(inet_ntoa(*(struct in_addr *)&iph->ip_src.s_addr));            dest = strdup(inet_ntoa(*(struct in_addr *)&iph->ip_dst.s_addr));#endif            switch (code)            {                case RESP_BAD_NET:                    icmp_rtype = "ICMP network unreachable";                    break;                case RESP_BAD_HOST:                    icmp_rtype = "ICMP host unreachable";                    break;                case RESP_BAD_PORT: /* FALLTHROUGH */                default:                    icmp_rtype = "ICMP port unreachable";                    break;            }            DebugMessage(DEBUG_PLUGIN, "%s: firing ICMP response packet.\n",                     MODNAME);            DebugMessage(DEBUG_PLUGIN, "%s -> %s (%s)\n\n", source, dest,                 icmp_rtype);            PrintNetData(stdout, (u_char *)icmp_pkt, (const int)sz);            //ClearDumpBuf();            free(source);            free(dest);    );#endif /* defined(DEBUG) */    if (link_offset)        n = eth_send(conf->ethdev, icmp_pkt, sz);    else        n = ip_send(conf->rawdev, icmp_pkt, sz);    if (n < sz)        ErrorMessage("%s: failed to send ICMP unreachable (%s).\n", MODNAME,                ((link_offset == 0) ? "raw socket" : "link-layer"));    return;}/** * Determine whether or not a TCP RST response can be sent * * @param p pointer to a Snort packet structure * * @return 1 on success, 0 on failure */static INLINE int IsRSTCandidate(Packet *p)

⌨️ 快捷键说明

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