News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Machine ID

Started by Nilrem, January 31, 2005, 01:41:46 PM

Previous topic - Next topic

thomasantony

Hi,
  I got an example for doing exactly that at my website in the win32asm section.
http://www.tomasm.tk/  . the program is called GetHdSerial

Thomas Antony :U
There are 10 types of people in the world. Those who understand binary and those who don't.


Programmer's Directory. Submit for free

Nilrem

Well there is a program that (to register) gets your machine id (hard-drive serial) and then mixes it with another code to give you a unique code. I am interested in this protection. I'm not going to develop it now, but when I use programs I like to understand fully their protections. 8-) I am a very curious person. I will try the code to night, would wsprintf help with the formatting?

MichaelW

Hi Thomas,

GetHDSerial returns 00403034 on both of the systems I tested it on. On my spare system the actual HDD serial number (from the information returned by IdDevice) is WD-WCAHM1149190. I did not take the time to restart my primary system, but the HDD is a higher capacity version of the drive in the spare system, so the serial number would be similar. For the C volume on my primary system the volume serial number is 1941-090A (obtained from a DIR command).

; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .486                       ; create 32 bit code
    .model flat, stdcall       ; 32 bit memory model
    option casemap :none       ; case sensitive

    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\kernel32.inc

    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\kernel32.lib

    include \masm32\macros\macros.asm
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
        RootPathName            db "c:\",0
        VolumeNameBuffer        db 128 dup(0)
        nVolumeNameSize         dd 128
        VolumeSerialNumber      dd 0
        MaximumComponentLength  dd 0
        FileSystemFlags         dd 0
        FileSystemNameBuffer    db 128 dup(0)
        nFileSystemNameSize     dd 128
    .code
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    invoke GetVolumeInformation,ADDR RootPathName,
                                ADDR VolumeNameBuffer,
                                nVolumeNameSize,
                                ADDR VolumeSerialNumber,
                                ADDR MaximumComponentLength,
                                ADDR FileSystemFlags,
                                ADDR FileSystemNameBuffer,
                                nFileSystemNameSize
    print chr$("RootPathName: ")
    print ADDR RootPathName
    print chr$(13,10,"VolumeNameBuffer: ")
    print ADDR VolumeNameBuffer
    print chr$(13,10,"VolumeSerialNumber (dec): ")
    print ustr$(VolumeSerialNumber)
    print chr$(13,10,"VolumeSerialNumber (hex): ")
    print uhex$(VolumeSerialNumber)
    print chr$(13,10,"MaximumComponentLength: ")
    print ustr$(MaximumComponentLength)

    .IF FileSystemFlags & FILE_NAMED_STREAMS
      print chr$(13,10,"FILE_NAMED_STREAMS")
    .ENDIF
    .IF FileSystemFlags & FILE_READ_ONLY_VOLUME
      print chr$(13,10,"FILE_READ_ONLY_VOLUME")
    .ENDIF
    .IF FileSystemFlags & FILE_SUPPORTS_OBJECT_IDS
      print chr$(13,10,"FILE_SUPPORTS_OBJECT_IDS")
    .ENDIF
    .IF FileSystemFlags & FILE_SUPPORTS_REPARSE_POINTS
      print chr$(13,10,"FILE_SUPPORTS_REPARSE_POINTS")
    .ENDIF
    .IF FileSystemFlags & FILE_SUPPORTS_SPARSE_FILES
      print chr$(13,10,"FILE_SUPPORTS_SPARSE_FILES")
    .ENDIF
    .IF FileSystemFlags & FILE_VOLUME_QUOTAS
      print chr$(13,10,"FILE_VOLUME_QUOTAS")
    .ENDIF
    .IF FileSystemFlags & FS_CASE_IS_PRESERVED
      print chr$(13,10,"FS_CASE_IS_PRESERVED")
    .ENDIF
    .IF FileSystemFlags & FS_CASE_SENSITIVE
      print chr$(13,10,"FS_CASE_SENSITIVE")
    .ENDIF
    ;.IF FileSystemFlags & FS_FILE_COMPRESSION
    ;  print chr$(13,10,"FS_FILE_COMPRESSION")
    ;.ENDIF
    ;.IF FileSystemFlags & FS_FILE_ENCRYPTION
    ;  print chr$(13,10,"FS_FILE_ENCRYPTION")
    ;.ENDIF
    .IF FileSystemFlags & FS_PERSISTENT_ACLS
      print chr$(13,10,"FS_PERSISTENT_ACLS")
    .ENDIF
    .IF FileSystemFlags & FS_UNICODE_STORED_ON_DISK
      print chr$(13,10,"FS_UNICODE_STORED_ON_DISK")
    .ENDIF
    ;.IF FileSystemFlags & FS_VOL_IS_COMPRESSED
    ;  print chr$(13,10,"FS_VOL_IS_COMPRESSED")
    ;.ENDIF

    print chr$(13,10,"FileSystemNameBuffer: ")
    print ADDR FileSystemNameBuffer   

    mov   eax, input(13,10,13,10,"Press enter to exit...")
    exit
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

