欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

使用C++对物理网卡/虚拟网卡进行识别(包含内外网筛选)

程序员文章站 2022-05-16 12:45:26
简介 在Socket编程的时候,我们需要实时获取我们所需要的IP地址。例如在编写后门的时候,我们可能需要获得有效的外网IP或内网IP;有时候我们可能需要判断我们获取的是否是虚拟机网卡,这时候就需要对每一张网卡上的特征进行识别。以下笔者总结了一些常用的处理方法供大家参考。 参考资料: 1. "提取网卡 ......

简介

在socket编程的时候,我们需要实时获取我们所需要的ip地址。例如在编写后门的时候,我们可能需要获得有效的外网ip或内网ip;有时候我们可能需要判断我们获取的是否是虚拟机网卡,这时候就需要对每一张网卡上的特征进行识别。以下笔者总结了一些常用的处理方法供大家参考。


参考资料:1.
              2.

c++代码样例

1. 头文件(包含特征处理函数)

/////////////////////////////////////////
//
// filename : netinfoproc.h
// creator : peterz
// date : 2018-6-21 23:50
// comment : 网卡信息筛选
// editor : visual studio 2017
//
/////////////////////////////////////////

#pragma once

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <strsafe.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <cstring>

#pragma comment(lib,"iphlpapi.lib")

using namespace std;

#define reg_error -2
#define no_pci -1
#define is_pci 0


/**
 * @brief 查看字符串中是否有指定特征串
 * @param source 指向源字符串的指针
 * @param target 指向目标字符串的指针
 */
bool isinstring(lpcstr source, lpcstr target)
{
    if (source == null && target == null)
    {
        return false;
    }
    const size_t targetlength = strlen(target);
    const size_t sourcelength = strlen(source);

    if (sourcelength >= targetlength)
    {
        for (int i = 0; i < strlen(source); i++)
        {
            if (i + targetlength > sourcelength)
            {
                return false;
            }
            for (int j = 0; j < targetlength; j++)
            {
                if (*(source + i + j) != *(target + j))
                {
                    break;
                }
                if (j == targetlength - 1)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

/**
 * @brief 获取注册表数据
 * @param hroot 根键
 * @param szsubkey 子键
 * @param szvaluename 数据项名
 * @param szreginfo 数据
 */
bool getreginfo(hkey hroot, lpctstr szsubkey, lpctstr szvaluename, lpstr szreginfo)
{
    hkey hkey;
    dword dwtype = reg_sz;
    dword dwlendata = strlen(szreginfo);
    long lres = regcreatekeyex(hroot, szsubkey, 0, null, reg_option_non_volatile, key_all_access, null, &hkey, null);
    if (lres != error_success)
    {
        if (lres == 5)
        {
            printf("please use administrator privilege !\n");
        }
        else
        {
            printf("get register info error! error code is ");
            printf("%ld\n", lres);
        }
        regclosekey(hkey);
        regclosekey(hroot);
        return false;
    }
    regqueryvalueex(hkey, szvaluename, 0, &dwtype, null, &dwlendata);
    lres = regqueryvalueex(hkey, szvaluename, 0, &dwtype, (lpbyte)szreginfo, &dwlendata);
    if (lres != error_success)
    {
        regclosekey(hkey);
        regclosekey(hroot);
        return false;
    }
    regclosekey(hkey);
    regclosekey(hroot);
    return true;
}

/**
 * @brief 验证注册信息是否是pci物理网卡(需要以管理员权限运行程序)
 * @param pipadapterinfo 指向网卡数据的指针
 */
int ispcinetcard(const pip_adapter_info pipadapterinfo)
{
    //通过注册表特征去除非物理网卡
    char szregsubkey[255] = "system\\currentcontrolset\\control\\network\\{4d36e972-e325-11ce-bfc1-08002be10318}\\";
    char sznetcardreginfo[255] = "\0";
    stringcchcat(szregsubkey, sizeof(szregsubkey), pipadapterinfo->adaptername);
    stringcchcat(szregsubkey, sizeof(szregsubkey), "\\connection");
    if (!getreginfo(hkey_local_machine, szregsubkey, "pnpinstanceid", sznetcardreginfo))
    {
        return reg_error;
    }
    if (strncmp(sznetcardreginfo, "pci", 3) == 0) return is_pci;
    else return no_pci;

}


/**
 * @brief 验证是否是虚拟网卡
 * @param pipadapterinfo 指向网卡数据的指针
 */
bool isvirtualnetcard(const pip_adapter_info pipadapterinfo)
{
    //去除有特征名的虚拟网卡
    if (isinstring(strlwr(pipadapterinfo->description), "virtual")) return true;
    //去除有mac的虚拟网卡 vmware
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x05 && pipadapterinfo->address[2] == 0x69) return true;
    //去除有mac的虚拟网卡 vmware
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x0c && pipadapterinfo->address[2] == 0x29) return true;
    //去除有mac的虚拟网卡 vmware
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x50 && pipadapterinfo->address[2] == 0x56) return true;
    //去除有mac的虚拟网卡 vmware
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x1c && pipadapterinfo->address[2] == 0x14) return true;
    //去除有mac的虚拟网卡 parallels
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x1c && pipadapterinfo->address[2] == 0x42) return true;
    //去除有mac的虚拟网卡 microsoft virtual pc
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x03 && pipadapterinfo->address[2] == 0xff) return true;
    //去除有mac的虚拟网卡 virtual iron
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x0f && pipadapterinfo->address[2] == 0x4b) return true;
    //去除有mac的虚拟网卡 red hat xen , oracle vm , xen source, novell xen
    if (pipadapterinfo->address[0] == 0x00 && pipadapterinfo->address[1] == 0x16 && pipadapterinfo->address[2] == 0x3e) return true;
    //去除有mac的虚拟网卡 virtualbox
    if (pipadapterinfo->address[0] == 0x08 && pipadapterinfo->address[1] == 0x00 && pipadapterinfo->address[2] == 0x27) return true;
    return false;
}


