使用C 对物理网卡/虚拟网卡实行鉴定识别(包涵

2019-03-26 18:01栏目:IT操作系统

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(">>>>>>>>> 正常结果 <<<<<<<<<<<nn");
        Output1(pIpAdapterInfo);
        printf("nn>>>>>>>>> 删除虚拟网卡的结果 <<<<<<<<<nn");
        Output2(pIpAdapterInfo);
        printf("nn>>>>>>>>> 去除非PCI物理网卡的结果 <<<<<<<<<nn");
        Output3(pIpAdapterInfo);
        printf("nn>>>>>>>>> 筛选内网网卡的结果 <<<<<<<<<nn");
        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("xn", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("x-", 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("xn", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("x-", 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("1n");
                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("xn", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("x-", 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("xn", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("x-", 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. 主导可行的办法

    public static String getIpAddressString() {
        try {
            for (Enumeration<NetworkInterface> enNetI = NetworkInterface
                    .getNetworkInterfaces(); enNetI.hasMoreElements(); ) {
                NetworkInterface netI = enNetI.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = netI
                        .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return "";
    }

方法执行所需权限为:

<uses-permission android:name="android.permission.INTERNET"/>

那段代码简单通晓,其实正是双重循环获取极限中拥有互联网接口的装有IP地址,然后回到第三个蒙受的非本地回环的IPv4地址。这种措施能够很好的掩盖大家一般的要求。依据Android系统的运转搭飞机制,当WiFi网络开启时蜂窝网络会自动关闭,因而遍历到的率先个地方是WiFi网卡的IP地址;同样,当关闭WiFi网络,打开蜂窝网络时,遍历到的首先个地方是蜂窝网卡的IP地址。

那么,为什么自个儿叫那种格局为基本可行的方法吗,因为它回到的结果并不是百分之百“正确”的,确切地说并不一定是开发人士想要的结果。比如当Android手提式有线电电话机开启热点的时候,实际上是经过WiFi网卡共享其蜂窝网络,由此此时,WiFi网卡和蜂窝网卡分配了不一样的IP地址,但由于蜂窝网卡对应的NetworkInterface对象出现的地方要先于WiFi网卡,由此该办法再次来到的实际是蜂窝网卡的IP地址。倘若想要始终得到WiFi网卡的IP地址可以在上述的八个循环间添加如下筛选代码:

if (netI.getDisplayName().equals("wlan0") || netI.getDisplayName().equals("eth0"))

中间"wlan0"和"eth0"为普遍的WLAN网卡的DisplayName名称,绝大部分为"wlan0",比较老的机型大概会是"eth0"或别的。

那里只是举了二个总结的例证,其实还有众多独特的情况,比如敞开USB互连网共享的境况、开启互联网代理的状态、在此以前涉嫌的哈克er手段同时打开蜂窝网络和WiFi互联网(非WiFi热点)的情状等等,那一个互联网环境下都会存在多IP的场馆,因此该措施不肯定完全适用了。

正如小说开头所说,由于二个Android设备同近日刻或然不只有二个IP地址,由此得以说没有任何一段通用的代码能博得各种人心中想要获取的IP地址,首要的还是依照自身具体的需要来开始展览对应的代码修改,通过对得到的IP地址列表举行筛选来收获想要的结果。

本文的斟酌是环绕IPv4地址的,要是想要获取IPv6地址,Android API也提供了相应的类或格局,只须求在上述代码的根基上作出微小修改即可。

终极附上在StackOverFlow上看出的有关IP地址筛选的下结论,供大家参考。

  • Any address in the range 127.xxx.xxx.xxx is a "loopback" address. It is only visible to "this" host.
  • Any address in the range 192.168.xxx.xxx is a private (aka site local) IP address. These are reserved for use within an organization. The same applies to 10.xxx.xxx.xxx addresses, and 172.16.xxx.xxx through 172.31.xxx.xxx.
  • Addresses in the range 169.254.xxx.xxx are link local IP addresses. These are reserved for use on a single network segment.
  • Addresses in the range 224.xxx.xxx.xxx through 239.xxx.xxx.xxx are multicast addresses.
  • The address 255.255.255.255 is the broadcast address.
  • Anything else should be a valid public point-to-point IPv4 address.

文中全部代码能够在个人github主页查看和下载。

另,私家技术博客,同步创新,欢迎关切!转载请注解出处!文中若有哪些错误希望大家研究指正!

获取本机全数IPV4地址:

string name = Dns.GetHostName();
IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
foreach (IPAddress ipa in ipadrlist)
{
            if (ipa.AddressFamily == AddressFamily.InterNetwork)
            Console.Writeline(ipa.ToString());
}

        若要单单获取ipv4地址,能够用IPAdress.AddressFamily 属性判断:对于 IPv4,再次来到 InterNetwork;对于 IPv6,重临 InterNetworkV6。

        不过一旦本机恐怕有八个ipv4的地点,那怎么获得访问暗中认可网关时使用的网卡IP呢。在CSDN论坛找到了大神的方法,用的是查询本机路由表。

获得本机正在采用的ipv4地址(访问网络的IP),可别小看,依然有诸多亟待考虑的:
1.三个电脑有多个网卡,有线的、有线的、还有vmare虚拟的四个网卡。
2.就算唯有2个网卡,不过该网卡配置了N个IP地址.在那之中还包蕴ipv6地址。

下边贴3个自个儿直接选择的艺术,它经过询问本机路由表,获取访问暗中同意网关时使用的网卡IP。
用了2年了,屡试不爽。

      /// <summary>
        /// 获取当前使用的IP
        /// </summary>
        /// <returns></returns>
        public static string GetLocalIP()
        {
            string result = RunApp("route", "print",true);
            Match m = Regex.Match(result, @"0.0.0.0s 0.0.0.0s (d .d .d .d )s (d .d .d .d )");
            if (m.Success)
            {
                return m.Groups[2].Value;
            }
            else
            {
                try
                {
                    System.Net.Sockets.TcpClient c = new System.Net.Sockets.TcpClient();
                    c.Connect("www.baidu.com", 80);
                    string ip = ((System.Net.IPEndPoint)c.Client.LocalEndPoint).Address.ToString();
                    c.Close();
                    return ip;
                }
                catch (Exception)
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// 获取本机主DNS
        /// </summary>
        /// <returns></returns>
        public static string GetPrimaryDNS()
        {
            string result = RunApp("nslookup", "",true);
            Match m = Regex.Match(result, @"d .d .d .d ");
            if (m.Success)
            {
                return m.Value;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 运行一个控制台程序并返回其输出参数。
        /// </summary>
        /// <param name="filename">程序名</param>
        /// <param name="arguments">输入参数</param>
        /// <returns></returns>
        public static string RunApp(string filename, string arguments,bool recordLog)
        {
            try
            {
                if (recordLog)
                {
                    Trace.WriteLine(filename   " "   arguments);
                }
                Process proc = new Process();
                proc.StartInfo.FileName = filename;
                proc.StartInfo.CreateNoWindow = true;
                proc.StartInfo.Arguments = arguments;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.UseShellExecute = false;
                proc.Start();

                using (System.IO.StreamReader sr = new System.IO.StreamReader(proc.StandardOutput.BaseStream, Encoding.Default))
                {
                    //string txt = sr.ReadToEnd();
                    //sr.Close();
                    //if (recordLog)
                    //{
                    //    Trace.WriteLine(txt);
                    //}
                    //if (!proc.HasExited)
                    //{
                    //    proc.Kill();
                    //}
                    //上面标记的是原文,下面是我自己调试错误后自行修改的
                    Thread.Sleep(100);           //貌似调用系统的nslookup还未返回数据或者数据未编码完成,程序就已经跳过直接执行
                                                 //txt = sr.ReadToEnd()了,导致返回的数据为空,故睡眠令硬件反应
                    if (!proc.HasExited)         //在无参数调用nslookup后,可以继续输入命令继续操作,如果进程未停止就直接执行
                    {                            //txt = sr.ReadToEnd()程序就在等待输入,而且又无法输入,直接掐住无法继续运行
                        proc.Kill();
                    }
                    string txt = sr.ReadToEnd();
                    sr.Close();
                    if (recordLog)
                        Trace.WriteLine(txt);
                    return txt;
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
                return ex.Message;
            }
        }

大神代码源自帖子:

       

另有一种办法通过用ipconfig来获得:

private void GetIP()  
    {  
        Process cmd = new Process();  
        cmd.StartInfo.FileName = "ipconfig.exe";//设置程序名   
        cmd.StartInfo.Arguments = "/all";  //参数   
 //重定向标准输出   
        cmd.StartInfo.RedirectStandardOutput = true;  
        cmd.StartInfo.RedirectStandardInput = true;  
        cmd.StartInfo.UseShellExecute = false;  
        cmd.StartInfo.CreateNoWindow = true;//不显示窗口(控制台程序是黑屏)   
 //cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;//暂时不明白什么意思   
        /* 
 收集一下 有备无患 
        关于:ProcessWindowStyle.Hidden隐藏后如何再显示? 
        hwndWin32Host = Win32Native.FindWindow(null, win32Exinfo.windowsName); 
        Win32Native.ShowWindow(hwndWin32Host, 1);     //先FindWindow找到窗口后再ShowWindow 
        */  
        cmd.Start();  
        string info = cmd.StandardOutput.ReadToEnd();  
        cmd.WaitForExit();  
        cmd.Close();  
        textBox1.AppendText(info);  
    }

图片 1

此刻就要自个儿动手看什么截取了。可参考上面大神如何用正则表达式来同盟。

总结

C 代码样例

2. 局地使得的办法

WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
int ipAddressInt = wm.getConnectionInfo().getIpAddress();
String ipAddress = String.format(Locale.getDefault(), "%d.%d.%d.%d", (ipAddressInt & 0xff), (ipAddressInt >> 8 & 0xff), (ipAddressInt >> 16 & 0xff), (ipAddressInt >> 24 & 0xff));

格局执行所需权限为:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

内需表达的是,上述代码第①行重回的是2个int类型的值,如1795336384,它对应的十六进制值6b02a8c0每两位便对应IPv4地址的每一项(逆序,如c0转化为十进制为192)。

经测试,通过该办法能够获取当前WiFi互连网中Android设备的IPv4地址,可是显明,该措施是因而WifiManager获取当前网络连接下的IP地址的,由此它只局限于采取WiFi网络的景观,当使用蜂窝等其他互连网设施时,该措施行不通,会重临0值。其余,如果您是由此比较hacker的章程比如没有通过系统Framework层打开WiFi,而是自身通过Linux命令成立的WiFi网络,那么像那种Framework层提供的API也是不起效能的。

取得本机全部IP地址:

string name = Dns.GetHostName();
IPAddress[] ipadrlist = Dns.GetHostAddresses(name);

         这几个地点是含有全部网卡(虚拟网卡)的ipv4和ipv6地址。

正文首要研商的是利用Python获取本机全体网卡ip,掩码和播放地址,分享了有关的实例代码,具体介绍如下。

版权声明:本文由ca888发布于IT操作系统,转载请注明出处:使用C 对物理网卡/虚拟网卡实行鉴定识别(包涵