BOOL GetVolumeInformation(
  LPCTSTR lpRootPathName,
  LPTSTR lpVolumeNameBuffer,
  DWORD nVolumeNameSize,
  LPDWORD lpVolumeSerialNumber,
  LPDWORD lpMaximumComponentLength,
  LPDWORD lpFileSystemFlags,
  LPTSTR lpFileSystemNameBuffer,
  DWORD nFileSystemNameSize
);
FILE_NAMED_STREAMS
FILE_READ_ONLY_VOLUME
FILE_SUPPORTS_OBJECT_IDS
FILE_SUPPORTS_REPARSE_POINTS
FILE_SUPPORTS_SPARSE_FILES
FILE_VOLUME_QUOTAS
FS_CASE_IS_PRESERVED
FS_CASE_SENSITIVE
FS_FILE_COMPRESSION
FS_FILE_ENCRYPTION
FS_PERSISTENT_ACLS
FS_UNICODE_STORED_ON_DISK
FS_VOL_IS_COMPRESSED


RootPathName: c:\
VolumeNameBuffer:
VolumeSerialNumber (dec): 423692554
VolumeSerialNumber (hex): 1941090A
MaximumComponentLength: 255
FS_CASE_IS_PRESERVED
FS_UNICODE_STORED_ON_DISK
FileSystemNameBuffer: FAT32


If I change the root path to "d:\" I get a different volume serial number (even though both volumes are on the same physical drive), and again it matches the volume serial number returned by DIR.
eschew obfuscation

Nilrem

Thankyou. 8-) I won'tbe using all of that code because I don't need it but bits of it I am interested in and it helped a lot. 8-)

Nilrem

Tested it, why does my serial number come up a negative number, to do with signed and unsigned? It gives a postive number on my d:\ drive so...?

Tedd

Signed numbers are taken as the upper-half of the number space (the topmost bit is set) so depending on the drive, if the number is 'large' then it will be printed as negative.
Though this depends on what options you give to wsprintf - "%d" or "%i" will give negatives, "%lu" just gives the whole number, treating the topmost bit as significant and not as a sign.
No snowflake in an avalanche feels responsible.

MichaelW

The DIR command displays the hex value of the number, so I assume the number should be interpreted as an unsigned value.

eschew obfuscation

Nilrem

Well what would you do to rectify the situation Michael?

MichaelW

I doubt that the sign of the number has any meaning here. In my version I used the uhex$ macro which displays the number as unsigned hex. If you are using wsprintf to convert the value, you could try "%lX". Run a "DIR /p" on a directory and see what it returns, as this is how MS intended that the value be ihnterpreted.

eschew obfuscation

Nilrem

#24
I am not using wsprintf, I will show you my code, a trimmed version of yours.

    .data
   
    RootPathName            db "c:\",0
    VolumeNameBuffer        db 128 dup(0)
    nVolumeNameSize         dd 128
    VolumeSerialNumber      dd 0
    MaximumComponentLength  dd 0
    FileSystemFlags         dd 0
    FileSystemNameBuffer    db 128 dup(0)
    nFileSystemNameSize     dd 128

ID PROC

LOCAL lpstring[128]:DWORD

    invoke GetVolumeInformation,ADDR RootPathName,
                                ADDR VolumeNameBuffer,
                                nVolumeNameSize,
                                ADDR VolumeSerialNumber,
                                ADDR MaximumComponentLength,
                                ADDR FileSystemFlags,
                                ADDR FileSystemNameBuffer,
                                nFileSystemNameSize

    print chr$("RootPathName: ")
    print ADDR RootPathName
    print chr$(13,10,"VolumeSerialNumber (dec): ")
    print ustr$(VolumeSerialNumber)
    print chr$(13,10,"VolumeSerialNumber (hex): ")
    print uhex$(VolumeSerialNumber)

mov lpstring, input ()
ret

ID endp
When accessing the C:\ drive it gives a negative number (dec) but when doing it with the D:\ it gives a positive integer.
Solutions?

MichaelW

Perhaps there is an error in the ustr$ macro. It's supposed to convert the value to an unsigned decimal number. In any event, I think the sign is not relevant to using the number as an identifier. In my tests Microsoft displays the number in hex, with a "-" between the upper and lower words, so effectively they are treating it as a string. If the number were intended to be treated as a number, then I think Microsoft would have documented the fields that make up the number, which AFAIK they have not.