/**
 * @brief 验证是否是0.0.0.0不可用ip
 * @param pipadapterinfo 指向网卡数据的指针
 */
bool isinvalidip(const pip_adapter_info pipadapterinfo)
{
    ip_addr_string *pipaddrstring = &(pipadapterinfo->ipaddresslist);
    do
    {
        if (!strcmp(pipaddrstring->ipaddress.string, "0.0.0.0"))
        {
            return false;
        }
        if ((pipaddrstring = pipaddrstring->next) == null)
        {
            return true;
        }
    } while (pipaddrstring);
    return true;
}

/**
* @brief 验证是否是内网ip
* @param pipadapterinfo 指向网卡数据的指针
*/
bool isintranetip(const pip_adapter_info pipadapterinfo)
{
    ip_addr_string *pipaddrstring = &(pipadapterinfo->ipaddresslist);
    do
    {
        if (strncmp(pipaddrstring->ipaddress.string, "10", 2) == 0 || (strncmp(pipaddrstring->ipaddress.string, "172.16", 6) > 0 && strncmp(pipaddrstring->ipaddress.string, "172.31", 6) < 0) || strncmp(pipaddrstring->ipaddress.string, "192.168", 7) == 0)
        {
            return true;
        }
        if ((pipaddrstring = pipaddrstring->next) == null)
        {
            return false;
        }
    } while (pipaddrstring);
    return true;
}

2. cpp文件(代码应用演示)

/////////////////////////////////////////
//
// filename : netcardver.cpp
// creator : peterz
// date : 2018-6-21 23:50
// comment : 网卡信息筛选
// editor : visual studio 2017
//
/////////////////////////////////////////

#include "netinfoproc.h"

void output1(pip_adapter_info pipadapterinfo); //结果输出1(正常结果)
void output2(pip_adapter_info pipadapterinfo); //结果输出2(删除虚拟网卡的结果)
void output3(pip_adapter_info pipadapterinfo); //结果输出3(去除非pci物理网卡) >>需要以管理员权限运行程序<<
void output4(pip_adapter_info pipadapterinfo); //结果输出4(筛选内网网卡)

//主函数
int main(void)
{
    pip_adapter_info pipadapterinfo = (pip_adapter_info)malloc(sizeof(ip_adapter_info));
    unsigned long stsize = sizeof(ip_adapter_info);
    int nrel = getadaptersinfo(pipadapterinfo, &stsize);
    if (error_buffer_overflow == nrel/*getadaptersinfo参数传递的内存空间不足*/)
    {
        //free(pipadapterinfo);
        pipadapterinfo = (pip_adapter_info)realloc(pipadapterinfo, stsize);
        nrel = getadaptersinfo(pipadapterinfo, &stsize);
    }
    if (error_success == nrel)
    {
        printf(">>>>>>>>> 正常结果 <<<<<<<<<<<\n\n");
        output1(pipadapterinfo);
        printf("\n\n>>>>>>>>> 删除虚拟网卡的结果 <<<<<<<<<\n\n");
        output2(pipadapterinfo);
        printf("\n\n>>>>>>>>> 去除非pci物理网卡的结果 <<<<<<<<<\n\n");
        output3(pipadapterinfo);
        printf("\n\n>>>>>>>>> 筛选内网网卡的结果 <<<<<<<<<\n\n");
        output4(pipadapterinfo);
    }
    if (pipadapterinfo)
    {
        free(pipadapterinfo);
    }
    system("pause");
    return 0;
}

