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

📄 synscan.c

📁 nessus 扫描器 windows版 漏洞扫描
💻 C
字号:
#include <winsock2.h>
#include <process.h>

#include "port.h"
#include "synscan.h"

#define MAX_PACK_LEN        1024*8          //接收的最大IP报文
#define MAX_ADDR_LEN        16+MAX_PATH+2   //点分十进制地址的最大长度+主机名

//计算检验和
USHORT checksum(USHORT *buffer, int size) 
{
    unsigned long cksum=0;

    while (size > 1) {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }

    if (size) {
        cksum += *(UCHAR*)buffer;
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
    return (USHORT)(~cksum);
}

int tcp_status(int sd, char *type, DWORD timeout)
{
    fd_set rset, wset, eset;
    fd_set FAR *prset = NULL, *pwset = NULL, *peset = NULL;
    struct timeval tval;
    int i, status, err_no = 0;
    DWORD t1, t2;
    MSG msg;

    if (timeout <1000) timeout = timeout * 1000;

    tval.tv_sec = 0;
    tval.tv_usec = 0;
    t1 = GetTickCount();
    t2 = t1;
    while(t2-t1 <= timeout)
    {
        Sleep(10);
        FD_ZERO(&rset);
        FD_ZERO(&wset);
        FD_ZERO(&eset);

        for(i = 0; i<(int)strlen(type); i++)
        {
            if(type[i] == 'r') { FD_SET(sd, &rset); prset = &rset; }
            if(type[i] == 'w') { FD_SET(sd, &wset); pwset = &wset; }
            if(type[i] == 'e') { FD_SET(sd, &eset); peset = &eset; }
        }
        status = select(-1/*sd+1*/, prset, pwset, peset, &tval);
        err_no = WSAGetLastError();
        t2 = GetTickCount();
        if(status == 0)
        {
            if(PeekMessage(&msg, 0, NULL, NULL, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
                if(msg.message == WM_QUIT) return -1;
            }
            if(t2-t1 <timeout) continue;
            else
            {
                if(prset) FD_CLR((UINT)sd,&rset);
                if(pwset) FD_CLR((UINT)sd,&wset);
                if(peset) FD_CLR((UINT)sd,&eset);
                SetLastError(WSAETIMEDOUT);
                return -10;
            }
        }

        if(peset && FD_ISSET(sd, peset))
        {
            if(prset != NULL) FD_CLR((UINT)sd,&rset);
            if(pwset != NULL) FD_CLR((UINT)sd,&wset);
            if(peset != NULL) FD_CLR((UINT)sd,&eset);
            /*
            len = sizeof(errno);
            getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&errno, &len);
            */
            return -1;
        }
        if((prset && FD_ISSET(sd, prset)) || (pwset && FD_ISSET(sd, pwset)))
        {
            /*
            len = sizeof(errno);
            getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&errno, &len);
            */
        }
        if(prset != NULL) FD_CLR((UINT)sd,&rset);
        if(pwset != NULL) FD_CLR((UINT)sd,&wset);
        if(peset != NULL) FD_CLR((UINT)sd,&eset);

        if(err_no == WSAEINTR) return WSAEINTR;
        if(err_no)
        {
            return -1;
        }
        else break;

    }
    return 0;
}

DWORD WINAPI DoRecvPacket(LPVOID pParam)
{
    char            szSrcHost[128];
    char            szRemoteHost[128];
    char            szRemoteIP[50];
    int             nScanMethod;
    int             *pnNodata = NULL;
    int             *pnLoop = NULL;
    int             *pnLocalThreads = NULL;
    int             *pnTotalThreads = NULL;
    int             *pnOpened = NULL;
    struct arglist  *desc = NULL;
    struct arglist  *key = NULL;
    char            szLine[MAX_PATH] = {0};

    char            pRecvBuf[RECV_BUFSIZE+1] = {0};
    unsigned int    nBufSize = 0;
    SOCKET          nSockListen = 0;
    DWORD           dwDest;
    long            *lPhe;
    HOSTENT         *phe;
    int             nPort = 0;
    DWORD           dwTimeout = 0;
    DWORD           dwStartTime = 0;
    int             nErrorCode;
    BOOL            bRecvPacket = FALSE;

    IP_HEADER       *ip_hdr = NULL;
    TCP_HEADER      *tcp_hdr = NULL;
    USHORT          ip_hdr_len = 0;
    UINT            ack = 0;
    USHORT          sport = 0;
    UCHAR           flag = 0;
    DWORD           source_addr = 0;
    
    DWORD           dwBufferLen[10] ;
    DWORD           dwBufferInLen = 1 ;
    DWORD           dwBytesReturned = 0 ;
    int             nSourcePort = 7000;
    SOCKADDR_IN     sa;
    int             nProtocol = 0;

    RECV_THREAD_INFO *thread_info = NULL;
    thread_info = (RECV_THREAD_INFO*)pParam;

    strcpy(szSrcHost, thread_info->szSrcHost);
    strcpy(szRemoteHost, thread_info->szRemoteHost);
    strcpy(szRemoteIP, thread_info->szRemoteIP);
    nScanMethod = thread_info->nScanMethod;
    pnLoop = thread_info->pnLoop;
    pnOpened = thread_info->pnOpened;
    desc = thread_info->desc;
    key = arg_get_value(desc, "key");

    nSockListen = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    CheckSockError(nSockListen, "socket");

    while (nSourcePort < 65536) {
        //获得本地IP
        sa.sin_addr.s_addr = inet_addr(szSrcHost);
        sa.sin_family = AF_INET;
        sa.sin_port = htons(nSourcePort);
        nErrorCode = bind(nSockListen, (PSOCKADDR)&sa, sizeof(sa));
        if (nErrorCode != SOCKET_ERROR)
            break;
        nSourcePort++;
    }

    if (nErrorCode == SOCKET_ERROR) goto f_exit;

    //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
    nErrorCode = WSAIoctl(nSockListen, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen),
        &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL);
    CheckSockError(nErrorCode, "Ioctl");
    if (nErrorCode == SOCKET_ERROR) goto f_exit;

    //获得目标主机地址
    dwDest = inet_addr(szRemoteIP);
    if (dwDest == INADDR_NONE) {
        phe = gethostbyname(szRemoteIP);
        if (phe) {
            lPhe = (long*)(*phe->h_addr_list);
            dwDest = *lPhe;
        }
    }

    //接收数据
    dwTimeout = RECV_TIMEOUT;
    dwStartTime = GetTickCount();

    while (1) {
        if (*pnOpened && !bRecvPacket) break;

        //计时,RECV_TIMEOUT s超时
        if ((GetTickCount()-dwStartTime) > dwTimeout) {
            if ( ((*pnLoop) > 0) && (nScanMethod == SCAN_SYN) ) {
                dwStartTime = GetTickCount();//计时清零
            }
            else goto f_exit;
        }

        if (tcp_status(nSockListen, "r", 1) < 0)
            continue;

        memset(pRecvBuf, 0, sizeof(pRecvBuf));
        nErrorCode = recv(nSockListen, pRecvBuf, RECV_BUFSIZE, 0);
        CheckSockError(nErrorCode, "recv");
        nBufSize = nErrorCode;
        if (nBufSize <= 0) goto f_exit;

        //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
        nErrorCode = WSAIoctl(nSockListen, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen),
            &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL);
        CheckSockError(nErrorCode, "Ioctl");
        if (nErrorCode == SOCKET_ERROR) goto f_exit;

        ip_hdr = (IP_HEADER *)pRecvBuf;
        ip_hdr_len = sizeof(unsigned long) * (ip_hdr->h_lenver & 0xf);
        source_addr = ip_hdr->sourceIP;

        nProtocol = ip_hdr->proto;
        switch (nProtocol) {
        case IPPROTO_TCP:
            if ( nBufSize < (ip_hdr_len + sizeof(TCP_HEADER)) ) {
                fprintf(stderr, "Packet length error: %d, request length: %d\n", nBufSize, ip_hdr_len + sizeof(TCP_HEADER));
                continue;
            }

            tcp_hdr = (TCP_HEADER*)(pRecvBuf + ip_hdr_len);
            sport = tcp_hdr->th_sport;
            ack = tcp_hdr->th_ack;
            flag = tcp_hdr->th_flag;
            nPort = ntohs(sport); 

            //地址是否正确
            if(source_addr != dwDest)
                continue;

            bRecvPacket = TRUE;

            //RST/ACK - 端口未开放
            if ((flag & ~TH_URG) == (TH_RST | TH_ACK)) {
                int type = 0;
                if (!plug_get_key(desc, "PortScan/ClosePort", &type))
                    plug_set_key(desc, "PortScan/ClosePort", ARG_INT, nPort);
                dwStartTime = GetTickCount(); //计时清零
                continue;
            }

            //SYN/ACK - 端口开放
            if ((flag & ~TH_URG) == (TH_SYN | TH_ACK)) {
                if (nScanMethod == SCAN_SYN) {
                    if (AlertUser(desc, nPort)) {
                        (*pnOpened)++;
                    }
                    dwStartTime = GetTickCount(); //计时清零
                }
            }
        break;
        case IPPROTO_UDP:
        break;
        case IPPROTO_ICMP:
        break;
        default: break;
        }

    }

f_exit:

    closesocket(nSockListen);
    
    return 1;
}

