C++ ICMP扫描源码

头文件声明:

class ScanICMP 
{

public:

    /* @接口 默认构造函数
     * @邮箱 575814050@qq.com
     * @时间 2018年12月13号
     */
    ScanICMP();
    
    /* @接口 默认析构函数
     * @邮箱 575814050@qq.com
     * @时间 2018年12月13号
     */
    ~ScanICMP();

    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年12月19号
     */
    virtual void stopICMP();
    
    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年12月13号
     */
    virtual bool beginICMP(ulong);
    
    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年2018月12号
     */
    virtual void setTimeout(ulong);

    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年2018月12号
     */
    virtual bool beginICMP(ulong, ulong);
    
    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年12月18号
     */
    virtual void setSyntonyFunc(const DoxSyntonyParam &);

private:

    /* @接口
     * @邮箱 575814050@qq.com
     * @时间 2018年12月13号
     */
    void buildICMP(char *, int);
    
    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年10月26号
     */
    ulong getTickCountCalibrate();

    /* @接口
     * @邮箱 575814050@qq.com
     * @时间 2018年12月6号
     */
    static ulong icmpThread(void *);

    /* @接口
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年11月30号
     */
    ushort calCheckSum(ushort *, int);
    
    /* @接口
     * @邮箱 575814050@qq.com
     * @时间 2018年12月18号
     */
    void buildAddr(ulong, SOCKADDR_IN &);

    /* @接口 
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年12月18号
     */
    bool recvAndSendInfo(char *, SOCKADDR_IN &, char *);

    /* @接口
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 575814050@qq.com
     * @时间 2018年12月21号
     */
    bool isSameICMPReport(const ICMPHeader *, const ICMPHeader *);

public:

    ulong m_sip;
    ulong m_eip;
    bool m_stop;
    ulong m_sRaw;
    ulong m_dwTimeout;
    DoxSyntonyParam m_send;

};
源代码定义:

ScanICMP::ScanICMP()
    , m_stop(false)
    , m_dwTimeout(128)
{
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(2, 2);
    if(WSAStartup(wVersionRequested, &wsaData))
    {
        DoxLogger("Winsock Initialization failed");
        exit(1);
    }
    m_sRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);
    int fromlen = sizeof(SOCKADDR_IN); int timeout = m_dwTimeout;
    int bread = setsockopt(m_sRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
    if(bread == SOCKET_ERROR)
    {
        DoxLogger("setsockopt(SO_RCVTIMEO) failed;");
        exit(1);
    }
}

ScanICMP::~ScanICMP()
{
    closesocket(m_sRaw);
    WSACleanup();
}

void ScanICMP::stopICMP()
{
    m_stop = true;
}

bool ScanICMP::beginICMP(ulong ip)
{
    static int seq = 0; Object<IDoxPointer> info(NIL);
    char pIcmp[sizeof(ICMPHeader) + 32] = { 0 };
    SOCKADDR_IN dest; buildAddr(ip, dest); buildICMP(pIcmp, seq++); 
    int nRet = sendto(m_sRaw, pIcmp, sizeof(ICMPHeader) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
    if(nRet == SOCKET_ERROR)
    {
        DoxLogger("sendto() failed;"); return false;
    }
    char recBuf[65536] = { 0 };    int nLen = sizeof(SOCKADDR_IN);
    ICMPHeader *srcICMP = (ICMPHeader *)pIcmp;
    while(true)
    {
        if(m_stop) { Sleep(100); break; }
        ulong timeStamp = getTickCountCalibrate();
        nRet = recvfrom(m_sRaw, recBuf, 65536, 0, (sockaddr *)&dest, &nLen);
        if(nRet == SOCKET_ERROR) break;
        IPHeader *pIPHeader = (IPHeader*)recBuf;
        ushort usIPHeaderLen = (ushort)((pIPHeader->m_byVerHLen & 0x0f) * 4);
        ICMPHeader *desICPMP = (ICMPHeader *)(recBuf + usIPHeaderLen);
        ulong timeDiff = timeStamp - srcICMP->m_ulTimeStamp;
        if(timeDiff > m_dwTimeout) break;
        if(!isSameICMPReport(desICPMP, srcICMP)) continue;
//         if(desICPMP->m_usID != srcICMP->m_usID) continue;
//         if(desICPMP->m_byType != ECHO_REPLY) continue;
//         if(desICPMP->m_usSeq != srcICMP->m_usSeq) continue;        
        in_addr inaddr; inaddr.s_addr = ip;
        QString address = QS("%1:Byte = %2 Time = %3ms TTL = %4").arg(inet_ntoa(inaddr)).arg(nRet).arg(timeDiff).arg(pIPHeader->m_byTTL);
        info->setString(address); m_send(info); Sleep(5);
        return true;
    }
    return false;
}

ulong ScanICMP::icmpThread(void *param)
{
    ScanICMP *pIcmp = (ScanICMP *)param;
    for(ulong ip = pIcmp->m_sip; ip < pIcmp->m_eip + 1; ++ip)
        pIcmp->beginICMP(htonl(ip));
    return 0;
}

ulong ScanICMP::getTickCountCalibrate()
{
    static ULONG s_ulFirstCallTick = 0;
    static LONGLONG s_ullFirstCallTickMS = 0;
    SYSTEMTIME systemtime;
    FILETIME filetime;
    GetLocalTime(&systemtime);
    SystemTimeToFileTime(&systemtime, &filetime);
    LARGE_INTEGER liCurrentTime;
    liCurrentTime.HighPart = filetime.dwHighDateTime;
    liCurrentTime.LowPart = filetime.dwLowDateTime;
    LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;
    if(s_ulFirstCallTick == 0)
        s_ulFirstCallTick = GetTickCount();
    if(s_ullFirstCallTickMS == 0)
        s_ullFirstCallTickMS = llCurrentTimeMS;
    return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);
}

