Help with Hardware ID - c#

I'm using C# and .NET 2.0. My app needs some way to check the different users so I'll use hardware id, but I saw that I can use only:
mac address - easily changeable and not everybody have it // NO
processor id - using WMI it returns a value for the cpu model, it's not unique // NO
motherboard serial - not every motherboard have it // NO
the Windows's volume serial - I'm not sure if it will be changed on Windows reinstall and format of the volume
So is there something I didn't mention for hwid? I want something that everybody have and it won't be erased on windows reinstall. Else I'd have to use the windows's volume serial number.
EDIT: From the commments I think it's best to use HDD id. How to get it?
EDIT2: I just read that the SCSI drives don't have serial. Is that true?
FINAL EDIT: I'm already using the root drive serial on my app. It work's pretty well. Thanks all.

HDD Serial number: unique, unchangeable, and everyone has it.
not a perfect option but...

Well i'd go for more than one id. If you combine enough IDs they will get you enough uniqueness.
EDIT: you might also go for the place on the harddisk your program was installed too (Platter, Cylinder etc.)

Why do you want to use hardware Id? I'd go with some kind of forms-based (or AD based) security, myself.
Given that, however: The thing about HWID is that it identifies that particular computer configuration: it is designed to change if there are system changes. You mention that Windows Volume Serial could change on reinstall and reformat, but won't your software also have to be reinstalled at that point? HDD Serial could also change if, say, the user swaps HDDs for some reason.
If you have to use HWID, you'll probably need to select one (or more) of the available options to provide uniqueness and either code around, or inform users about, hardware changes requiring a re-install and/or reconfigure of your software.

The MAC address is not very reliable.
You should use something that cannot be changed such a CPU ID or HDD IDE ID.
Here is want I mean:
http://www.soft.tahionic.com/download-hdd_id/index.html
http://www.soft.tahionic.com/download-hdd_id/hardware%20ID%20programmer%27s%20DLL.html
And to answer your question, Yes, SCSI does not have a hardware ID.

Do you have to think about security or only reliability, i.e. does the user want to tamper your ID check?
If you need (high) security, buy one of the "software protection" products, this is far cheaper than to do it yourself.
No high security required? =>
Another possibility is to use the User or Machine SID. You have to take into account that your application is executed elvated => User is Administrator then.
Last but not least: Write a random value of some bytes into the registry (possibly at various places) under HKEY_CURRENT_USER and use these as an ID.

Related

UDID for windows 8