//结果输出1(正常结果)
void output1(pip_adapter_info pipadapterinfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pipadapterinfo)
    {
        //输出信息
        cout << "网卡名称:" << pipadapterinfo->adaptername << endl;
        cout << "网卡描述:" << pipadapterinfo->description << endl;
        cout << "网卡mac地址:" << pipadapterinfo->address;
        for (uint i = 0; i < pipadapterinfo->addresslength; i++)
        {
            if (i == pipadapterinfo->addresslength - 1)
            {
                printf("%02x\n", pipadapterinfo->address[i]);
            }
            else
            {
                printf("%02x-", pipadapterinfo->address[i]);
            }
        }
        cout << "网卡ip地址如下:" << endl;
        ip_addr_string *pipaddrstring = &(pipadapterinfo->ipaddresslist);
        //可能网卡有多ip,因此通过循环去判断
        do
        {
            cout << pipaddrstring->ipaddress.string << endl;
            pipaddrstring = pipaddrstring->next;
        } while (pipaddrstring);
        pipadapterinfo = pipadapterinfo->next;
        cout << "*****************************************************" << endl;
    }
    return;
}

//结果输出2(删除虚拟网卡的结果)
void output2(pip_adapter_info pipadapterinfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pipadapterinfo)
    {
        //去除虚拟网卡ip
        if (isvirtualnetcard(pipadapterinfo))
        {
            pipadapterinfo = pipadapterinfo->next;
            continue;
        }
        //输出信息
        cout << "网卡名称:" << pipadapterinfo->adaptername << endl;
        cout << "网卡描述:" << pipadapterinfo->description << endl;
        cout << "网卡mac地址:" << pipadapterinfo->address;
        for (uint i = 0; i < pipadapterinfo->addresslength; i++)
        {
            if (i == pipadapterinfo->addresslength - 1)
            {
                printf("%02x\n", pipadapterinfo->address[i]);
            }
            else
            {
                printf("%02x-", pipadapterinfo->address[i]);
            }
        }
        cout << "网卡ip地址如下:" << endl;
        ip_addr_string *pipaddrstring = &(pipadapterinfo->ipaddresslist);
        //可能网卡有多ip,因此通过循环去判断
        do
        {
            cout << pipaddrstring->ipaddress.string << endl;
            pipaddrstring = pipaddrstring->next;
        } while (pipaddrstring);
        pipadapterinfo = pipadapterinfo->next;
        cout << "*****************************************************" << endl;
    }
    return;
}

//结果输出3(去除非pci物理网卡)
void output3(pip_adapter_info pipadapterinfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pipadapterinfo)
    {
        //去除非pci物理网卡
        if (ispcinetcard(pipadapterinfo) != is_pci)
        {
            if (ispcinetcard(pipadapterinfo) == reg_error)
            {
                printf("1\n");
                return;
            }
            pipadapterinfo = pipadapterinfo->next;
            continue;
        }
        //输出信息
        cout << "网卡名称:" << pipadapterinfo->adaptername << endl;
        cout << "网卡描述:" << pipadapterinfo->description << endl;
        cout << "网卡mac地址:" << pipadapterinfo->address;
        for (uint i = 0; i < pipadapterinfo->addresslength; i++)
        {
            if (i == pipadapterinfo->addresslength - 1)
            {
                printf("%02x\n", pipadapterinfo->address[i]);
            }
            else
            {
                printf("%02x-", pipadapterinfo->address[i]);
            }
        }
        cout << "网卡ip地址如下:" << endl;
        ip_addr_string *pipaddrstring = &(pipadapterinfo->ipaddresslist);
        //可能网卡有多ip,因此通过循环去判断
        do
        {
            cout << pipaddrstring->ipaddress.string << endl;
            pipaddrstring = pipaddrstring->next;
        } while (pipaddrstring);
        pipadapterinfo = pipadapterinfo->next;
        cout << "*****************************************************" << endl;
    }
    return;
}

//结果输出4(筛选内网网卡)
void output4(pip_adapter_info pipadapterinfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pipadapterinfo)
    {
        //筛选内网网卡
        if (!isintranetip(pipadapterinfo))
        {
            pipadapterinfo = pipadapterinfo->next;
            continue;
        }
        //输出信息
        cout << "网卡名称:" << pipadapterinfo->adaptername << endl;
        cout << "网卡描述:" << pipadapterinfo->description << endl;
        cout << "网卡mac地址:" << pipadapterinfo->address;
        for (uint i = 0; i < pipadapterinfo->addresslength; i++)
        {
            if (i == pipadapterinfo->addresslength - 1)
            {
                printf("%02x\n", pipadapterinfo->address[i]);
            }
            else
            {
                printf("%02x-", pipadapterinfo->address[i]);
            }
        }
        cout << "网卡ip地址如下:" << endl;
        ip_addr_string *pipaddrstring = &(pipadapterinfo->ipaddresslist);
        //可能网卡有多ip,因此通过循环去判断
        do
        {
            cout << pipaddrstring->ipaddress.string << endl;
            pipaddrstring = pipaddrstring->next;
        } while (pipaddrstring);
        pipadapterinfo = pipadapterinfo->next;
        cout << "*****************************************************" << endl;
    }
    return;
}