void ScanICMP::setTimeout(ulong timeout)
{
    m_dwTimeout = timeout;
}

bool ScanICMP::beginICMP(ulong sip, ulong eip)
{
    m_sip = sip; m_eip = eip;
    HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)icmpThread, this, 0, NULL);
    if(handle == INVALID_HANDLE_VALUE)
    {
        DoxLogger("创建线程失败");
        return false;
    }
    CloseHandle(handle);
    return true;
}

void ScanICMP::buildICMP(char *buff, int nSeq)
{
    //初始化ICMP包  
    ICMPHeader *pIcmp = (ICMPHeader *)buff;
    pIcmp->m_byType = ECHO_REQUEST; pIcmp->m_byCode = 0;
    pIcmp->m_usID = (ushort)::GetCurrentProcessId();
    pIcmp->m_usChecksum = 0; pIcmp->m_usSeq = 0;
    pIcmp->m_ulTimeStamp = getTickCountCalibrate();
    pIcmp->m_usSeq = nSeq;
    pIcmp->m_usChecksum = calCheckSum((ushort *)buff, sizeof(ICMPHeader) + 32);
}

void ScanICMP::buildAddr(ulong ip, SOCKADDR_IN &dest)
{
    dest.sin_family = AF_INET;
    dest.sin_port = htons(0);
    dest.sin_addr.s_addr = ip;
}

ushort ScanICMP::calCheckSum(ushort *pBuffer, int nSize)
{
    unsigned long ulCheckSum = 0;
    while(nSize > 1)
    {
        ulCheckSum += *pBuffer++;
        nSize -= sizeof(ushort);
    }
    if(nSize)
        ulCheckSum += *(uchar*)pBuffer;
    ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff);
    ulCheckSum += (ulCheckSum >> 16);
    return (ushort)(~ulCheckSum);
}

void ScanICMP::setSyntonyFunc(const DoxSyntonyParam &recvFunc)
{
    m_send = recvFunc;
}

bool ScanICMP::recvAndSendInfo(char *pIcmp, SOCKADDR_IN &dest, char *recBuf)
{
    int nRet = sendto(m_sRaw, pIcmp, sizeof(ICMPHeader) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
    if(nRet == SOCKET_ERROR)
    {
        DoxLogger("sendto() failed;");
        return false;
    }
    int nLen = sizeof(SOCKADDR_IN);
    nRet = recvfrom(m_sRaw, recBuf, 65536, 0, (sockaddr *)&dest, &nLen);
    return nRet > 0;
}

bool ScanICMP::isSameICMPReport(const ICMPHeader *icmp1, const ICMPHeader *icmp2)
{
    if(icmp1->m_usID != icmp2->m_usID) return false;
    if(icmp1->m_byType != ECHO_REPLY)  return false;
    if(icmp1->m_usSeq != icmp2->m_usSeq)  return false;
    return true;
}
源程序下载地址:https://download.csdn.net/download/yangfahe1/10909507

示例程序运行方式:https://blog.csdn.net/yangfahe1/article/details/84028318

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值