web-dev-qa-db-ja.com

一意のマシンIDを取得

コピーせずにソフトウェアを配布するために、コンピューターのプロセッサシリアル番号のような一意の変更不可能なマシンIDを取得したい。

Windowsをフォーマットして再インストールした後、すべてが変更されているプロセッサのシリアル番号とハードディスクのシリアル番号を試してみました。

コンピューターの変更不可能なシリアル番号を取得する方法はありますか?

34
ush

WMI Code creator を使用できます。 「キー」(processorid、mac、およびソフトウェア生成キー)の組み合わせを使用できると思います。

using System.Management;
using System.Windows.Forms;

try
{
     ManagementObjectSearcher searcher = 
         new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Processor"); 

     foreach (ManagementObject queryObj in searcher.Get())
     {
         Console.WriteLine("-----------------------------------");
         Console.WriteLine("Win32_Processor instance");
         Console.WriteLine("-----------------------------------");
         Console.WriteLine("Architecture: {0}", queryObj["Architecture"]);
         Console.WriteLine("Caption: {0}", queryObj["Caption"]);
         Console.WriteLine("Family: {0}", queryObj["Family"]);
         Console.WriteLine("ProcessorId: {0}", queryObj["ProcessorId"]);
     }
}
catch (ManagementException e)
{
    MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}

Win32_Processor

WMIを使用したC#でのハードウェア識別子の取得 by Peter Bromberg

15
PRR

一意のIDが必要な場合は、最初に一意のの定義を決定する必要があります。コピー防止メカニズムに使用する場合は、単純なものを使用します。これは、誰かが本当にあなたのソフトウェアを使用したい場合、十分な時間とスキルがあれば、あなたの保護を破る方法を見つけるからです。一意のハードウェアIDの場合は、仮想マシンについて考えるだけで、誰かがソフトウェアを改ざんできるようになりすましができることがわかります。

PCから取得できるものはほとんどなく、PCをその寿命全体にわたって一意と見なすことはできません。 (ハードウェアの変更では、ある時点でIDを再生成する必要があります。)そのような何かが必要な場合は、顧客に送信できる認証SBドングルを使用して調査する必要があります。

取得が難しくない一意の識別子が必要な場合は、MACアドレス(信頼できない)、OSシリアル番号、またはドメインとユーザー名を取得できますが、それらはすべて偽造の影響を受けやすくなっています。ただし、許可されていない人をロックアウトすることが主な目的の場合、インストール、登録、またはPCから別のPCへの移動が困難な場合は誰もソフトウェアを使用したくないため、何も販売しません。マシンごとのライセンス供与の一部。 (これは非常に頻繁に起こるでしょう。)

最初のステップとして、簡単にします。ターゲットグループで簡単になりすましにくいものを使用します。 (たとえば、ドメインやユーザー名は、企業の顧客が簡単になりすますことはできません。PCはポリシーを実装する大規模な環境で実行されているためです。など).

それらをロックアウトすることもできますが、それは彼らがあなたのソフトウェアを購入するという意味ではありません。彼らはもはやそれを使用しません。あなたが考慮しなければならないのは、あなたのプログラムを使用するのが非常に複雑になったので、何人の潜在的な顧客が支払わないか、支払わないかです。

14
Oliver

MACアドレスを使用することは避けたいです。一部のハードウェアでは、再起動時にMACアドレスが変更される場合があります。調査のかなり早い段階で、それに頼らないことを学びました。

記事をご覧ください ソフトウェア保護とライセンスの開発 著作権侵害を減らすためにアプリを設計および実装する方法に関するいくつかの指針があります。

義務的な免責事項とプラグ:私が共同設立した会社は OffByZero Cobaltライセンスソリューション を作成します。したがって、ライセンスをアウトソーシングし、コアコンピテンシーに集中することをお勧めすることを聞いても、おそらく驚くことではないでしょう。

12
Duncan Bayne

この記事 をご覧ください。それは非常に網羅的であり、さまざまなハードウェア情報を抽出する方法を見つけるでしょう。

記事 からの引用:

ハードウェア情報を取得するには、ManagementObjectSearcherクラスのオブジェクトを作成する必要があります。

using System.Management;
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + Key);
foreach (ManagementObject share in searcher.Get()) {
    // Some Codes ...
}

上記のコードのキーは、適切なデータに置き換えられる変数です。たとえば、CPUの情報を取得するには、キーをWin32_Processorに置き換える必要があります。

4

はい、物理アドレス、一意のドライブID、ハードドライブID(ボリュームシリアル)、CPU ID、BIOS IDの組み合わせのコードを取得できます。例( 完全な例 ):

//Main physical hard drive ID
    private static string diskId()
    {
        return identifier("Win32_DiskDrive", "Model")
        + identifier("Win32_DiskDrive", "Manufacturer")
        + identifier("Win32_DiskDrive", "Signature")
        + identifier("Win32_DiskDrive", "TotalHeads");
    }
    //Motherboard ID
    private static string baseId()
    {
        return identifier("Win32_BaseBoard", "Model")
        + identifier("Win32_BaseBoard", "Manufacturer")
        + identifier("Win32_BaseBoard", "Name")
        + identifier("Win32_BaseBoard", "SerialNumber");
    }
4
Raj kumar

編集:私はちょうどあなたがC#で意味を見た。アンマネージコードのより良い方法を次に示します。

