• 物理网卡地址


    以下是获取网卡 MAC地址的方法.

    /// <summary>
      /// 以下是获取网卡 MAC地址的方法.
      /// 只能获取第一块
    
      /// </summary>
      /// <returns></returns>
      public static string GetMacAddress()
      {
      ManagementClass adapters = new ManagementClass("Win32_NetworkAdapterConfiguration");
      string MACAddress = "unknown";
      foreach (ManagementObject adapter in adapters.GetInstances())
      {
      if((bool)adapter["IPEnabled"] == true)
      {
      MACAddress = adapter.Properties["MACAddress"].Value.ToString();
      break;
      }
      }
      return MACAddress;
      }
    
    
    
    那就在客戶端的程序裡寫一個然發送回來保存在數據庫裡。
     public string GetNetCard()
      {
      string str = "";
      ManagementClass mcMAC = new ManagementClass("Win32_NetworkAdapterConfiguration");
      ManagementObjectCollection mocMAC = mcMAC.GetInstances();
      foreach (ManagementObject m in mocMAC)
      {
      if ((bool)m["IPEnabled"])
      {
      str = m["MacAddress"].ToString();
      break;
      }
      }
      return str;
      }
    
    
    
    
    
    
    
    
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Configuration;
    using System.Runtime.InteropServices;
    using System.Management;
    
    namespace POS
    {
      class GetVol
      {
      [DllImport("kernel32.dll")]
      private static extern int GetVolumeInformation(
      string lpRootPathName,
      string lpVolumeNameBuffer,
      int nVolumeNameSize,
      ref int lpVolumeSerialNumber,
      int lpMaximumComponentLength,
      int lpFileSystemFlags,
      string lpFileSystemNameBuffer,
      int nFileSystemNameSize
      );
    
      public string GetVolOf(string drvID)
      {
      const int MAX_FILENAME_LEN = 256;
      int retVal = 0;
      int a = 0;
      int b = 0;
      string str1 = null;
      string str2 = null;
      int i = GetVolumeInformation(
      drvID + @":",
      str1,
      MAX_FILENAME_LEN,
      ref retVal,
      a,
      b,
      str2,
      MAX_FILENAME_LEN
      );
    
      return retVal.ToString("x");
      }
    
      public string GetNetCard()
      {
      string str = "";
      ManagementClass mcMAC = new ManagementClass("Win32_NetworkAdapterConfiguration");
      ManagementObjectCollection mocMAC = mcMAC.GetInstances();
      foreach (ManagementObject m in mocMAC)
      {
      if ((bool)m["IPEnabled"])
      {
      str = m["MacAddress"].ToString();
      break;
      }
      }
      return str;
      }
      }
    }
    View Code

    c#如何给.NET软件添加注册码

    本文宗旨在于提出一种给软件添加注册码的方法。至于所提出的方法是否有效,是否能够经得起一些逆向高手的破解,还得经过验证。我只是提出我个人的看法。
    一、目标。
        目标很明确,就是根据需要注册软件的个人信息,产生注册码。并且软件本身必须可以校验该注册码是否有效。并且能够防止别人逆向算出校验算法,产生注册机;能够防止别人用暴力破解方法,直接修改软件执行代码,绕过注册。
       
    二、方法论述
        要做到以上的目标,有两个方面特别重要。一是,注册码产生算法的选择;二是,要使软件具有自身校验机制,防止可执行程序别篡改。下面我们分别论述这两点。
    1. 注册码产生算法的选择
       现在很多软件都存在注册机,很大原因是因为软件本身的注册码产生算法太过于简单。破解人员很容易从反汇编代码中抠出注册算法,并且能够很容易的还原成C代码。这些搞破解的算不上大师,但也可以算得上牛人了。我也曾经了解过相关的知识,看懂反汇编的代码不难,难的是在大量的汇编代码中找到彼此的调用关系,并且能够逆向的写出对应的代码;当然有些懒人直接抠出其中的汇编代码,不用理解详细的执行过程就能达到破解的目的。
       言归正传,不管别人多么NB,他至少要反汇编,至少看的是汇编代码。而如果我们的算法足够强大,他们也就玩完了。纵观如今标准的加密算法,无非就是对称加密和非对称加密。我们也不用去自创算法了,别做些吃力不讨好的事,自己设计的算法,安全性远远比不上现在常用的算法。我先简单列举出常用的算法,并说明为什么要选择我们所要的算法。
       a. 对称加密算法现在流行的有DES,AES两种,DES算法广泛的用在银行行业,AES出现的比较晚,但是安全性比DES好。所谓的对称就是只有一个密钥,加密和解密使用同一个密码,所以称为对称加密。如果我们用它在产生注册码,那么我们的软件中必须保存这个密钥。不管密钥在哪里,总是要存在在一个地方,而我们又没有办法去保证这个密钥的安全性。原因很简单,破解者只要跟下代码,就知道我们从哪里读出来这个密钥。
       b. 非对称加密有RSA,和椭圆曲线等,最流行的是RSA。虽然椭圆曲线效率和安全性比RSA好,但比较复杂,我至今没看明白原理,呵呵。所谓的非对称,是因为它有两个密钥,一个称为公钥,一个称为私钥。公钥是可以对外发布的,而私钥是自己保存的。用公钥加密,必须用私钥解密,反之,用私钥加密必须用公钥解密。所以,我们知道,我们可以在软件中保存公钥的内容,这个是可以公开的(当然,把它隐藏在软件内部是必要的,总之可以造成破解的难度的事情我们都可以去尝试)。然后,私钥我们可以自己留着。别人拿不到私钥,根本计算不出注册码来。
      
    2. 至此,我们知道我们可以使用RSA算法了,而且可以保证软件的安全。至少无法产生注册机,因为别人没有私钥。但是具体怎么做,我们可以按照下面的流程。
       a. 注册码产生过程:
          注册信息(包括用户名等信息)---> RSA私钥加密 ---> 注册码。
         
       b. 软件验证注册码过程:
          注册码 ---> RSA公钥解密 ---> 注册信息。
      
    3. 解决了第一个目标,我们还是很难防止别人直接篡改2进制的可执行文件,从而绕过注册码的校验。但是,方法总是有的。为了解决这个问题,我想到了一个方法:软件的自我校验。具体的做法是这样的:
       a. 我们为自身的软件产生校验值,这里要使用摘要算法。最常用的摘要算法是MD5,相信大家都听过,这里也就不再详述,我们仅仅需要在软件的执行时,读取可执行程序(在Windows下,自身的执行文件是可读的,但是如果自己要改写自己,那就没办法了)并计算校验值。
       b. 接着,我们可以判断校验值是否正确,如果不正确,我们软件可以直接自杀。
      
       但是这里有个问题,我们怎么在软件中保存正确的校验值呢?不可能保存在文件或者注册表中,这样早晚会被知道的。别人可以直接修改该校验值使之与错误的校验值相同,从而骗过软件的校验。这里有个方法:回归到(第1、2点)中描述的方法。如何回归?我们接着说。
    
    4. 保存软件的校验值:让校验值融入注册码。我们修改(第2点)的过程如下:
       a. 注册码产生过程:
          注册信息(包括用户名等信息)+ 软件校验值 ---> RSA私钥加密 ---> 注册码。
      
       b. 软件验证注册码过程:
          注册码 ---> RSA公钥解密 ---> 注册信息 + 软件校验值。
       这样子,我们就可以这样判断软件是否已经成功注册。首先根据上面步骤,算出注册信息和软件校验值,然后把这两者和当前的用户信息,和计算出的校验值做比较,如果都匹配,说明软件已经被成功的注册。
      
    5. 尝试破解。
       如果你知道了详细的过程,如何破解该软件?首先我们知道,已经无法写出注册机来了。唯一的办法是暴利破解,但是暴利破解,软件又加了自我校验。但是,百密总有一疏,暴利破解还是可以达到的。我们先回顾一下,如果我们按照上述的办法添加了注册码校验。那么我们的代码差不多是这么写的:
      
       int RSA_Check( char * sn ){
           该函数计算软件的校验值,根据注册码sn解密出校验值和用户信息,然后比较,返回是否校验通过。
       }
       ....
       在软件的启动时,我们调用上述的函数。
       if( RSA_Check( sn ) ){     <--------------------------①
           在这里,如果校验失败,那就直接exit(0)吧,呵呵~
       }
      
       但是致命弱点就在上述的①位置。因为①位置的汇编差不多是这样的:
       je xxxxx    
       ....
       ....
      
       仅仅是一条跳转语句,那么,破解人员直接将其改成jne或者别的jmp指令就完事了,我们的努力就全废了。既然如此,我们代码绝不能写成这样,或者我们的方法不该如此简单。至少,我们可以这么做:
       1. 不要把校验算法写成一个统一的接口。
       2. 不要仅仅在一个地方做判断。这点其实很简单也很有效,如果你愿意,你可以在软件中对效率要求不高的地方多加几个判断,这对破解人来说是相当痛苦的,至少他无法同时查找到所有的关键位置。只要有一个地方没改成功,那么我们的自我校验就起作用,那么我们就有权利执行后续的动作了。比如,直接删掉本身的程序(当然,这里必须关闭自己,然后调用另一个进程来删除软件)等等。
       3. 更“贱”的方法是,起一个附加的进程,和主进程互相监视,互相校验。如果校验到对方注册异常了,那就杀掉对方,干掉对方的可执行程序。听起来很贱,但是不是有用,俺也不知道。
       4. 如果要防止一个注册码到处使用的情况(中国人都是互帮互助的,呵呵),可以在注册信息中添加目标机器的信息,加入到注册信息中。
       4. 等等的这些方法,就很多了,大家可以自由发挥。
      
    三. 总结
       经过上述的论述,我觉得没有绝对的安全,有时如果你的软件不想被破解,那么您就只能诅咒那些不道德的人了。但是我们可以让他们更加痛苦,至少菜鸟是无法随随便便搞破坏的。在中国,写个软就开源,免费吧,别指望拿它来养家糊口了。
      
    四. 附件
        RSA加解密实现代码
     
    View Code

    C#获取本机和其它计算机物理网卡地址(MAC)

    验证计算机MAC地址进行软件授权是一种通用的方法,C#可以轻松获取计算机的MAC地址,本文采用实际的源代码讲述了两种获取网卡的方式,第一种 方法使用ManagementClass类,只能获取本机的计算机网卡物理地址,第二种方法使用Iphlpapi.dll的SendARP方法,可以获取 本机和其它计算机的MAC地址。
        方法1:使用ManagementClass类
              示例: 
    /// <summary>
    /// 获取网卡物理地址
    /// </summary>
    /// <returns></returns>
    publicstaticstringgetMacAddr_Local()
    {
        stringmadAddr =null;
        ManagementClass mc =newManagementClass("Win32_NetworkAdapterConfiguration");
        ManagementObjectCollection moc2 = mc.GetInstances();
        foreach(ManagementObject moinmoc2)
        {
            if(Convert.ToBoolean(mo["IPEnabled"]) ==true)
            {
                madAddr = mo["MacAddress"].ToString();
                madAddr = madAddr.Replace(':','-');
            }
            mo.Dispose();
        }
        returnmadAddr;
    }
    说明:   1.需要给项目增加引用:System.Management,如图:
        2.在程序开始添加包引入语句:using System.Management;
    
        3.本方案只能获取本机的MAC地址;
        方法2:使用SendARP类
              示例: 
    //下面一种方法可以获取远程的MAC地址
    [DllImport("Iphlpapi.dll")]
    staticexternintSendARP(Int32 DestIP, Int32 SrcIP,refInt64 MacAddr,refInt32 PhyAddrLen);
    [DllImport("Ws2_32.dll")]
    staticexternInt32 inet_addr(stringipaddr);       
    /// <summary>
    /// SendArp获取MAC地址
    /// </summary>
    /// <param name="RemoteIP">目标机器的IP地址如(192.168.1.1)</param>
    /// <returns>目标机器的mac 地址</returns>
    publicstaticstringgetMacAddr_Remote(stringRemoteIP)
    {
        StringBuilder macAddress =newStringBuilder();
        try
        {
            Int32 remote = inet_addr(RemoteIP);
            Int64 macInfo =newInt64();
            Int32 length = 6;
            SendARP(remote, 0,refmacInfo,reflength);
            stringtemp = Convert.ToString(macInfo, 16).PadLeft(12,'0').ToUpper();
            intx = 12;
            for(inti = 0; i < 6; i++)
            {
                if(i == 5)
                {
                    macAddress.Append(temp.Substring(x - 2, 2));
                }
                else
                {
                    macAddress.Append(temp.Substring(x - 2, 2) +"-");
                }
                x -= 2;
            }
            returnmacAddress.ToString();
        }
        catch
        {
            returnmacAddress.ToString();
        }
    }
    说明:    1.在程序开始添加包引入语句:using System.Runtime.InteropServices;
        2.该方法可以获取远程计算机的MAC地址;
     
    View Code
  • 相关阅读:
    属性序列化自定义与字母表排序-JSON框架Jackson精解第3篇
    URL及日期等特殊数据格式处理-JSON框架Jackson精解第2篇
    JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法
    开源项目-跨项目及操作系统的通用代码生成器,解放您的双手
    图解并发与并行-分别从CPU和线程的角度理解
    8成以上的java线程状态图都画错了,看看这个-图解java并发第二篇
    面霸告诉你这些技术面试的非技术性经验,让你的面试成功率显著提升
    List集合对象去重及按属性去重的8种方法-java基础总结系列第六篇
    图解进程线程、互斥锁与信号量-看完不懂你来打我
    总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
  • 原文地址:https://www.cnblogs.com/blogpro/p/11462965.html
Copyright © 2020-2023  润新知