In the recent issue, it was reported that machine codes are repeated approximately once per 50 different machines in SKGL 2.0.5.3. The reasons under investigation are:
- small hash value allows even more collisions.
- the machine information that is being hashed does not collect all hardware that can be changed.
The first reason is currently in focus, and I have tried to develop a piece of code that now increases the length of the machine code. It would be great if those of you who are able to test this on several machines could do so, and comment(either directly below this thread or here) how frequent the collisions are on different machines! Thank you in advance! 🙂
EDIT 2: This can be done by anyone using Windows:
- Download the software below (no installation required): (or download the exe file directly here) NOTE: In Google Chrome, it might tell that the file is dangerous because it is not commonly downloaded. Please right click and press keep.
- When you launch the software, you will see a 6 digit code in the text box. Please submit it here: https://docs.google.com/forms/d/1aWPKxb9Ejm_QzMciqNvFzPeJVFrNgRxaTHfM4ROUqnc/viewform.
- Thank you for your contribution! 🙂
EDIT: You can also write the machine code you get on your own computer and post it below this thread. (hardware info using dxdiag would be awesome, but the machine code is more important at this point)
public class AnalysisOfMachineCode { [TestMethod] public void test() { Debug.WriteLine(getMachineCode()); } [SecuritySafeCritical] public static int getMachineCode() { ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_Processor"); string collectedInfo = ""; // here we will put the informa foreach (ManagementObject share in searcher.Get()) { // first of all, the processorid collectedInfo += share.GetPropertyValue("ProcessorId"); } searcher.Query = new ObjectQuery("select * from Win32_BIOS"); foreach (ManagementObject share in searcher.Get()) { //then, the serial number of BIOS collectedInfo += share.GetPropertyValue("SerialNumber"); } searcher.Query = new ObjectQuery("select * from Win32_BaseBoard"); foreach (ManagementObject share in searcher.Get()) { //finally, the serial number of motherboard collectedInfo += share.GetPropertyValue("SerialNumber"); } // patch luca bernardini if (string.IsNullOrEmpty(collectedInfo) | collectedInfo == "00" | collectedInfo.Length <= 3) { collectedInfo += getHddSerialNumber(); } return getEightByteHash(collectedInfo, 1000000); } [SecuritySafeCritical] public static string getHddSerialNumber() { // --- Win32 Disk ManagementObjectSearcher searcher = new ManagementObjectSearcher("\\root\\cimv2", "select * from Win32_DiskPartition WHERE BootPartition=True"); uint diskIndex = 999; foreach (ManagementObject partition in searcher.Get()) { diskIndex = Convert.ToUInt32(partition.GetPropertyValue("Index")); break; // TODO: might not be correct. Was : Exit For } // I haven't found the bootable partition. Fail. if (diskIndex == 999) return string.Empty; // --- Win32 Disk Drive searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive where Index = " + diskIndex.ToString()); string deviceName = ""; foreach (ManagementObject wmi_HD in searcher.Get()) { deviceName = wmi_HD.GetPropertyValue("Name").ToString(); break; // TODO: might not be correct. Was : Exit For } // I haven't found the disk drive. Fail if (string.IsNullOrEmpty(deviceName.Trim())) return string.Empty; // -- Some problems in query parsing with backslash. Using like operator if (deviceName.StartsWith("\\\\.\\")) { deviceName = deviceName.Replace("\\\\.\\", "%"); } // --- Physical Media searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia WHERE Tag like '" + deviceName + "'"); string serial = string.Empty; foreach (ManagementObject wmi_HD in searcher.Get()) { serial = wmi_HD.GetPropertyValue("SerialNumber").ToString(); break; // TODO: might not be correct. Was : Exit For } return serial; } public static int getEightByteHash(string s, int MUST_BE_LESS_THAN = 1000000000) { //This function generates a eight byte hash //The length of the result might be changed to any length //just set the amount of zeroes in MUST_BE_LESS_THAN //to any length you want uint hash = 0; foreach (byte b in System.Text.Encoding.Unicode.GetBytes(s)) { hash += b; hash += (hash << 10); hash ^= (hash >> 6); } hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); int result = (int)(hash % MUST_BE_LESS_THAN); int check = MUST_BE_LESS_THAN / result; if (check > 1) { result *= check; } return result; } }
line 56: would be
diskIndex = Convert.ToUInt32(partition.GetPropertyValue(“DiskIndex”));
Thank you for your comment and feedback!
Hi.
I ‘m getting in this problem because old machine code is almost useless. We’ are getting the same machine code from three different machines.
I’ll post new and old machine codes.
Reply to: https://skgl.codeplex.com/workitem/2246
Uldis,
Thank you for all this data! I am very sorry that I am replying so late, I have been quite busy the last few weeks. Let me look into this this week.
/Artem
Hi – I investigated problem and posted info under
Cannot post this link: https://skgl.codeplex.com/workitem/2246
Hi Uldis,
I’ve now replied to your question here: https://skgl.codeplex.com/workitem/2246.
I hope this helps!
/Artem
I would like to know the results of your survey. Have you got any stats for us?
Thank you.
Based on all hash codes, no duplicates were observed. In conclusion, it is perfectly fine to keep the current length (i.e. 8 digits), but instead add the necessary to the string that is being hashed. Please see the http://skgl.codeplex.com/SourceControl/list/changesets.
The thread were the machine code function is being discussed: http://skgl.codeplex.com/workitem/2246.