ManagementClass oMClass = new ManagementClass ("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection colMObj = oMCLass.GetInstances();
foreach(ManagementObject objMO in colMObj)
    Console.WriteLine(objMO["MacAddress"].ToString());
3
Blindy

たぶん最も簡単な方法です。 DeviceId Nugetパッケージを取得する

そして、それを次のように使用します

string deviceId = new DeviceIdBuilder()
.AddMachineName()
.AddMacAddress()
.AddProcessorId()
.AddMotherboardSerialNumber()
.ToString();

IDの生成に使用される情報をパーソナライズできます

Githubプロジェクト

3
Daniel

(最初の?)ネットワークアダプターのMACアドレスを使用するというBlindyの提案を2回目にしました。はい、MACアドレスはスプーフィングされる可能性がありますが、これには副作用があり(同じネットワーク内に同じMACアドレスを持つ2台のPCは必要ありません)、それは「あなたの平均的な海賊」がソフトウェアを使用します。ソフトウェア著作権侵害に対する100%の解決策がないことを考えると、MACアドレスはIMOという良い妥協案です。

ただし、ユーザーがネットワークカードを追加、交換、または削除すると(または古いPCを完全に交換すると)アドレスが変更されることに注意してください。

2
Heinzi

MACを使用するべきではありません。これは悪い方法です。一部のOSは毎日それを変更するだけだからです。私の経験:Tools.CpuID.ProcessorId()+ volumeSerial;

string volumeSerial = "";
    try {
        ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""C:""");
        dsk.Get();
        volumeSerial = dsk["VolumeSerialNumber"].ToString();
    } catch {
        try {
            ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""D:""");
            dsk.Get();
            volumeSerial = dsk["VolumeSerialNumber"].ToString();
        } catch { File.WriteAllText("disk.mising","need C or D"); Environment.Exit(0); }
    }

public class CpuID
    {
        [DllImport("user32", EntryPoint = "CallWindowProcW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
        private static extern IntPtr CallWindowProcW([In] byte[] bytes, IntPtr hWnd, int msg, [In, Out] byte[] wParam, IntPtr lParam);

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern bool VirtualProtect([In] byte[] bytes, IntPtr size, int newProtect, out int oldProtect);

        const int PAGE_EXECUTE_READWRITE = 0x40;



        public static string ProcessorId()
        {
            byte[] sn = new byte[8];

            if (!ExecuteCode(ref sn))
                return "ND";

            return string.Format("{0}{1}", BitConverter.ToUInt32(sn, 4).ToString("X8"), BitConverter.ToUInt32(sn, 0).ToString("X8"));
        }

        private static bool ExecuteCode(ref byte[] result)
    {
        int num;

        /* The opcodes below implement a C function with the signature:
         * __stdcall CpuIdWindowProc(hWnd, Msg, wParam, lParam);
         * with wParam interpreted as an 8 byte unsigned character buffer.
         * */

        byte[] code_x86 = new byte[] {
            0x55,                      /* Push ebp */
            0x89, 0xe5,                /* mov  ebp, esp */
            0x57,                      /* Push edi */
            0x8b, 0x7d, 0x10,          /* mov  edi, [ebp+0x10] */
            0x6a, 0x01,                /* Push 0x1 */
            0x58,                      /* pop  eax */
            0x53,                      /* Push ebx */
            0x0f, 0xa2,                /* cpuid    */
            0x89, 0x07,                /* mov  [edi], eax */
            0x89, 0x57, 0x04,          /* mov  [edi+0x4], edx */
            0x5b,                      /* pop  ebx */
            0x5f,                      /* pop  edi */
            0x89, 0xec,                /* mov  esp, ebp */
            0x5d,                      /* pop  ebp */
            0xc2, 0x10, 0x00,          /* ret  0x10 */
        };
        byte[] code_x64 = new byte[] {
            0x53,                                     /* Push rbx */
            0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, /* mov rax, 0x1 */
            0x0f, 0xa2,                               /* cpuid */
            0x41, 0x89, 0x00,                         /* mov [r8], eax */
            0x41, 0x89, 0x50, 0x04,                   /* mov [r8+0x4], edx */
            0x5b,                                     /* pop rbx */
            0xc3,                                     /* ret */
        };

        byte[] code;

        if (IsX64Process())
            code = code_x64;
        else 
            code = code_x86;

        IntPtr ptr = new IntPtr(code.Length);

        if (!VirtualProtect(code, ptr, PAGE_EXECUTE_READWRITE, out num))
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

        ptr = new IntPtr(result.Length);

        try {
            return (CallWindowProcW(code, IntPtr.Zero, 0, result, ptr) != IntPtr.Zero);
        } catch { System.Windows.Forms.MessageBox.Show("Память повреждена"); return false; }
    }

        private static bool IsX64Process()
        {
            return IntPtr.Size == 8;
        }

    }
2
Nik Shev

次の siteSystem.Managementを使用して同じことを達成しますが、コンソールアプリケーションでは非常に洗練された方法です

0
Sujoy

私が知っているこれには2つの方法があります:

  1. システムのプロセッサIDを取得します。

    public string getCPUId()
    {
        string cpuInfo = string.Empty;
        ManagementClass mc = new ManagementClass("win32_processor");
        ManagementObjectCollection moc = mc.GetInstances();
    
        foreach (ManagementObject mo in moc)
        {
            if (cpuInfo == "")
            {
                //Get only the first CPU's ID
                cpuInfo = mo.Properties["processorID"].Value.ToString();
                break;
            }
        }
        return cpuInfo;
    }
    
  2. システムのUUIDを取得します。

    public string getUUID()
    {
            Process process = new Process();
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.FileName = "CMD.exe";
            startInfo.Arguments = "/C wmic csproduct get UUID";
            process.StartInfo = startInfo;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();
            process.WaitForExit();
            string output = process.StandardOutput.ReadToEnd();
            return output;
    }
    
0