Also, I have doubts that a volume serial number would be a reasonable machine ID, because I doubt that it would uniquely identify the system. I think Microsoft intended it to be a reasonable volume identifier in an environment where there would be only a limited number of volumes. For a uinique identifier I think your network adapter MAC address would be a much better choice, because AFAIK every network adapter has a unique MAC address.








eschew obfuscation

P1

Quote from: Nilrem on February 01, 2005, 01:33:19 PM
When accessing the C:\ drive it gives a negative number (dec) but when doing it with the D:\ it gives a positive integer.
The serial is to be display in HEX for this very reason.  Also so it format neatly for the Dir output to the console.  Try dw2hex in MASM32 for output.  And compare it to your hard drive Dir output.

Regards,  P1  :8)

Nilrem

This code doesn't work for entering either C, c, C:, c:, C:\, or c:\, why?

ID PROC

LOCAL lpstring[128]:DWORD
mov lpstring, input ("Enter the drive letter please: ")

    invoke GetVolumeInformation,ADDR lpstring,
                                ADDR VolumeNameBuffer,
                                nVolumeNameSize,
                                ADDR VolumeSerialNumber,
                                ADDR MaximumComponentLength,
                                ADDR FileSystemFlags,
                                ADDR FileSystemNameBuffer,
                                nFileSystemNameSize
  print chr$(13,10,"RootPathName: ")
    print ADDR lpstring
    print chr$(13,10,"VolumeSerialNumber (dec): ")
    print ustr$(VolumeSerialNumber)
    print chr$(13,10,"VolumeSerialNumber (hex): ")
    print uhex$(VolumeSerialNumber)

mov lpstring, input ("Press Enter to Exit")
ret

ID endp

six_L

#28
hi, Nilrem,
here is a code written by Babek( Russian )with TASM. I translated it into MASM. it can work fine.
;==============================================================================
Mr. Thomas Antony,
your GetHdSerial has some problem. i addid a HandleError proc. the [invoke GetVolumeInformation,ADDR RootPath,ADDR VolName,255,Serial,ecx,edx,0,0] returned false value. i tested it on windows xp home edition.

;@echo off
;goto make
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;  Author:Thomas Antony
;  Date: 5 January 2004
;  Licence:GPL
;  ASM Format:MASM32
;  Tested on Win98SE and WinXP Professional
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
MsgCaption db "The Serial Number of your HDD is:",0
pzCaption db "Error!!!",0
RootPath db "C:\",0
SerialFmt db "%08lX",0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
SerialNo db 8 dup(?)
Serial dd ?
VolName db 255 dup(?)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
HandleError proc lpTitle:DWORD
     
LOCAL lpMsgBuffer     : LPVOID ;dword
; calculate language ID, asm version of MAKELANGID
mov cx, SUBLANG_DEFAULT
shl ecx, 10
;or  cx, LANG_NEUTRAL        ; LANG_NEUTRAL = 0, nothing necessary

; Setup parameters for FormatMessage, normal pushing to use some
; params directly (e.g. GetLastError returns the ID in eax, but I
; can't use this register in "invoke")

push NULL                ; we don't need this
push 0                   ; min. size of output buffer if we use
; FORMAT_MESSAGE_ALLOCATE_BUFFER
lea  ebx,lpMsgBuffer     ; get address of our buffer
push ebx                 ; address of buffer
push ecx                 ; our language ID, calculated above
invoke GetLastError      ; get error number
push eax                 ; push return value = error ID
push NULL                ; can be used to format a string, we don't need it
mov edx, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM
push edx                 ; some flags, check your doc for more
call FormatMessage       ; here we go

; Display error-message
invoke MessageBox, NULL, lpMsgBuffer, lpTitle, MB_OK or MB_ICONSTOP
; free memory
invoke LocalFree, lpMsgBuffer

ret
HandleError endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetVolumeInformation,ADDR RootPath,ADDR VolName,255,Serial,ecx,edx,0,0
.if eax==0
invoke HandleError, addr pzCaption
jmp qexit
.endif
invoke wsprintfA,ADDR SerialNo,ADDR SerialFmt,ADDR Serial
invoke MessageBoxA,0,ADDR SerialNo,ADDR MsgCaption,0
qexit: invoke ExitProcess,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

end start

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
:make
set name=hds_1

    \masm32\bin\ml /c /coff /Cp %name%.bat
    \masm32\bin\Link /subsystem:windows %name%.obj
   
    if exist *.bak del *.bak
    if exist *.obj del *.obj
    echo.



regards.



[attachment deleted by admin]
regards

Nilrem

Hi, thankyou, however the problem with my code is user input. Compile it and you will see.