美文网首页
端口扫描

端口扫描

作者: 遇银 | 来源:发表于2022-03-10 10:33 被阅读0次
    异常扫描逻辑.png
    #include <stdio.h>
    #include <string.h>
    #include <sys/time.h>
    #include <arpa/inet.h>
    
    #include "hikadef_hash.h"
    #include "hikadef_scan_check.h"
    #include "hikadef_publish.h"
    #include "Hikadef_Log.h"
    
    /*----------------------------------------------------------------------------------*/
    typedef struct scan_info_t
    {
        char scan_ipstr[32];
        unsigned int scan_port;
        unsigned int protocol;
        unsigned int scan_type;
        unsigned char portmap[65535];
        long timestamp;
    } scan_info;
    
    enum SCAN_TYPE
    {
        SCAN_TYPE_NULL   = 0,   
        SCAN_TYPE_SYN    = 1,
        SCAN_TYPE_ACK,
        SCAN_TYPE_FIN,
        SCAN_TYPE_CON,
        SCAN_TYPE_SEND
    };
    
    static char *protocol_str[] = {
        [0] = "TCP",
        [1] = "UDP",
    };
    
    
    /*----------------------------------------------------------------------------------*/
    
    #define HASH_TABLE_SIZE    80         //hash桶大小
    #define SCAN_TIME_LIMIT    5000000    //5s
    #define SCAN_PORT_LIMIT    5
    hash_t *scan_hash;
    
    
    //获取当前时间
    long get_now_time()
    {
        struct timeval tv;
        gettimeofday(&tv,NULL);
        return (tv.tv_sec*1000000 + tv.tv_usec);
    }
    
    //获取扫描的端口个数
    static int get_scan_port_count(unsigned char map[65535])
    {
        int i = 0;
        int sum = 0;
        for(i = 0; i< 65535; i++)
        {
            if(1 == map[i])
            {
                sum++;
            }
        }
    
        return sum;
    }
    
    static void hexToCharIP(struct in_addr addrIP, char ipstr[16])
    {
      unsigned int intIP;
      memcpy(&intIP, &addrIP,sizeof(unsigned int));
      int a = (intIP >> 24) & 0xFF;
      int b = (intIP >> 16) & 0xFF;
      int c = (intIP >> 8) & 0xFF;
      int d = intIP & 0xFF;
      sprintf(ipstr, "%d.%d.%d.%d", d,c,b,a);
    }
    
    
    
    //基于ip+protocol的hash函数
    static unsigned int hash_func(unsigned int bucktes, void *key)
    {
        unsigned int hashval = 0;
    
        while('\0' != *(char*)key)
        {
            hashval = (hashval << 5) + *(char*)key++;
        }
        return hashval % bucktes;
    }
    
    int network_scan_init()
    {   
        scan_hash = hash_alloc(HASH_TABLE_SIZE, hash_func);
        if(NULL == scan_hash)
        {
            return -1;
        }
    
        return 0;
    }
    
    
    static int network_parse_info(struct NETWATCH_HEADER_T *pap,  scan_info *parse_info)
    {
        int iRslt = 0;
        unsigned int seq = pap->seq;
        unsigned char fin =  pap->flag & 0x01;
        unsigned char syn = (pap->flag & 0x02) >> 1;
        //unsigned char rst = (pap->flag & 0x04) >> 2;
        unsigned char psh = (pap->flag & 0x08) >> 3;
        unsigned char ack = (pap->flag & 0x10) >> 4;
        
        switch(pap->protpcol)
        {
            case 0:   //TCP
                if(0 == psh)
                {
                    parse_info->scan_type = SCAN_TYPE_NULL;
                    goto end;
                }
    
                if(1 == syn && 0 == ack)
                {
                    parse_info->scan_type = SCAN_TYPE_SYN;
                }
                else if(1 == ack && 0 == seq)
                {
                    parse_info->scan_type = SCAN_TYPE_ACK;
                }
                else if(1 == fin && 0 == ack)
                {
                    parse_info->scan_type = SCAN_TYPE_FIN;
                }
                else if(0 != seq && 0 != ack)
                {
                    parse_info->scan_type = SCAN_TYPE_CON;
                }
                else
                {
                    parse_info->scan_type = SCAN_TYPE_NULL;
                    goto end;
                }
                break;
            case 1:     //UDP
                parse_info->scan_type = SCAN_TYPE_SEND;
                break;
            default:
                parse_info->scan_type = SCAN_TYPE_NULL;
                break;
        }
    
        parse_info->protocol = pap->protpcol;
        parse_info->scan_port= pap->port;
        hexToCharIP(pap->ip, parse_info->scan_ipstr);
        
    end:
        //HikadefLog(LOG_INFO, "%d,%d,%d,%d,%d,%d, ip = %s", seq,fin,syn,rst,psh,ack, parse_info->scan_ipstr);
        return iRslt;
    }
    
    int network_scan_check(struct NETWATCH_HEADER_T *pap)
    {
        char key[100] = {0};
        scan_info parse_info = {0};
        scan_info *find = NULL;
    
        //解析
        network_parse_info(pap, &parse_info);
    
        if(SCAN_TYPE_NULL == parse_info.scan_type)
        {
            //HikadefLog(LOG_INFO,"not scan");
            return 0;
        }
        
        //key = ip:proto
        snprintf(key, sizeof(key), "%s:%d", parse_info.scan_ipstr, parse_info.protocol);
        
        find = (scan_info*)hash_lookup_entry(scan_hash, key, sizeof(*key)); 
        if(NULL == find)
        {
            
            parse_info.timestamp = get_now_time();
            parse_info.portmap[parse_info.scan_port] = 1;
            hash_add_entry(scan_hash, key, sizeof(key), &parse_info, sizeof(scan_info));
            HikadefLog(LOG_INFO,"new hash node ,time %ld, port = %d ", parse_info.timestamp, parse_info.scan_port);
        }
        else
        {
            if(get_now_time() - find->timestamp > SCAN_TIME_LIMIT)
            {
                //上次扫描行为结束
                HikadefLog(LOG_INFO,"Time up, port count = %d ", get_scan_port_count(find->portmap));
                if(get_scan_port_count(find->portmap)>= SCAN_PORT_LIMIT)
                {
                    HikadefLog(LOG_INFO,"Timpe and port up, must alarm ");
                    hikadef_alarm_network_scan_insert_info(find->scan_ipstr, find->scan_port, protocol_str[find->protocol]);
                    hash_free_entry(scan_hash, key, sizeof(key));
                }
                else
                {
                    HikadefLog(LOG_INFO,"Time up, new_port = %d", parse_info.scan_port);
                    find->portmap[parse_info.scan_port] = 1;
                    find->timestamp = get_now_time();
                    hash_update_entry(scan_hash, key, sizeof(key), find, sizeof(scan_info));
                }
                
            }
            else
            {
                HikadefLog(LOG_INFO,"Time not up, add port =%d", parse_info.scan_port);
                find->portmap[parse_info.scan_port] = 1;
                hash_update_entry(scan_hash, key, sizeof(key), find, sizeof(scan_info));
                
            }
        }
    
        return 0;
    }
    
    
    
    #if 0
    int main()
    {
        struct NETWATCH_HEADER_T test = {0};
    
    
        network_scan_init();
    
        test.protpcol = 0;
        test.flag = 0x1a;
        test.port = 10;
        test.seq = 0;
    
        network_scan_check(&test);
    
        test.protpcol = 1;
        network_scan_check(&test);
    
        test.port = 11;
        network_scan_check(&test);
    
        sleep (5);
        test.port = 12;
        network_scan_check(&test);
    
            test.port = 13;
        network_scan_check(&test);
    
    
        return 0;
    
        
    }
    #endif
    

    相关文章

      网友评论

          本文标题:端口扫描

          本文链接:https://www.haomeiwen.com/subject/kujfdrtx.html