I modified and meshed some features to give a script that will submit the info given to a php, retrieve the activation key, input it, write the ini, and continue as expected. Ini will write to AppData folder, can be easily modified to go to the folder you want. Fully functional if you have webhosting that supports php.
WhateverYouCallYourApp.ahk:
Code:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
Website := "http://www.yourwebsite.com/validate.php?code=" ;This must be first, modify to match your website, the validate.php?code= part should remain the same unless you make the correct modifications in the php file.
SWP_Initialize( 0x81645732, 0x19573549 ) ; Up to 8 secret keys,
SWP_CheckRegistration( "My Application Name", "software@developer.com" ) ; Modify this info to match your program
;The following would be your program
Gui, Add, Text,, Hello Here I am.
Gui, Add, Button,, Nothing
Gui, Add, Button, Default gExitApp, Exit
Gui, Show, x150 y150, Test App
return
ExitApp:
ExitApp
; End your program area.
;Shouldnt have to modify anything below here except the location of the ini file
; SWProtect-GUI.ahk
;-------------------------------------------------------------------------------
;
; Software Protection Library - GUI Implementation 0.11
;
; This library contains a simple set of GUI functions to allow easy
; implementation of a software protection, using a registration code and a
; computer fingerprint.
;
; Requires: SWProtect-Internal.ahk
;
; Original Code: Laszlo Hars <www.Hars.US>
; Library/GUI Version: Icarus
;
; AutoHotkey Forum Thread:
; http://www.autohotkey.com/forum/viewtopic.php?t=5763&postdays=0&postorder=asc&start=0
;
; USAGE 1:
; 1. Include this file in your script
; 2. In your loading sequence, call SWP_Initialize() then
; SWP_CheckRegistration( "AppName", "DeveloperEmail" )
; to check/ask for a valid registration.
;
; USAGE 2:
; 1. Include this file in a new script
; 2. Call SWP_Initialize() then SWP_ShowKeyGen() to activate a KeyGen dialog
;
; TODO:
; - See if there is a way to use less global variables
; - See if there is a way to avoid using a fixed GUI ID (currently, 20) and
; instead pass it as an optional parameter. The reason why this is not
; implemented like this is because we need to have 20GuiEscape: labels
;
;-------------------------------------------------------------------------------
#Include SWProtect-Internal.ahk
#Include http.ahk
;-------------------------------------------------------------------------------
; TESTER - Comment or delete this tester when including the file
;
/*
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
; USAGE 1: Add this in a separate file, to have your own keygen
;-------------------------
SWP_Initialize( 0x81645732, 0x19573549 ) ; Up to 8 secret keys,
SWP_ShowKeyGen()
Return
;-------------------------
; USAGE 2: Add this in your loading sequence to check/ask for a valid registration
;-------------------------
SWP_Initialize( 0x81645732, 0x19573549 ) ; Up to 8 secret keys,
SWP_CheckRegistration( "My Application", "software@developer.com" )
;-------------------------
Msgbox The program continues here`n`n`n`n`n`n`n`n
Return
*/
;
; END OF TESTER
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; Main GUI Function
;-------------------------------------------------------------------------------
SWP_CheckRegistration( appName, developerEmail ) {
;
; Checks for the existence of a valid registration file.
; If registration is valid, it will return the control to the caller, otherwise
; it will show a registration GUI (with an option to the user to ask for a
; registration key) and will only resume normal operation if a valid
; registration code is entered.
;
; When a valid key is entered, the registration details will be saved in an INI
; file (default: Reg.ini) so that next time this function is called, it will be
; able to find the registration code on its own.
;
;-------------------------------------------------------------------------------
Global SWP_AppName, SWP_IniFilename, SWP_DeveloperEmail, SWP_LicenseOK
SWP_AppName := appName
SWP_IniFilename = %A_AppData%\MyProg\Reg.ini ; Modify as needed for placement of the Reg.ini file.
FileCreateDir %A_AppData%\MyProg ;Create folder for INI placement.
SWP_DeveloperEmail := developerEmail
SWP_LicenseOK := false
If( Not FileExist( iniFilename ) ) {
SWP_ShowRegisterDialog( appName )
Loop
If( SWP_LicenseOK ) ; Loop will be broken by a valid license
Break
}
Else { ; File exists, read registration data and validate
SWP_ReadRegFile( iniFilename )
Sleep 1000 ; This is here since the Reload in SWP_ReadRegFile
; seem to still give the application to continue running
; before it actually reloads.
; Deleteing this launches the "The program continues"
; msgbox
; *** TODO: Can be fixed?
}
}
SWP_ShowKeyGen() {
;
; This function shows a simple generator for registration numbers.
; Once the user has sent you his Computer ID, use this function to generate
; a valid registration key for this user+computer.
;
; The proper use of this function, is to create a separate ahk code, including
; this library, then calling this function.
;
; Note that you need to call SWP_Initialize with the same seed keys as in your
; SWP_CheckRegistration function BEFORE you call this function.
;
;-------------------------------------------------------------------------------
Global SwpGuiVal_Name, SwpGuiVal_Email, SwpGuiVal_Key, SwpGuiVal_Fingerprint
,SWP_GuiID
SWP_GuiID := 20
GuiID := SWP_GuiID
Gui %GuiID%:Margin, 10, 10
; Top introduction text
Gui %GuiID%:Font, s10 bold
Gui %GuiID%:Add, Text, x10 y10 w352 h22 center, Please enter user details:
Gui %GuiID%:Font, s10 norm
; Text labels
Gui %GuiID%:Add, Text, xp y+15 w135 h22 right section, % "Name/Company: "
Gui %GuiID%:Add, Text, xp y+2 wp hp right , % "Email Address: "
Gui %GuiID%:Add, Text, xp Y+2 wp hp right , % "Computer ID: "
Gui %GuiID%:Add, Text, xp Y+2 wp hp right , % "Key: "
; Edit fields
Gui %GuiID%:Add, Edit, xs+137 ys wp+64 hp vSwpGuiVal_Name
Gui %GuiID%:Add, Edit, xp y+2 wp hp vSwpGuiVal_Email
Gui %GuiID%:Add, Edit, xp y+2 wp hp vSwpGuiVal_Fingerprint
Gui %GuiID%:Font, s10 bold
Gui %GuiID%:Add, Edit, xp y+2 wp hp readonly center vSwpGuiVal_Key
Gui %GuiID%:Font, s10 norm
Gui %GuiID%:Add, Groupbox, xs ys-20 w352 h126
; Buttons
Gui %GuiID%:Add, Button, xs y+10 w109 h24 gSWP_RegisterDialogCancel , E&xit
Gui %GuiID%:Font, s10 bold
Gui %GuiID%:Add, Button, x+2 yp wp+20 hp default gSWP_KeygenGenerate , &Generate
Gui %GuiID%:Font, s10 norm
Gui %GuiID%:Add, Button, x+2 yp wp-20 h24 gSWP_KeygenOk, &Copy && Exit
Gui %GuiID%:Show, w372, Registration Key Generator
}
;-------------------------------------------------------------------------------
; Other GUI Functions (you should generally avoid calling these functions)
;-------------------------------------------------------------------------------
SWP_ShowRegisterDialog( appName ) {
Global SWP_GuiID ; *** TODO: See if there is a way to have a dynamically
; created 20GuiEscape labels, so we can pass GuiID as
; an optional parameter to the function
Global SWP_AppName, SwpGuiVal_Name, SwpGuiVal_Email, SwpGuiVal_Key
SWP_GuiID := 20
GuiID := SWP_GuiID
Gui %GuiID%:Margin, 10, 10
; Top introduction text
Gui %GuiID%:Font, s10 bold
Gui %GuiID%:Add, Text, x10 y10 w352 h22 center, %appName% is not registered.
Gui %GuiID%:Font, s10 norm
Gui %GuiID%:Add, Text, xp y+0 wp hp center, Please enter your registration details:
; Text labels
Gui %GuiID%:Add, Text, xp y+15 w135 h22 right section, % "Name/Company: "
Gui %GuiID%:Add, Text, xp y+2 wp hp right , % "Email Address: "
; Gui %GuiID%:Add, Text, xp Y+2 wp hp right , % "Registration Code: "
; Edit fields
Gui %GuiID%:Add, Edit, xs+137 ys wp+64 hp vSwpGuiVal_Name
Gui %GuiID%:Add, Edit, xp y+2 wp hp vSwpGuiVal_Email
; Gui %GuiID%:Add, Edit, xp y+2 wp hp vSwpGuiVal_Key
Gui %GuiID%:Add, Groupbox, xs ys-20 w352 h102
; Buttons
Gui %GuiID%:Add, Button, xs y+10 w268 h24 default gSWP_RegisterDialogGetKey , &Get a Registration Key (Internet Required)
Gui %GuiID%:Add, Button, x+2 yp w90 h24 gSWP_RegisterDialogCancel , E&xit
Gui %GuiID%:Font, s10 bold
; Gui %GuiID%:Add, Text, xp-250 yp+30, Have a registration key already? ->
; Gui %GuiID%:Add, Button, xp+250 yp w90 h24 gSWP_RegisterDialogOk, Register
Gui %GuiID%:Show, w372, %appName% Registration
}
20GuiEscape:
20GuiClose:
SWP_RegisterDialogCancel:
ExitApp
Return
SWP_RegisterDialogOk:
Gui %SWP_GuiID%:Submit, NoHide
If( SwpGuiVal_Name = "" or SwpGuiVal_Email = "" or SwpGuiVal_Key = "" )
MsgBox 16,Invalid Registration, Invalid Registration.`nPlease check your input.`t
Else If( Not SWP_IsUserAuthenticated( SwpGuiVal_Name, SwpGuiVal_Email, SwpGuiVal_Key ) ) {
MsgBox 16,Invalid Registration, Invalid Registration.`nPlease check your input.`t
}
Else {
; Registration ok, write to ini file and exit happily
IniWrite %SwpGuiVal_Name%, %SWP_IniFilename%, Registration, Name
IniWrite %SwpGuiVal_Email%, %SWP_IniFilename%, Registration, Email
IniWrite %SwpGuiVal_Key%, %SWP_IniFilename%, Registration, Key
MsgBox 64,Registration Accepted, Your registration was accepted and saved.`t`nThank you for using %SWP_AppName%.
SWP_LicenseOK := true
Gui %SWP_GuiID%:Destroy
}
Return
SWP_RegisterDialogOkAuto:
If( Not SWP_IsUserAuthenticated( SwpGuiVal_Name, SwpGuiVal_Email, SwpGuiVal_Key ) ) ; find these variables so we can set them upon post
{
MsgBox 16,Invalid Registration, Invalid Registration.`nCode Transfer Error`t
}
Else {
; Registration ok, write to ini file and exit happily
IniWrite %SwpGuiVal_Name%, %SWP_IniFilename%, Registration, Name
IniWrite %SwpGuiVal_Email%, %SWP_IniFilename%, Registration, Email
IniWrite %SwpGuiVal_Key%, %SWP_IniFilename%, Registration, Key
MsgBox 64,Registration Accepted, Your registration was accepted and saved.`t`nThank you for using %SWP_AppName%.
SWP_LicenseOK := true
}
Return
;Dont lose this variable %SwpGuiVal_Fingerprint%
SWP_RegisterDialogGetKey:
SWP_ShowGetKeyDialog()
URL =%Website%%SwpGuiVal_Name%%SwpGuiVal_Email%%SwpGuiVal_Fingerprint%
; MsgBox %URL% ;Enable when testing to check contents of variable
length := httpQuery(SwpGuiVal_Key2,URL)
varSetCapacity(SwpGuiVal_Key2,-1)
SwpGuiVal_Key = %SwpGuiVal_Key2% ; Swap the key to another variable so that all spaces are trimmed off properly
; MsgBox %SwpGuiVal_Key% ;Enable when testing to check contents of variable
GoTo SWP_RegisterDialogOkAuto
Return
SWP_ShowGetKeyDialog() {
Global SWP_GuiID, SWP_AppName, SwpGuiVal_Fingerprint, SwpGuiButton_Ok
,SWP_DeveloperEmail
Gui %SWP_GuiID%:Submit
; Destroy
Gui %SWP_GuiID%:Destroy
; Then rebuild
SwpGuiVal_Fingerprint := SWP_GetPcFingerprint()
GuiID := SWP_GuiID
;Instead of showing the GUI we will simply POST this to the PHP file.
; %SwpGuiVal_Fingerprint% ;This is the var with fingerprint
}
SWP_GetDialogOk:
Gui %SWP_GuiID%:Submit
Clipboard := "Computer ID: " SwpGuiVal_Fingerprint
MsgBox 64,Copied to Clipboard, Your Computer ID was copied to the clipboard.`nPlease send it along with your name and email address to`t`n%SWP_DeveloperEmail%.
ExitApp
Return
SWP_ReadRegFile( iniFilename ) {
Global SWP_LicenseOK
IniRead Name, %iniFilename%, Registration, Name
IniRead Email, %iniFilename%, Registration, Email
IniRead Key, %iniFilename%, Registration, Key
SWP_LicenseOK := false
If( Not SWP_IsUserAuthenticated( Name, Email, Key ) ) {
MsgBox 16,Invalid Registration, Your registration details seem to be invalid.`t`n
FileDelete %iniFilename%
Reload
}
SWP_LicenseOK := true
}
SWP_KeygenGenerate:
Gui %SWP_GuiID%:Submit, NoHide
SwpGuiVal_Key := SWP_GenerateKey( SwpGuiVal_Name, SwpGuiVal_Email, SwpGuiVal_Fingerprint )
GuiControl ,%SWP_GuiID%:,SwpGuiVal_Key,%SwpGuiVal_Key%
Return
SWP_KeygenOK:
Gui %SWP_GuiID%:Submit, NoHide
Clipboard =
( LTRIM
-----------------------------------
Username: %SwpGuiVal_Name%
Email: %SwpGuiVal_Email%
Key: %SwpGuiVal_Key%
-----------------------------------
)
Gui %SWP_GuiID%:Destroy
Return
;-------------------------------------------------------------------------------
; Revision History
;-------------------------------------------------------------------------------
/*
0.11 2007 09 04
- Added : Keygen
- Changed: Initialize function (secret seeds) now needs to be called
separately prior to calling any of the other main GUI functions.
This is done to allow different key generation for every software
you develop.
If this is not a requirement, the Initialize function can be put
back into the two main GUI functions (only make sure you are using
the same seeds)
0.10 2007 09 03
- First version
*/
; httpQuery-0-3-5.ahk
httpQuery(byref Result, lpszUrl, POSTDATA="", HEADERS="")
{ ; v0.3.5 (w) Sep, 8 2008 by Heresy & derRaphael / zLib-Style release
; updates Aug, 28 2008
; currently the verbs showHeader, storeHeader, and updateSize are supported in httpQueryOps
; in case u need a different UserAgent, Proxy, ProxyByPass, Referrer, and AcceptType just
; specify them as global variables - mind the varname for referrer is httpQueryReferer [sic].
; Also if any special dwFlags are needed such as INTERNET_FLAG_NO_AUTO_REDIRECT or cache
; handling this might be set using the httpQueryDwFlags variable as global
global httpQueryOps, httpAgent, httpProxy, httpProxyByPass, httpQueryReferer, httpQueryAcceptType
, httpQueryDwFlags
; Get any missing default Values
defaultOps =
(LTrim Join|
httpAgent=AutoHotkeyScript|httpProxy=0|httpProxyByPass=0|INTERNET_FLAG_SECURE=0x00800000
SECURITY_FLAG_IGNORE_UNKNOWN_CA=0x00000100|SECURITY_FLAG_IGNORE_CERT_CN_INVALID=0x00001000
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID=0x00002000|SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE=0x00000200
INTERNET_OPEN_TYPE_PROXY=3|INTERNET_OPEN_TYPE_DIRECT=1|INTERNET_SERVICE_HTTP=3
)
Loop,Parse,defaultOps,|
{
RegExMatch(A_LoopField,"(?P<Option>[^=]+)=(?P<Default>.*)",http)
if StrLen(%httpOption%)=0
%httpOption% := httpDefault
}
; Load Library
hModule := DllCall("LoadLibrary", "Str", "WinINet.Dll")
; SetUpStructures for URL_COMPONENTS / needed for InternetCrackURL
; http://msdn.microsoft.com/en-us/library/aa385420(VS.85).aspx
offset_name_length:= "4-lpszScheme-255|16-lpszHostName-1024|28-lpszUserName-1024|"
. "36-lpszPassword-1024|44-lpszUrlPath-1024|52-lpszExtrainfo-1024"
VarSetCapacity(URL_COMPONENTS,60,0)
; Struc Size ; Scheme Size ; Max Port Number
NumPut(60,URL_COMPONENTS,0), NumPut(255,URL_COMPONENTS,12), NumPut(0xffff,URL_COMPONENTS,24)
Loop,Parse,offset_name_length,|
{
RegExMatch(A_LoopField,"(?P<Offset>\d+)-(?P<Name>[a-zA-Z]+)-(?P<Size>\d+)",iCU_)
VarSetCapacity(%iCU_Name%,iCU_Size,0)
NumPut(&%iCU_Name%,URL_COMPONENTS,iCU_Offset)
NumPut(iCU_Size,URL_COMPONENTS,iCU_Offset+4)
}
; Split the given URL; extract scheme, user, pass, authotity (host), port, path, and query (extrainfo)
; http://msdn.microsoft.com/en-us/library/aa384376(VS.85).aspx
DllCall("WinINet\InternetCrackUrlA","Str",lpszUrl,"uInt",StrLen(lpszUrl),"uInt",0,"uInt",&URL_COMPONENTS)
; Update variables to retrieve results
Loop,Parse,offset_name_length,|
{
RegExMatch(A_LoopField,"-(?P<Name>[a-zA-Z]+)-",iCU_)
VarSetCapacity(%iCU_Name%,-1)
}
nPort:=NumGet(URL_COMPONENTS,24,"uInt")
; Import any set dwFlags
dwFlags := httpQueryDwFlags
; For some reasons using a selfsigned https certificates doesnt work
; such as an own webmin service - even though every security is turned off
; https with valid certificates works when
if (lpszScheme = "https")
dwFlags |= (INTERNET_FLAG_SECURE|SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)
; Check for Header and drop exception if unknown or invalid URL
if (lpszScheme="unknown") {
Result := "ERR: No Valid URL supplied."
Return StrLen(Result)
}
; Initialise httpQuery's use of the WinINet functions.
; http://msdn.microsoft.com/en-us/library/aa385096(VS.85).aspx
hInternet := DllCall("WinINet\InternetOpenA"
,"Str",httpAgent,"UInt"
,(httpProxy != 0 ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_DIRECT )
,"Str",httpProxy,"Str",httpProxyBypass,"Uint",0)
; Open HTTP session for the given URL
; http://msdn.microsoft.com/en-us/library/aa384363(VS.85).aspx
hConnect := DllCall("WinINet\InternetConnectA"
,"uInt",hInternet,"Str",lpszHostname, "Int",nPort
,"Str",lpszUserName, "Str",lpszPassword,"uInt",INTERNET_SERVICE_HTTP
,"uInt",0,"uInt*",0)
; Do we POST? If so, check for header handling and set default
if (Strlen(POSTDATA)>0) {
HTTPVerb:="POST"
if StrLen(Headers)=0
Headers:="Content-Type: application/x-www-form-urlencoded"
} else ; otherwise mode must be GET - no header defaults needed
HTTPVerb:="GET"
; Form the request with proper HTTP protocol version and create the request handle
; http://msdn.microsoft.com/en-us/library/aa384233(VS.85).aspx
hRequest := DllCall("WinINet\HttpOpenRequestA"
,"uInt",hConnect,"Str",HTTPVerb,"Str",lpszUrlPath . lpszExtrainfo
,"Str",ProVer := "HTTP/1.1", "Str",httpQueryReferer,"Str",httpQueryAcceptTypes
,"uInt",dwFlags,"uInt",Context:=0 )
; Send the specified request to the server
; http://msdn.microsoft.com/en-us/library/aa384247(VS.85).aspx
sRequest := DllCall("WinINet\HttpSendRequestA"
, "uInt",hRequest,"Str",Headers, "uInt",Strlen(Headers)
, "Str",POSTData,"uInt",Strlen(POSTData))
VarSetCapacity(header, 2048, 0) ; max 2K header data for httpResponseHeader
VarSetCapacity(header_len, 4, 0)
; Check for returned server response-header (works only _after_ request been sent)
; http://msdn.microsoft.com/en-us/library/aa384238.aspx
Loop, 5
if ((headerRequest:=DllCall("WinINet\HttpQueryInfoA","uint",hRequest
,"uint",21,"uint",&header,"uint",&header_len,"uint",0))=1)
break
If (headerRequest=1) {
VarSetCapacity(res,headerLength:=NumGet(header_len),32)
DllCall("RtlMoveMemory","uInt",&res,"uInt",&header,"uInt",headerLength)
Loop,% headerLength
if (*(&res-1+a_index)=0) ; Change binary zero to linefeed
NumPut(Asc("`n"),res,a_index-1,"uChar")
VarSetCapacity(res,-1)
} else
res := "timeout"
; Get 1st Line of Full Response
Loop,Parse,res,`n,`r
{
RetValue := A_LoopField
break
}
; No Connection established - drop exception
If (RetValue="timeout") {
html := "Error: timeout"
return -1
}
; Strip protocol version from return value
RetValue := RegExReplace(RetValue,"HTTP/1\.[01]\s+")
; List taken from http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
HttpRetCodes := "100=Continue|101=Switching Protocols|102=Processing (WebDAV) (RFC 2518)|"
. "200=OK|201=Created|202=Accepted|203=Non-Authoritative Information|204=No"
. " Content|205=Reset Content|206=Partial Content|207=Multi-Status (WebDAV)"
. "|300=Multiple Choices|301=Moved Permanently|302=Found|303=See Other|304="
. "Not Modified|305=Use Proxy|306=Switch Proxy|307=Temporary Redirect|400=B"
. "ad Request|401=Unauthorized|402=Payment Required|403=Forbidden|404=Not F"
. "ound|405=Method Not Allowed|406=Not Acceptable|407=Proxy Authentication "
. "Required|408=Request Timeout|409=Conflict|410=Gone|411=Length Required|4"
. "12=Precondition Failed|413=Request Entity Too Large|414=Request-URI Too "
. "Long|415=Unsupported Media Type|416=Requested Range Not Satisfiable|417="
. "Expectation Failed|418=I'm a teapot (RFC 2324)|422=Unprocessable Entity "
. "(WebDAV) (RFC 4918)|423=Locked (WebDAV) (RFC 4918)|424=Failed Dependency"
. " (WebDAV) (RFC 4918)|425=Unordered Collection (RFC 3648)|426=Upgrade Req"
. "uired (RFC 2817)|449=Retry With|500=Internal Server Error|501=Not Implem"
. "ented|502=Bad Gateway|503=Service Unavailable|504=Gateway Timeout|505=HT"
. "TP Version Not Supported|506=Variant Also Negotiates (RFC 2295)|507=Insu"
. "fficient Storage (WebDAV) (RFC 4918)|509=Bandwidth Limit Exceeded|510=No"
. "t Extended (RFC 2774)"
; Gather numeric response value
RetValue := SubStr(RetValue,1,3)
; Parse through return codes and set according informations
Loop,Parse,HttpRetCodes,|
{
HttpReturnCode := SubStr(A_LoopField,1,3) ; Numeric return value see above
HttpReturnMsg := SubStr(A_LoopField,5) ; link for additional information
if (RetValue=HttpReturnCode) {
RetMsg := HttpReturnMsg
break
}
}
; Global HttpQueryOps handling
if strlen(HTTPQueryOps)>0 {
; Show full Header response (usefull for debugging)
if (instr(HTTPQueryOps,"showHeader"))
MsgBox % res
; Save the full Header response in a global Variable
if (instr(HTTPQueryOps,"storeHeader"))
global HttpQueryHeader := res
; Check for size updates to export to a global Var
if (instr(HTTPQueryOps,"updateSize")) {
Loop,Parse,res,`n
If RegExMatch(A_LoopField,"Content-Length:\s+?(?P<Size>\d+)",full) {
global HttpQueryFullSize := fullSize
break
}
if (fullSize+0=0)
HttpQueryFullSize := "size unavailable"
}
}
; Check for valid codes and drop exception if suspicious
if !(InStr("100 200 201 202 302",RetValue)) {
Result := RetValue " " RetMsg
return StrLen(Result)
}
VarSetCapacity(BytesRead,4,0)
fsize := 0
Loop ; the receiver loop - rewritten in the need to enable
{ ; support for larger file downloads
bc := A_Index
VarSetCapacity(buffer%bc%,1024,0) ; setup new chunk for this receive round
ReadFile := DllCall("wininet\InternetReadFile"
,"uInt",hRequest,"uInt",&buffer%bc%,"uInt",1024,"uInt",&BytesRead)
ReadBytes := NumGet(BytesRead) ; how many bytes were received?
If ((ReadFile!=0)&&(!ReadBytes)) ; we have had no error yet and received no more bytes
break ; we must be done! so lets break the receiver loop
Else {
fsize += ReadBytes ; sum up all chunk sizes for correct return size
sizeArray .= ReadBytes "|"
}
if (instr(HTTPQueryOps,"updateSize"))
Global HttpQueryCurrentSize := fsize
}
sizeArray := SubStr(sizeArray,1,-1) ; trim last PipeChar
VarSetCapacity(result,fSize+1,0) ; reconstruct the result from above generated chunkblocks
Dest := &result ; to a our ByRef result variable
Loop,Parse,SizeArray,|
DllCall("RtlMoveMemory","uInt",Dest,"uInt",&buffer%A_Index%,"uInt",A_LoopField)
, Dest += A_LoopField
DllCall("WinINet\InternetCloseHandle", "uInt", hRequest) ; close all opened
DllCall("WinINet\InternetCloseHandle", "uInt", hInternet)
DllCall("WinINet\InternetCloseHandle", "uInt", hConnect)
DllCall("FreeLibrary", "UInt", hModule) ; unload the library
return fSize ; return the size - strings need update via VarSetCapacity(res,-1)
}
And here is validate.php
Code:
<?php
\\ validate.php
SWP_Initialize(0x81645732,0x19573549);
$str=$_GET['code'];
$key=XCBC($str);
echo $key;
function XCBC($str)
{
global $str,$u,$v,$l0,$l1,$m0,$m1;
$u=0;
$v=0;
$str = bin2hex($str);
// full length intermediate message blocks
$flimbs = ceil(strlen($str)/16)-1;
for($i=0; $i<$flimbs; $i+=1)
{
XCBCstep();
}
if (strlen($str)==16)
{
$u = $u ^ $l0;
$v = $v ^ $l1;
XCBCstep();
}else{
$u = $u ^ $m0;
$v = $v ^ $m1;
$str = $str."100000000000000";
XCBCstep();
}
$u = dechex($u);
$v = dechex($v);
while (strlen($u) < 8) { $u='0'.$u; }
while (strlen($v) < 8) { $v='0'.$v; }
return $u.$v;
}
function XTEA()
{
global $u,$v,$key;
$s = 0;
$d = 0x9e3779b9;
for($i=0; $i<32;$i++)
{
$u = _add($u ,_add($v << 4 ^ _rshift($v,5), $v) ^ _add($s,$key[$s & 3] ) );
$s = ($s + $d) ;
$s= 0xffffffff & $s ;
$v = _add($v ,_add($u << 4 ^ _rshift($u,5), $u) ^ _add($s,$key[_rshift($s, 11) & 3]));
}
return;
}
function XCBCstep()
{
global $u,$v,$str;
$p = substr($str,0,8);
$q = substr($str,8,8);
$str = substr($str,16);
$p=hexdec($p);
$q=hexdec($q);
$u = $u ^ $p;
$v = $v ^ $q;
XTEA();
return;
}
function _add($i1, $i2) {
$result = 0.0;
foreach (func_get_args() as $value)
{
if (0.0 > $value) {
$value -= 1.0 + 0xffffffff;
}
$result += $value;
}
// convert to 32 bits
if (0xffffffff < $result || -0xffffffff > $result) {
$result = fmod($result, 0xffffffff + 1);
}
// convert to signed integer
if (0x7fffffff < $result) {
$result -= 0xffffffff + 1.0;
} elseif (-0x80000000 > $result) {
$result += 0xffffffff + 1.0;
}
return $result;
}
function hex2bin($h)
{
if (!is_string($h)) return null;
$r='';
for ($a=0; $a<strlen($h); $a+=2) { $r.=chr(hexdec($h{$a}.$h{($a+1)})); }
return $r;
}
function _rshift($integer, $n) {
// convert to 32 bits
if (0xffffffff < $integer || -0xffffffff > $integer) {
$integer = fmod($integer, 0xffffffff + 1);
}
// convert to unsigned integer
if (0x7fffffff < $integer) {
$integer -= 0xffffffff + 1.0;
} elseif (-0x80000000 > $integer) {
$integer += 0xffffffff + 1.0;
}
// do right shift
if (0 > $integer) {
$integer &= 0x7fffffff; // remove sign bit before shift
$integer >>= $n; // right shift
$integer |= 1 << (31 - $n); // set shifted sign bit
} else {
$integer >>= $n; // use normal right shift
}
return $integer;
}
function SWP_Initialize($mk0=0x11111111, $mk1=0x22222222, $mk2=0x33333333, $mk3=0x44444444 ,$ml0=0x12345678,$ml1=0x12345678,$mm0=0x87654321, $mm1=0x87654321)
{
global $l0,$l1,$m0,$m1 ,$key;
$key[0] = $mk0;
$key[1] = $mk1;
$key[2] = $mk2;
$key[3] = $mk3;
$l0 = $ml0;
$l1 = $ml1;
$m0 = $mm0;
$m1 = $mm1;
return;
}
?>
Just in case you dont have it, here is the include file you will need.
SWProtect-Internal.ahk
Code:
; SWProtect-Internal.ahk
;-------------------------------------------------------------------------------
;
; Software Protection Library 0.12
;
; This library contains a set of functions to generate a registration key
; based on a user fingerprint.
; To be used separately or together with the GUI library - SWProtect-GUI.ahk
;
; Original Code: Laszlo Hars <www.Hars.US>
; Library Version: Icarus
; modifications: guest3456 (see changelog at bottom)
;
; Original proof of concept by Laszlo, taken from AutoHotkey Forum at
; http://www.autohotkey.com/forum/viewtopic.php?t=5763&postdays=0&postorder=asc&start=0
;
;
; Functions in this version
;
; SWP_Initialize( [ secret1, secret 2, ... , secret 8 ] )
; Fingerprint := SWP_GetPcFingerprint()
; UserOK := SWP_IsUserAuthenticated( username, email, key )
; Key := SWP_GenerateKey( username, email, fingerprint )
;
;-------------------------------------------------------------------------------
#NoEnv
;-------------------------------------------------------------------------------
; TESTER - Comment or delete this tester when including the file
;
/*
; Initialize the required globals
;----------------------------------------
SWP_Initialize() ; May be called with up to 8 secret keys
; Get a hardware fingerprint
;----------------------------------------
Fingerprint := SWP_GetPcFingerprint()
MsgBox 32,,Your computer ID is`n%Fingerprint%
; Generate a license key for this user
;----------------------------------------
Username := "Icarus"
Email := "Icarus@Sky.com"
Key := SWP_GenerateKey( Username, Email, Fingerprint )
MsgBox 32,,Your registration details are:`nUser:`t%Username%`nEmail:`t%Email%`nKey:`t%Key%
; Check if a user's registration code is ok
;----------------------------------------
;Key := "some invalid key by the user" ; Uncomment to test
UserOK := SWP_IsUserAuthenticated( Username, Email, Key )
If( UserOK )
MsgBox 32,OK,User is authenticated
Else
MsgBox 16,INVALID,User is NOT authenticated`n%Username%`n%Email%`n%Key%
Return
*/
;
; END OF TESTER
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; API Functions
;-------------------------------------------------------------------------------
;
; SWP_Initialize( [ secret1, secret 2, ... , secret 8 ] )
; Fingerprint := SWP_GetPcFingerprint()
; UserOK := SWP_IsUserAuthenticated( username, email, key )
; Key := SWP_GenerateKey( username, email, fingerprint )
;
;-------------------------------------------------------------------------------
SWP_Initialize( mk0=0x11111111, mk1=0x22222222, mk2=0x33333333, mk3=0x44444444
,ml0=0x12345678, ml1=0x12345678, mm0=0x87654321, mm1=0x87654321 ) {
Global
k0 := mk0 ; 128-bit secret key (example)
k1 := mk1
k2 := mk2
k3 := mk3
l0 := ml0 ; 64- bit 2nd secret key (example)
l1 := ml1
m0 := mm0 ; 64- bit 3rd secret key (example)
m1 := mm1
}
SWP_GetPcFingerprint() {
EnvGet, COMPUTERNAME, COMPUTERNAME
EnvGet, HOMEPATH, HOMEPATH
EnvGet, USERNAME, USERNAME
EnvGet, PROCESSOR_ARCHITECTURE, PROCESSOR_ARCHITECTURE
EnvGet, PROCESSOR_IDENTIFIER, PROCESSOR_IDENTIFIER
EnvGet, PROCESSOR_LEVEL, PROCESSOR_LEVEL
EnvGet, PROCESSOR_REVISION, PROCESSOR_REVISION
PCdata = %COMPUTERNAME%%HOMEPATH%%USERNAME%%PROCESSOR_ARCHITECTURE%%PROCESSOR_IDENTIFIER%
PCdata = %PCdata%%PROCESSOR_LEVEL%%PROCESSOR_REVISION%%A_OSType%%A_OSVersion%%Language%
Fingerprint := XCBC(Hex(PCdata,StrLen(PCdata)), 0,0, 0,0,0,0, 1,1, 2,2)
Return Fingerprint
}
SWP_GenerateKey( username, email, fingerprint ) {
Global k0,k1,k2,k3,l0,l1,m0,m1
If( not k0 ) {
MsgBox 16,Error,Error in SWP_GenerateKey - values are not initialized.`nPlease call SWP_Initialize() first.
Return false
}
Together = %username%%email%%fingerprint%
Auth := XCBC(Hex(Together,StrLen(Together)), 0,0, k0,k1,k2,k3, l0,l1, m0,m1)
Return Auth
}
SWP_IsUserAuthenticated( username, email, key ) {
Global k0,k1,k2,k3,l0,l1,m0,m1
If( not k0 ) {
MsgBox 16,Error,Error in SWP_IsUserAuthenticated - values are not initialized.`nPlease call SWP_Initialize() first.
Return false
}
Fingerprint := SWP_GetPcFingerprint()
Together = %username%%email%%Fingerprint%
AuthData := XCBC(Hex(Together,StrLen(Together)), 0,0, k0,k1,k2,k3, l0,l1, m0,m1)
Return Key=AuthData
}
;-------------------------------------------------------------------------------
; Internal Functions by Laszlo
;-------------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TEA cipher ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Block encryption with the TEA cipher
; [y,z] = 64-bit I/0 block
; [k0,k1,k2,k3] = 128-bit key
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TEA(ByRef y,ByRef z, k0,k1,k2,k3)
{ ; need SetFormat Integer, D
s = 0
d = 0x9E3779B9
Loop 32 ; could be reduced to 8 for speed
{
k := "k" . s & 3 ; indexing the key
y := 0xFFFFFFFF & (y + ((z << 4 ^ z >> 5) + z ^ s + %k%))
s := 0xFFFFFFFF & (s + d) ; simulate 32 bit operations
k := "k" . s >> 11 & 3
z := 0xFFFFFFFF & (z + ((y << 4 ^ y >> 5) + y ^ s + %k%))
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; XCBC-MAC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; x = long hex string input
; [u,v] = 64-bit initial value (0,0)
; [k0,k1,k2,k3] = 128-bit key
; [l0,l1] = 64-bit key for not padded last block
; [m0,m1] = 64-bit key for padded last block
; Return 16 hex digits (64 bits) digest
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
XCBC(x, u,v, k0,k1,k2,k3, l0,l1, m0,m1)
{
Loop % Ceil(StrLen(x)/16)-1 ; full length intermediate message blocks
XCBCstep(u, v, x, k0,k1,k2,k3)
If (StrLen(x) = 16) ; full length last message block
{
u := u ^ l0 ; l-key modifies last state
v := v ^ l1
XCBCstep(u, v, x, k0,k1,k2,k3)
}
Else { ; padded last message block
u := u ^ m0 ; m-key modifies last state
v := v ^ m1
x = %x%100000000000000
XCBCstep(u, v, x, k0,k1,k2,k3)
}
Return Hex8(u) . Hex8(v) ; 16 hex digits returned
}
XCBCstep(ByRef u, ByRef v, ByRef x, k0,k1,k2,k3)
{
StringLeft p, x, 8 ; Msg blocks
StringMid q, x, 9, 8
StringTrimLeft x, x, 16
p = 0x%p%
q = 0x%q%
u := u ^ p
v := v ^ q
TEA(u,v,k0,k1,k2,k3)
}
Hex8(i) ; 32-bit integer -> 8 hex digits
{
format = %A_FormatInteger% ; save original integer format
SetFormat Integer, Hex
i += 0x100000000 ; convert to hex, set MS bit
StringTrimLeft i, i, 3 ; remove leading 0x1
SetFormat Integer, %format% ; restore original format
Return i
}
Hex(ByRef b, n=0) ; n bytes data -> stream of 2-digit hex
{ ; n = 0: all (SetCapacity can be larger than used!)
format = %A_FormatInteger% ; save original integer format
SetFormat Integer, Hex ; for converting bytes to hex
m := VarSetCapacity(b)
If (n < 1 or n > m)
n := m
Loop %n%
{
x := 256 + *(&b+A_Index-1) ; get byte in hex, set 17th bit
StringTrimLeft x, x, 3 ; remove 0x1
h = %h%%x%
}
SetFormat Integer, %format% ; restore original format
Return h
}
;-------------------------------------------------------------------------------
; Revision History
;-------------------------------------------------------------------------------
/*
0.12 2010-04-29
- guest3456: changed script to use #NoEnv and GetFingerprint to use EnvGet
to solve this bug: http://www.autohotkey.com/forum/post-347395.html#347395
0.11 2007 09 04
- Fixed : IsUserAuthenticated returned -1 in case of an uninitialized
globals, now returning false.
0.10 2007 09 03
- First version
*/
Ive been thinking it might be nice to have some sort of more advanced php system. Could have people register on your site with a username / password that they would enter instead of their Name and Email address. Have the php store that along with the fingerprint / regkey, and have the program check everytime it runs. If the fingerprint doesnt match the one on file, then they are trying to use their username/password on a different computer. I might have to learn php lol.