web-dev-qa-db-fra.com

obtenir un identifiant unique de machine

Je souhaite obtenir un identifiant d'ordinateur unique et non modifiable, tel que le numéro de série du processeur de l'ordinateur, permettant de distribuer un logiciel sans copie.

J'ai essayé avec le numéro de série du processeur et le numéro de série du disque dur qui changent tous après le formatage et la réinstallation de Windows. 

Avez-vous une idée de la façon dont je peux obtenir un numéro de série non modifiable d'un ordinateur?

31
ush

Vous pouvez utiliser Créateur de code WMI . Je suppose que vous pouvez avoir une combinaison de "clés" (processeurs, mac et clé générée par logiciel). 

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

Récupération d'identifiants matériels en C # avec WMI par Peter Bromberg

15
PRR

Si vous avez besoin d'un identifiant unique , vous devez d'abord définir votre définition de unique . Si vous voulez/avez l'intention de l'utiliser pour un mécanisme de protection contre la copie, utilisez quelque chose de simple. En effet, si quelqu'un veut vraiment utiliser votre logiciel, il trouvera le moyen de briser votre protection, s'il dispose de suffisamment de temps et de compétences. Dans le cas d'un identifiant matériel unique, pensez aux machines virtuelles et vous verrez qu'il est possible d'usurper n'importe quoi pour que quelqu'un puisse altérer votre logiciel.

Il n’ya pas grand-chose que vous puissiez prendre sur un PC et considérez-le comme unique pendant toute sa durée de vie. (Les modifications matérielles nécessiteront probablement de régénérer l'ID à un moment donné.) Si vous avez besoin de quelque chose comme ça, vous devez utiliser une authentification clé USB que vous pouvez envoyer à vos clients.

Si vous avez simplement besoin d’un identifiant unique qui n’est pas aussi difficile à obtenir, vous pouvez utiliser l’adresse MAC (non fiable), le numéro de série du système d’exploitation ou le nom de domaine et d’utilisateur, mais ils sont tous susceptibles d’être falsifiés. Cependant, si votre objectif principal est de verrouiller des personnes non autorisées, vous ne vendez rien car personne ne voudra utiliser votre logiciel s'il est difficile à installer, enregistrer ou passer d'un PC à un autre, bien que la dernière considération soit: partie intégrante de la licence par machine. (Cela va probablement arriver assez souvent.)

Dans un premier temps, facilitez-vous la vie: utilisez quelque chose de simple et qui n'est pas facile à usurper dans votre groupe cible. (Par exemple, les entreprises et les clients ne peuvent pas usurper les noms de domaines et d’utilisateurs, car leurs ordinateurs fonctionnent dans un environnement plus vaste, mettant en œuvre des stratégies, etc.) Oubliez simplement les autres noms jusqu’à ce que vous ayez cela.

Peut-être pouvez-vous les verrouiller, mais cela ne signifie pas qu'ils vont acheter votre logiciel; ils ne veulent tout simplement plus l'utiliser. Ce que vous devez considérer est le nombre de clients potentiels qui ne seront pas ou ne voudront pas payer parce que vous avez compliqué l'utilisation de votre programme.

14
Oliver

Je resterais bien loin d'utiliser les adresses MAC. Sur certains matériels, l’adresse MAC peut changer lorsque vous redémarrez. Au cours de nos recherches, nous avons appris assez tôt à ne pas nous en remettre.

Consultez l'article Développement pour la protection logicielle et la gestion de licences , qui contient des indications sur la manière de concevoir et de mettre en œuvre des applications pour réduire le piratage.

Clause de non-responsabilité obligatoire & plug: la société que j'ai co-fondée produit la solution de licence OffByZero Cobalt . Vous ne serez donc probablement pas surpris d'apprendre que je vous recommande d'externaliser vos licences et de vous concentrer sur vos compétences essentielles.

11
Duncan Bayne

Découvrez cet article . Il est très exhaustif et vous trouverez comment extraire diverses informations sur le matériel.

Citation de article :

Pour obtenir des informations sur le matériel, vous devez créer un objet de la classe ManagementObjectSearcher.

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

La clé du code ci-dessus est une variable qui est remplacée par les données appropriées. Par exemple, pour obtenir les informations de la CPU, vous devez remplacer la clé par Win32_Processor.

5
Laurent Etiemble

edit: Je viens de voir que vous vouliez dire en c #. Voici un meilleur moyen d'utiliser du code non géré:

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

J'appuie la suggestion de Blindy d'utiliser l'adresse MAC de la (première?) Carte réseau. Oui, l'adresse MAC peut être usurpée, mais cela a des effets secondaires (vous ne voulez pas deux PC avec la même adresse MAC dans le même réseau), et c'est quelque chose que "votre pirate moyen" ne fera pas juste pour pouvoir utiliser votre logiciel. Considérant qu'il n'y a pas de solution à 100% contre le piratage de logiciels, l'adresse MAC est un bon compromis, IMO.

Notez cependant que l'adresse changera lorsque l'utilisateur ajoutera, remplacera ou supprimera une carte réseau (ou remplacera complètement son ancien PC). Soyez donc prêt à aider vos clients et à leur donner une nouvelle clé lorsqu'ils modifieront leur configuration matérielle.

2
Heinzi

Oui, nous pourrions obtenir un code combinant adresse physique, identifiant de lecteur unique, identifiant de disque dur (série), identifiant de processeur et identifiant de BIOS. Exemple ( Exemple complet ):

//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");
    }
2
Raj kumar

Vous ne devriez pas utiliser MAC, c'est mauvais. Parce que certains OS le changent tous les jours. Mon expérience: Tools.CpuID.Processor Id () + 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

Je sais qu'il y a deux manières possibles de le faire:

  1. Obtenez l'identifiant du processeur du système:

    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. Obtenir l'UUID du système:

    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
Siddhant Jaiswal