First i've tried this:
But this can change easily, and not true hw id.
Then found that code, very simple:
This works in dos and win9x. But fails on WinXP/Win2k.
Ok i see: i need some dll (Inpout32.dll or WinIO,AsmIO...etc)
But these are ~50k , first 2 solution is only a bunch of bytes.
Anyway, if no other solution, i will add that 50k dll to my project.
I have another question: this small routine gets serialnumber from ide controller.
Ok, this is the most common hw part in pc, but if destination pc uses sata disk (or scsi), how can i read hdd info?
Is there i/o port map of sata (scsi) controller available on the net? (i googled but no success)...thanks
invoke GetVolumeInformation,StrAddr ( "c:\" ),addr buffer,254,addr ID,0,0,0,0
But this can change easily, and not true hw id.
Then found that code, very simple:
mov di,addr buffer
mov dx,1f7h ; io address of first ide controller's status register
@@ in al,dx ; get status
test al,80h ; BUSY?
jnz @b
dec dx ; 1f6h drive/head selection register
mov al,0a0h ; select master drive
out dx,al
inc dx ; 1f7h status register
@@ in al,dx ; get status
test al,80h
jnz @b
mov al,0ech ; get dive info command
out dx,al
@@ in al,dx ; get status
test al,80h
jnz @b
sub dx,7 ; 1f0h controller"s data port
mov ecx,14h ; number of words to get (last 10 word is the serial)
cld
rep insw ; get words into buffer
This works in dos and win9x. But fails on WinXP/Win2k.
Ok i see: i need some dll (Inpout32.dll or WinIO,AsmIO...etc)
But these are ~50k , first 2 solution is only a bunch of bytes.
Anyway, if no other solution, i will add that 50k dll to my project.
I have another question: this small routine gets serialnumber from ide controller.
Ok, this is the most common hw part in pc, but if destination pc uses sata disk (or scsi), how can i read hdd info?
Is there i/o port map of sata (scsi) controller available on the net? (i googled but no success)...thanks
probably doable via deviceiocontrol thru mountmanager or whatnot, the getvolumeinformation api should be sufficient though, and you are right in the fact that the code you pasted will not work in any os greater than win9x simply because the in/out command is priveledged, you could code your own device driver to do it however, that is probably the best approach.. but to load the drive you require admin priveledges etc...
I received a new idea:
For dos and w9x that direct i/o commands and for w2k/xp MS WMI api, which is icluded in OS.
Pro for wmi: handle all type of HDD (ata,sata,scsi)
Con for wmi: need ole, do you know some masm32 wmi example/tutor ?
For dos and w9x that direct i/o commands and for w2k/xp MS WMI api, which is icluded in OS.
Pro for wmi: handle all type of HDD (ata,sata,scsi)
Con for wmi: need ole, do you know some masm32 wmi example/tutor ?
Hey, You won't believe! ( not a cheat! )
I've played with many serialnumber retriever app, and see my hd serial is almost is my nick ! (s5viHarddisk)
This is my 160Gig Seagate. What is the chance of this ?
"The chances of them coming is A million to one he said.... ... But still... they come." (from The War of the Worlds)
Anyway i found a simple commandline wmi solution for windows millenium and above:
I've played with many serialnumber retriever app, and see my hd serial is almost is my nick ! (s5viHarddisk)
This is my 160Gig Seagate. What is the chance of this ?
"The chances of them coming is A million to one he said.... ... But still... they come." (from The War of the Worlds)
# hdparm -I /dev/hda
/dev/hda:
ATA device, with non-removable media
Model Number: ST3160023A
Serial Number: 5JS5V1HD
Firmware Revision: 8.01
Standards:
Used: ATA/ATAPI-6 T13 1410D revision 2
Supported: 6 5 4 3
Configuration:
Logical max current
cylinders 16383 65535
heads 16 1
sectors/track 63 63
Anyway i found a simple commandline wmi solution for windows millenium and above:
wmic /namespace:\\root\cimv2 path Win32_PhysicalMedia
I worked out the complete solution (tested on w98 and xp too)
On win9x we must use ntkern.vxd (built in w9x) to make direct i/o
On NT/w2k/XP we can use wmi subsystem to query hardware
Thanks to Kernel_Gaddafi from www.masmforum.com to share his wmi code example
http://www.masmforum.com/simple/index.php?topic=2594.0
Now i can compare hdd serial to the list of valid numbers (stored in my exe), and if not found,exit app.
Yes i store valid numbers in my exe but i encrypt it. With hexeditor you cannot see numbers in my exe.
New user must send me a little file (generated my app) which contains his hdd serial, i pick up his number to my list and i send modified exe.
This is my method to protect my app.
If someone knows better or want to share his method i appreciate it. thanks
;
; Check wmi is present
;
invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,StrAddr ( "SYSTEM\CurrentControlSet\Control\WMI" ),0,KEY_QUERY_VALUE,addr hKey
.if eax!=0 ; no wmi, it must be win95 or win98 !!
;
; Read HDD serialnumber via direct I/O (only for primary master IDE drive!)
;
invoke GetHDDSerialIO,addr numbuf
.else ; wmi is present, it must be millennium or above (xp,nt,2k)
;
; Read HDD serialnumber via wmi
;
invoke GetWmiInfo
.endif
; now serialnumber string is in numbuf
On win9x we must use ntkern.vxd (built in w9x) to make direct i/o
;
; Win9x, ntkern.vxd int 2eh functions for direct hw i/O
;
NtKernInAL MACRO ;in al,dx
push edx
mov edx,esp
mov eax,0f1h
int 2eh
add esp,4
ENDM
NtKernInAX MACRO ;in ax,dx
push edx
mov edx,esp
mov eax,0f3h
int 2eh
add esp,4
ENDM
NtKernOutAL MACRO ;out dx,al
push eax
push edx
mov edx,esp
mov eax,0f7h
int 2eh
add esp,8
endm
GetHDDSerialIO proc lpBuffer:DWORD
mov edi,lpBuffer
mov edx,1f7h ; io address of first ide controller's status register
@@: NtKernInAL
test al,80h ; BUSY?
jnz @b
dec dx ; 1f6h drive/head selection register
mov al,0a0h ; select master drive
NtKernOutAL
inc dx ; 1f7h status register
@@: NtKernInAL
test al,80h
jnz @b
mov al,0ech ; get dive info command
NtKernOutAL
@@: NtKernInAL
test al,80h
jnz @b
sub dx,7 ; 1f0h controller's data port
mov ecx,10 ; number of words, skip first 10 words
cld
.while ecx!=0 ; get words into buffer
NtKernInAX
dec ecx
.endw
mov ecx,10 ; number of words to get, 10 words is the serialnumber
cld
.while ecx!=0 ; get words into buffer
NtKernInAX
xchg al,ah
mov word ptr ,ax
inc edi
inc edi
dec ecx
.endw
mov ecx,246 ; number of words, read remaining 246 words to complete operation
cld
.while ecx!=0 ; get words into buffer
NtKernInAX
dec ecx
.endw
ret
GetHDDSerialIO endp
On NT/w2k/XP we can use wmi subsystem to query hardware
include <c:\masm32\macros\macros.asm>
include <c:\masm32\macros\ucmacros.asm>
; located in ObjIdl.h
EOAC_NONE EQU 0
; located in RpcDce.h
RPC_C_AUTHN_LEVEL_DEFAULT EQU 0
RPC_C_IMP_LEVEL_DEFAULT EQU 0
RPC_C_IMP_LEVEL_IMPERSONATE EQU 3
GUID2 STRUC
dd1 dd ?
dw1 dw ?
dw2 dw ?
db1 db ?
db2 db ?
db3 db ?
db4 db ?
db5 db ?
db6 db ?
db7 db ?
db8 db ?
GUID2 ENDS
IWbemLocator STRUCT
lpVtbl DWORD ?
IWbemLocator ENDS
IWbemLocatorVtbl STRUCT
QueryInterface DWORD ?
AddRef DWORD ?
Release DWORD ?
ConnectServer DWORD ?
IWbemLocatorVtbl ENDS
IWbemServices STRUCT
lpVtbl DWORD ?
IWbemServices ENDS
IWbemServicesVtbl STRUCT
QueryInterface DWORD ?
AddRef DWORD ?
Release DWORD ?
OpenNamespace DWORD ?
CancelAsyncCall DWORD ?
QueryObjectSink DWORD ?
GetObject DWORD ?
GetObjectAsync DWORD ?
PutClass DWORD ?
PutClassAsync DWORD ?
DeleteClass DWORD ?
DeleteClassAsync DWORD ?
CreateClassEnum DWORD ?
CreateClassEnumAsync DWORD ?
PutInstance DWORD ?
PutInstanceAsync DWORD ?
DeleteInstance DWORD ?
DeleteInstanceAsync DWORD ?
CreateInstanceEnum DWORD ?
CreateInstanceEnumAsync DWORD ?
ExecQuery DWORD ?
ExecQueryAsync DWORD ?
ExecNotificationQuery DWORD ?
ExecNotificationQueryAsync DWORD ?
ExecMethod DWORD ?
ExecMethodAsync DWORD ?
IWbemServicesVtbl ENDS
IEnumWbemClassObject STRUCT
lpVtbl DWORD ?
IEnumWbemClassObject ENDS
IEnumWbemClassObjectVtbl STRUCT
QueryInterface DWORD ?
AddRef DWORD ?
Release DWORD ?
Reset DWORD ?
Next DWORD ?
NextAsync DWORD ?
Clone DWORD ?
Skip DWORD ?
IEnumWbemClassObjectVtbl ENDS
IWbemClassObject STRUCT
lpVtbl DWORD ?
IWbemClassObject ENDS
IWbemClassObjectVtbl STRUCT
QueryInterface DWORD ?
AddRef DWORD ?
Release DWORD ?
GetQualifierSet DWORD ?
Get DWORD ?
Put DWORD ?
Delete DWORD ?
GetNames DWORD ?
BeginEnumeration DWORD ?
Next DWORD ?
EndEnumeration DWORD ?
GetPropertyQualifierSet DWORD ?
GetObjectText DWORD ?
SpawnDerivedClass DWORD ?
SpawnInstance DWORD ?
CompareTo DWORD ?
GetPropertyOrigin DWORD ?
InheritsFrom DWORD ?
GetMethod DWORD ?
PutMethod DWORD ?
DeleteMethod DWORD ?
BeginMethodEnumeration DWORD ?
NextMethod DWORD ?
EndMethodEnumeration DWORD ?
GetMethodQualifierSet DWORD ?
GetMethodOrigin DWORD ?
IWbemClassObjectVtbl ENDS
.data
; located in WbemCli.h
WBEM_FLAG_CONNECT_USE_MAX_WAIT EQU 80h
WBEM_FLAG_FORWARD_ONLY EQU 20h
WBEM_INFINITE EQU -1
WBEM_E_INVALID_QUERY EQU 80041017h
WBEM_E_INVALID_QUERY_TYPE EQU 80041018h
IID_IWbemLocator \
GUID2 <0dc12a687h,0737fh,011cfh,088h,04dh,000h,0aah,000h,04bh,02eh,024h>
IID_IEnumWbemClassObject \
GUID2 <027947e1h,0d731h,011ceh,0a3h,057h,000h,000h,000h,000h,000h,001h>
IID_IWbemClassObject \
GUID2 <0dc12a681h,0737fh,011cfh,088h,04dh,000h,0aah,000h,04bh,02eh,024h>
; located in WbemProv.h
CLSID_WbemAdministrativeLocator \
GUID2 <0cb8555cch,09128h,011d1h,0adh,09bh,000h,0c0h,04fh,0d8h,0fdh,0ffh>
locator IWbemLocator <>
service IWbemServices <>
enumerator IEnumWbemClassObject <>
processor IWbemClassObject <>
retCount DWORD ?
var_val DWORD ? ; not sure what these for
DWORD ?
DWORD ?
WSTR wstrNameSpace, "root\cimv2"
;WSTR wstrQuery, "SELECT * FROM Win32_Processor"
;WSTR wstrQueryLanguage, "WQL"
;wstrQuery dw "S","E","L","E","C","T"," ","*"," ","F","R","O","M"," ","W","i","n","3","2","_","D","i","s","k","D","r","i","v","e",00
wstrQuery dw "S","E","L","E","C","T"," ","*"," ","F","R","O","M"," ","W","i","n","3","2","_","P","h","y","s","i","c","a","l","M","e","d","i","a",00
;wstrQuery dw "S","E","L","E","C","T"," ","*"," ","F","R","O","M"," ","W","i","n","3","2","_","P","r","o","c","e","s","s","o","r",00
wstrQueryLanguage dw "W","Q","L",00
;wstrCPUName dw "P","r","o","c","e","s","s","o","r"," ","N","a","m","e",":","%","s",00
;WSTR wstrName, "Name"
WSTR wstrName, "SerialNumber"
;WSTR wstrName, "Model"
.code
;
; Get info from hardware via WMI , return a string into bufferSQL
;
GetWmiInfo proc
invoke CoInitializeEx,
NULL,
COINIT_MULTITHREADED
invoke CoInitializeSecurity,
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
invoke CoCreateInstance,
addr CLSID_WbemAdministrativeLocator,
NULL,
CLSCTX_INPROC_SERVER,
addr IID_IWbemLocator,
addr locator
mov esi,
lodsd
push offset service
push NULL
push NULL
push WBEM_FLAG_CONNECT_USE_MAX_WAIT
push NULL
push NULL
push NULL
push offset wstrNameSpace
push dword ptr
call dword ptr
mov esi,
lodsd
push offset enumerator
push NULL
push WBEM_FLAG_FORWARD_ONLY
push offset wstrQuery
push offset wstrQueryLanguage
push dword ptr
call dword ptr
mov esi,
lodsd
push offset retCount
push offset processor
push TRUE
push WBEM_INFINITE
push dword ptr
call dword ptr
mov esi,
lodsd
push NULL
push NULL
push offset var_val
push 0
push offset wstrName
push dword ptr
call dword ptr
mov ecx,
invoke WideCharToMultiByte,CP_ACP,0,,-1,addr numbuf,255,NULL,NULL
invoke CoUninitialize
ret
GetWmiInfo endp
Thanks to Kernel_Gaddafi from www.masmforum.com to share his wmi code example
http://www.masmforum.com/simple/index.php?topic=2594.0
Now i can compare hdd serial to the list of valid numbers (stored in my exe), and if not found,exit app.
Yes i store valid numbers in my exe but i encrypt it. With hexeditor you cannot see numbers in my exe.
New user must send me a little file (generated my app) which contains his hdd serial, i pick up his number to my list and i send modified exe.
This is my method to protect my app.
If someone knows better or want to share his method i appreciate it. thanks
A quick question, not knowing what your app is, and what its popularity would be, wouldn't you're copy protection scheme unnecessarily bloat the exe of the 1000th, 10000th customer?
Depending on your method of encrypting the serial no.?
regards,
Rags
Depending on your method of encrypting the serial no.?
regards,
Rags
lenght of Hdd serialnumber is 20 byte (10000*20byte=200k) but my exe is encrypted and packed by a pecompressor.
Sizes:
app: 45k
sqlite dll: 250k
jpg pictures: 10k (for decent look)
small database: 50k
these packed with pebundle and encrypted by Yoda's crypter1.3 into one exe (260k)
(to crack it you need: decrypt my exe, find hdd serial, write your HDD number)
Anyway users of my app is a closed group (2-10 users)
Sizes:
app: 45k
sqlite dll: 250k
jpg pictures: 10k (for decent look)
small database: 50k
these packed with pebundle and encrypted by Yoda's crypter1.3 into one exe (260k)
(to crack it you need: decrypt my exe, find hdd serial, write your HDD number)
Anyway users of my app is a closed group (2-10 users)
Hrm, there must be some non-direct-IO solution for 9x too. I mean, ATA vs. SATA vs. SCSI vs. USB storage (external HDD or even a large pendrive would do). Direct hardware access for this just isn't a very good idea.
Yes, You're right, F0dder
This win9x method works ONLY with primary master ata hdd (but not too hard to code all ide channels)
But i think these simple old machines which running Win9x have simple ata disk. (Probably)
I've never seen a win9x running on sata hdd (is it possible? is there a win9x driver for sata chipsets?)
Anyway,i call functions in ntkern.vxd, i really dont know if ntkern.vxd uses direct i/o instructions?
I hope ntkern.vxd manage correctly this i/o operations, isnt it?
I found info on ntkern.vxd http://vx.netlux.org/lib/vzo25.html
There are another solution , wmi for win9x is available, and we can use it on win9x also, but it need to make an istaller which detects lack of wmi, and install it (and of course i must pack wmi whit my app)
This win9x method works ONLY with primary master ata hdd (but not too hard to code all ide channels)
But i think these simple old machines which running Win9x have simple ata disk. (Probably)
I've never seen a win9x running on sata hdd (is it possible? is there a win9x driver for sata chipsets?)
Anyway,i call functions in ntkern.vxd, i really dont know if ntkern.vxd uses direct i/o instructions?
I hope ntkern.vxd manage correctly this i/o operations, isnt it?
I found info on ntkern.vxd http://vx.netlux.org/lib/vzo25.html
There are another solution , wmi for win9x is available, and we can use it on win9x also, but it need to make an istaller which detects lack of wmi, and install it (and of course i must pack wmi whit my app)
Well, if nothing else win9x COULD run on SATA by using "legacy" (int13) access for the drive... but I'm fairly certain there's ought to be someone running 9x on SCSI.