int SendSyn(SOCKADDR_IN sa, SOCKADDR_IN dest, int nPort)
{
    int             nDataSize;
    DWORD           dwSeq;
    unsigned char   ucTtl;
    USHORT          usWin;
    int             nSourcePort;
    long            *lPhe = 0;
    HOSTENT         *phe = NULL;
    IP_HEADER       ip_header;
    TCP_HEADER      tcp_header;
    PSD_HEADER      psd_header;
    IP_HEADER       *ip_hdr = NULL;
    TCP_HEADER      *tcp_hdr = NULL;
    
    unsigned short  ip_hdr_len = 0;
    unsigned int    ack = 0;
    USHORT          sport = 0;
    unsigned char   flag = 0;
    DWORD           source_addr = 0;

    char            pSendBuf[128] = {0};
    char            pRecvBuf[RECV_BUFSIZE+1] = {0};
    SOCKET          nSockRaw = 0;

    BOOL            bOpt = TRUE;
    int             nErrorCode;
    int             nRtn = 0;

    dwSeq = SEQ_VALUE + nPort * 2;
    ucTtl = nPort % 20 + 50;
    nSourcePort = nPort % 20000 + SOURCE_PORT;

    usWin = htons(1024 * (ucTtl % 4 + 1));
    nSockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    CheckSockError(nSockRaw, "socket()");

    //设置IP头操作选项
    bOpt = TRUE;
    nErrorCode = setsockopt(nSockRaw, IPPROTO_IP, IP_HDRINCL,
        (char *)&bOpt, sizeof(bOpt));
    CheckSockError(nErrorCode, "setsockopt()"); 
    
    if (nErrorCode == SOCKET_ERROR) {
        closesocket(nSockRaw);
        return -1;
    }

    //printf("source address: %s\n",inet_ntoa(sa.sin_addr));
    //printf("target address: %s\n",inet_ntoa(dest.sin_addr));

    //填充IP首部
    ip_header.h_lenver = (4<<4 | sizeof(ip_header)/sizeof(unsigned long));
    //高四位IP版本号,低四位首部长度
    ip_header.total_len = htons(sizeof(IP_HEADER) + sizeof(TCP_HEADER)); //16位总长度(字节)
    ip_header.ident = 1; //16位标识
    ip_header.frag_and_flags = 0; //3位标志位
    ip_header.ttl = ucTtl; //8位生存时间TTL
    ip_header.proto = IPPROTO_TCP; //8位协议(TCP,UDP…)
    ip_header.checksum = 0; //16位IP首部校验和
    ip_header.sourceIP = sa.sin_addr.s_addr; //32位源IP地址
    ip_header.destIP = dest.sin_addr.s_addr; //32位目的IP地址

    //填充TCP首部
    tcp_header.th_sport = htons(nSourcePort); //源端口号
    tcp_header.th_dport = htons(nPort); //目的端口号
    tcp_header.th_seq = htonl(dwSeq); //SYN序列号
    tcp_header.th_ack = 0; //ACK序列号置为0
    tcp_header.th_lenres = (sizeof(TCP_HEADER)/4<<4|0); //TCP长度和保留位
    tcp_header.th_flag = 2; //SYN 标志
    tcp_header.th_win = usWin; //窗口大小
    tcp_header.th_urp = 0; //偏移
    tcp_header.th_sum = 0; //校验和

    //填充TCP伪首部(用于计算校验和,并不真正发送)
    psd_header.saddr = ip_header.sourceIP;
    psd_header.daddr = ip_header.destIP;
    psd_header.mbz = 0;
    psd_header.ptcl = IPPROTO_TCP;
    psd_header.tcpl = htons(sizeof(tcp_header));

    //计算TCP校验和,计算校验和时需要包括TCP pseudo header 
    memcpy(pSendBuf, &psd_header, sizeof(psd_header)); 
    memcpy(pSendBuf + sizeof(psd_header), &tcp_header, sizeof(tcp_header));
    tcp_header.th_sum = checksum((USHORT *)pSendBuf, sizeof(psd_header) + sizeof(tcp_header));

    //计算IP校验和
    memset(pSendBuf, 0, sizeof(pSendBuf));
    memcpy(pSendBuf, &ip_header, sizeof(ip_header));
    memcpy(pSendBuf + sizeof(ip_header), &tcp_header, sizeof(tcp_header));
    //memset(pSendBuf + sizeof(ip_header) + sizeof(tcp_header), 0, 4);
    nDataSize = sizeof(ip_header) + sizeof(tcp_header);
    ip_header.checksum = checksum((USHORT *)&ip_header, sizeof(ip_header));

    //填充发送缓冲区
    if ( !memcpy(pSendBuf, &ip_header, sizeof(ip_header)) ) {
        closesocket(nSockRaw);
        return -1;
    }

    //发送TCP报文
    nErrorCode = sendto(nSockRaw, pSendBuf, nDataSize, 0,
        (struct sockaddr*) &dest, sizeof(dest));
    if (nErrorCode == SOCKET_ERROR) {

        //printf("source address - %s: %d\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
        //printf("target address - %s: %d\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port));
        
        CheckSockError(nErrorCode, "sendto()");
        closesocket(nSockRaw);
        return -1;
    }
    else
        nRtn = 1;

    closesocket(nSockRaw);

    return nRtn;
}

⌨️ 快捷键说明

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