I’m dealin’ with degenerate animals out here. But the bosses, what do they give a fuck? They’re sittin’ on their asses drinkin’ Anisette.
Nicky Santoro – Casino
Where I work we are developing a cross-platform application (Linux,Windows) and the bosses thought although the application is free the users must register to a website and then receive an activation code.If you move the application to another computer the application must not work.
The quote from the begining of the article is my opinion on what bosses do.They have tons of ideas to make your life harder
.
So that’s it I got to make this tweak until Monday. I like doing things the hard-way I mean that are millions of options you can have to solve this problem but for a long time I wished on an unit to generate me a hardware id that is unique for every machine and cross platform.
I did a little google research to find something already made because I am lazy but I didn’t came up with nothing just the information that the hardware ID that is not easily spoofed is the hard drive’s serial number.
Do not confuse hard drive serial number with the partition’s serial witch Windows allocates when it formats the partition.That is very easy to forge.I wrote a tool for forging that some time a go ( ChangeSerial ).
I decided to write my own unit for getting the HardwareID. I googled on how you can do it under Windows and I saw the easiest way is using WMI (Windows Management Instrumentation). For those who don’t know what WMI is , picture WMI like a database that stores crucial information on your computer that is accessible from any modern programming language.For you Delphi fans a guy named Rodrigo Ruz made our life a lot simpler by writing WMI Delphi Code Creator . The application has a very cool interface and besides that working with WMI becomse a pice of cake.
So I used WMI Delphi Code Creator , and wrote a very simple function to get my hard-drive serial
| Delphi | | copy code | | ? |
| 01 | function getSerial(): String; |
| 02 | const |
| 03 | WbemUser =''; |
| 04 | WbemPassword =''; |
| 05 | WbemComputer ='localhost'; |
| 06 | wbemFlagForwardOnly = $00000020; |
| 07 | var |
| 08 | FSWbemLocator : OLEVariant; |
| 09 | FWMIService : OLEVariant; |
| 10 | FWbemObjectSet: OLEVariant; |
| 11 | FWbemObject : Variant; |
| 12 | oEnum : IEnumvariant; |
| 13 | begin |
| 14 | Result := 'ERR_DISKERROR'; |
| 15 | FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); |
| 16 | FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword); |
| 17 | FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_PhysicalMedia','WQL',wbemFlagForwardOnly); |
| 18 | oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant; |
| 19 | if oEnum.Next(1, FWbemObject, nil) = 0 then |
| 20 | begin |
| 21 | Result := Format('%s',[String(FWbemObject.SerialNumber)]); |
| 22 | FWbemObject:=Unassigned; |
| 23 | end; |
| 24 | end |
Pretty cool I must say.
Than it came the hard part getting the serial with linux. I love linux it’s a love that just blossomed , I used to hate it because I was used with the nice Windows but after Micro$oft started making OSes for kids making them hacker not friendly and I think this policy will rise in the future I started working on Linux and I must say I am impressed. Once you manage to understand the command line it becomes a very powerful and fast tool.
You can get the serial simple by calling a command and the read the output from the console into your application,but as I said I like complicated things.I have never used linking an C object into a Lazarus project so I thought this might be the perfect opportunity for me to do that.
I gooled a bit and found a C program that spits out the serial number ( only as root ),adapted it a bit and came up with this function :
| C | | copy code | | ? |
| 01 | #include "chello.h" |
| 02 | char * getSerial(char * disk){ |
| 03 | int descriptor; |
| 04 | static struct hd_driveid hdd; |
| 05 | if ((descriptor = open(disk,O_RDONLY | O_NONBLOCK)) < 0) |
| 06 | { |
| 07 | return "ERR_DISKFAIL"; |
| 08 | } |
| 09 | |
| 10 | if (!ioctl(descriptor,HDIO_GET_IDENTITY,&hdd)) |
| 11 | { |
| 12 | return hdd.serial_no; |
| 13 | } |
| 14 | else return "ERR_BADSERIAL"; |
| 15 | }; |
| 16 |
FPC understand C object files so you must compile with GCC the command is this
gcc -c chello.c
After building the object file you must use link it to lazarus
| Delphi | | copy code | | ? |
| 1 | {$link chello.o} |
| 2 | {$linklib c} |
| 3 | |
| 4 | function getSerial(disk : PChar) : PChar;cdecl;external; |
That’s it … you can find the full source of this project by visiting my bitbucket repo here.
Tomorrow if I have some spare time I will tell you how I implemented the unique code validation using Lazarus and PHP ( I think ).
Why use the HDD for this, and not the Ethernet LAN card?
HDDs get replaced more often than LAN NICs (:
MAC was my first option but is very easy to change by altering the Windows Registry under Windows.
Your post, Cross platform HardwareID, is really well written. Glad I found your website, regards from Milton!
A provcoative insight! Just what we need!