Is there any unique device ID (UDID) or any similar ID I can read out on Windows 8 that doesn't change with hardware changes, app-reinstallation etc.?
If No - what is the best way to generate it yourself?
No. Yes.
No, there is not such ID because (in theory) you can change ANY hardware component so you may get a completely different ID (that's why Microsoft suggest to calculate a score based on ASHWID).
Yes, there is such ID (but it may not be applicable in your case).
If you can't rely on hardware because it's easy to add memory, change disks, add another network card (for example turning on/off bluetooth or wi-fi) then you have to rely on a "software" ID.
In the registry there is an unique ID generated during Windows installation and it won't change until you reinstall Windows. You can find such ID in HKLM/Software/Microsoft/Cryptography, it's a string named MachineGuid.
If you can identify a component you're pretty sure that won't change (motherboard for example) you may use a simple WMI query to get its serial number but you should always provide a fallback because many many MBs returns a fake S/N (and virtual machines may returns always the same one). What's the proper solution...well it depends on what you have to do with that ID. Identify the user? Check for license? Encrypt data? Each of these has a different "best practice" for ID.
Get an unique ID for the device
If you have to identify a particular device (regardless to the user) you have many options, what I'd prefer to do is to generate an ID using only stable data (S/N from motherboard and BIOS, for example). This won't help you if he/she completely renew its hardware but it should be stable enough (but you have to define what is enough in your case). You may even use the S/N of the primary disk (with portable devices it's pretty stable and you may even use it in combination with other serial numbers to build your own ID). You can get this informations through WMI or (if you're targeting WinRT) through specific bytes of the ASHWID structure.
Encrypt data
In this case you have to think when data may be unrecoverable. If with a small hardware change your users won't be able to read their previous files well, they'll be unhappy. In this case I would suggest to use the MachineGuid, unless they reinstall the OS they wouldn't have to worry (but do them a favor and provide a way to read back that GUID somewhere). If you're sure you're targeting a portable device like a phone or a tablet then disk serial number (or CPU ID, if available, or MB or BIOS) may be appropriate too (because it's pretty uncommon they'll change).
Licensing
I would use a combination of many (stable) IDs. As for an unique identifier for the device you can't be sure nothing will change. In the past MAC address was vastly used for this but mobile devices changed these rules (because it's easy to turn off a NIC). You can still use them but you have to put extra care (and code) to manage that situation. Again a combination of multiple IDs (chosen carefully) can help you to minimize customers effort when they change their hw/sw setup. In this case a good compromise could be the OS serial number (not the MachineGuid). If they install a new OS then they have to update your license too (but I would use it combined with something else to be sure they won't use the same OS copy on multiple computers or virtual machines).
Note about virtual machines
If you have to target VMs too then things become more complicated. In theory an user can create multiple copies of the same VM with exactly the same hardare and software configuration. If this is an issue and if you can't address this properly (for example using a network check) I would suggest you don't support them at all (just quit if you detect a VM).
here is a code example in JavaScript that filters form ASHWID the hardware modules that are unlikely to be changed (CPU id, size of memory, serial number of the disk device and bios) and convert it to string. the code is based on a code from this thread
// get the hardware Profile id and convert it to byte Array
var hardwareToken = Windows.System.Profile.HardwareIdentification.getPackageSpecificToken(null);
var byteArray = Windows.Security.Cryptography.CryptographicBuffer.copyToByteArray(hardwareToken.id);
var deviceSerial = '',
offset = 0;
// we filter the hardware modules that are unlikely to be changed, and aggregate them to a string.
while (offset < hardwareToken.id.length)
{
// CPU ID of the processor || Size of the memory || Serial number of the disk device || BIOS
if ((byteArray[offset] == 1 || byteArray[offset] == 2 || byteArray[offset] == 3 || byteArray[offset] == 9) && byteArray[offset+1] == 0)
{
for (var i=0; i<4; i++)
{
deviceSerial += byteArray[offset+i].toString();
}
}
offset += 4;
}

C# Keep a program running in the background till the computer completely shuts down

Basically, I am making a program that blocks the internet access after 11h PM. But my only problem is that there is many ways to bypass it, such as shutting down the computer and the user just have to wait until the process gets closed by the OS itself then cancel the shutdown operation (Windows 7).
Any ways to make sure that the program won't get terminated before the pc shutdowns or anything?
If your goal is to block internet access, I recommend enforcing this rule on your router rather than on your PCs. It would be a much simpler, much more reliable solution. Your router probably already supports the feature, but if it doesn't you can buy a new consumer-grade router (dirt-cheap) and/or install a custom firmware that does (see Tomato Firmware for the Linksys WRT-54GL and company).
If the router approach just won't work for you, and you must block internet access in software, I would first suggest investigating Windows "local policy" or "group policy" to see if they can do what you want.
If that's too complex for your taste, try finding an off-the-shelf solution. Look into ZoneAlarm or NetNanny to see if one of them will do the trick.
But if you are bent on writing a C# program to do it for you, you probably want to look into writing a Windows Service. Services are more complex to write and deploy, but they can be configured to run at boot and are not slaved to a user session like regular desktop apps.
That's actually somewhat complex. It's like a virus - how do you keep it running, always?
You might want to read about drivers. Drivers have the highest "trust" by the operating system. They can physically access anything in the computer. Anything but a driver or a core file may be closed by the user manually, is some way or another.
Another thing you can do is to "burn" the file into Kernal.DLL or such. You can do it with a different operating system on the computer (e.g Linux) or by physically writing to the hard disk (not via Windows's API). To physically access the driver, check this out.

Can processor id be used for AES crypto key?

I am using the code below to get processor id:
System.Management.ManagementClass theClass = new System.Management.ManagementClass("Win32_Processor");
System.Management.ManagementObjectCollection theCollectionOfResults = theClass.GetInstances();
foreach (System.Management.ManagementObject currentResult in theCollectionOfResults)
{
MessageBox.Show(currentResult["ProcessorID"].ToString());
}
Is processor ID a unique ID for every computer? I want to generate a random unique number for every computer to use as a AES crypto key. I don't want to use MAC address because i know that MAC address can be changed.
Processor ID is not guaranteed to be unique for every cpu or guaranteed to exist at all.
Hardware can be replaced - you can't change that fact.
Suggestions:
if you need to uniquely identify a machine - it is ok to use the processor Id or MAC address or both for uniqueness. (or any other hardware related number).
but you must keep in mind you id the hardware - not the user, so if the hardware has changed it is much like if someone you know took a face lift and now you don't recognize him.
If you need to identify the user (which I think is better) just let him choose a username and a password.
If you need to make sure that only one previously identified user is using your app, and your'e afraid he will be pirating your app.. the only way is having a server/central point.
It' s bad solution because CPU must support CPUID instructions and system may be contains more one CPU.

Is it possible to have a C# Winform with in-built Anti-Keylogger?

Every security systems have its limits. I understand that hardware key logger cannot be beaten as it is connected to the hardware itself. Also it is not a concern at this point as most of the time it is used by programmers and ethical hackers to log themselves, on top of which most of the time cautious users will be able to visually identify any unwanted hardware (forget gov. agencies).
But as a developer it is often a concern to protect the user! So is it possible for me, as a programmer to integrate a layer of security in my windows form that will be able disable any active key logger/s (i.e. Software based) on user’s system, by implementing some kind of anti hooking trick? Plus most of the software key loggers now days support “Screen shots” is there any way to escape it?
I presume you are worried about users entering their credentials and them being captured.
If this is the case then you need to establish a method of ensuring any captured details are not of use.
A method employed by many banks, and even World of Warcraft now, is the use of a portable token generator. The user then enters their username, password, and typically a PIN displayed on the token generator. These PINs exist for only a few seconds and never repeat. This means the nefarious user who intercepts the credentials can not authenticate with them.
I have never used them, and have no idea how you would source them, but you can read about them here:
http://en.wikipedia.org/wiki/Security_token
It seems to me this is a better method than trying to stop a keylogger from attacking your application.
Even shorter answer: not from c#. For reason's i'm not even going to go in to. Even though you could traverse all the modules that have inserted a keyboard hook, how would you determine whether it is a keylogger, and not something legitimate?
It is possible, but the heuristics to detect one would not be worth the time. It would be appropriate to allow the PC to have a good anti-virus/malware. If you are really paranoid, you could code an on-screen keyboard that inputs through the mouse for your application, very similar to what ING Direct has for PIN input.
Short answer: possibly, but probably not worth the effort.
The adversary has admin rights on the machine. You've already lost.
If you want to protect the user against such attacks best practice would be to run the application on a 'red' network and restrict the software going onto that network. And prevent data from the 'red' network ever being taken away. Even the security agencies are starting to get fed up with the cost and inconvenience of that.

APIs in C# for grabbing CPU IDs and drive/volume serial

I'm aware that I can grab the CPU identifier and the volume serial number for a physical drive by querying WMI, but WMI usually takes its sweet time. What other speedier options, if any, are available to retrieve this information? Are there Win32 APIs that would accomplish this?
Edit: Allow me to clarify. By CPU identifier, I'm referring to the same value one gets by querying the following WMI instance properties:
Win32_Processor::ProcessorId
Win32_LogicalDisk::VolumeSerialNumber
Just keep in mind that ID of the CPU is not always available.
By the way, what are you trying to accomplish? If you want to generate a unique key for a computer instance, check the Generating Unique Key (Finger Print) for a Computer for Licensing Purposes post by Sowkot Osman at Codeproject; it can give you some hints (also read comments).
You can query the windows registry for the drive information, not sure about the CPU though. It seems that your question is addressed in this SO q/a (demonstrates a number of methods to get this info, but for speed, maybe getting it from registry is your best bet):
How to list physical disks?
WMI actually takes a good portion of its data from the registry. The system stores plenty of information in there about the system, and it's obviously very quick to respond.
If you're looking to lock to the motherboard, CPU and/or HDD for licensing reasons, check out the following values:
HKLM\HARDWARE\DESCRIPTION\System\BIOS\BaseBoardManufacturer
HKLM\HARDWARE\DESCRIPTION\System\BIOS\BaseBoardProduct
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0\Identifier
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\BuildLabEx
HKLM\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\DiskController\0\DiskPeripheral\0 (may be specific to boards with RAID in use)
If you want to get the disk serial without WMI, issue a DeviceIoControl call to the physical drive device. Sample code in VB.NET: http://www.dreamincode.net/code/snippet429.htm
I like GetSystemInfo but that doesn't cover physical drives..

Categories