端口扫描

2022-03-10  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读