785 lines
30 KiB
Plaintext
785 lines
30 KiB
Plaintext
// This code contains the following functions. Please choose the one that matches your needs:
|
|
// ProtCheck
|
|
// ProtCheckWithAlg (the function also depends on the function MyAlgorithm)
|
|
// WriteString
|
|
// ReadString
|
|
// EncryptUserData
|
|
// or the same functions but using DRIS and API data encryption
|
|
// (these functions also require the functions CryptDRIS and possibly CryptApiData and MyRWAlgorithm)
|
|
// ProtCheckEnc
|
|
// ProtCheckWithAlgEnc
|
|
// WriteStringEnc
|
|
// ReadStringEnc
|
|
// EncryptUserDataEnc
|
|
|
|
|
|
// Summary: does a standard protection check
|
|
// Syntax:
|
|
//[ <Result> = ] ProtCheck ()
|
|
// return value is 0 (success) or an error code
|
|
PROCEDURE ProtCheck()
|
|
hLib, ret_code are system int
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = PROTECTION_CHECK // standard protection check
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked!")
|
|
|
|
// Summary: does a standard protection check and executes an algorithm
|
|
// NB for this to work you must program at least "user algorithm" into the dongle
|
|
// NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the
|
|
// sample code generated by DinkeyAdd for the algorithm that you are using. For Lite models copy the sample
|
|
// code from DinkeyLook
|
|
// Syntax:
|
|
//[ <Result> = ] ProtCheckWithAlg ()
|
|
// return value is 0 (success) or an error code
|
|
PROCEDURE ProtCheckWithAlg()
|
|
hLib, ret_code are system int
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = EXECUTE_ALGORITHM // protection check and execute specified algorithm
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.alg_number = 1
|
|
// !!!! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
|
DRIS.var_a = 1 // sample values
|
|
DRIS.var_b = 2
|
|
DRIS.var_c = 3
|
|
DRIS.var_d = 4
|
|
DRIS.var_e = 5
|
|
DRIS.var_f = 6
|
|
DRIS.var_g = 7
|
|
DRIS.var_h = 8
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
DelayBeforeClosing(1000)
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
// if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code
|
|
// !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd
|
|
IF (MyAlgorithm(DRIS.var_a, DRIS.var_b, DRIS.var_c, DRIS.var_d, DRIS.var_e, DRIS.var_f, DRIS.var_g, DRIS.var_h) <> DRIS.alg_answer) THEN
|
|
Info("Dinkey protection error!", "You have not patched your algorithm in the MyAlgorithm routine")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked!")
|
|
|
|
// Summary:
|
|
// !!!! You should replace this function with the one generated by the
|
|
// "generate source code" button in Algorithm tab for DinkeyAdd (if you have specified an algorithm)
|
|
// or from DinkeyLook if you are using a Dinkey Lite dongle. You can modify the C code to make it compatiable with Windev.
|
|
// Syntax:
|
|
//[ <Result> = ] MyAlgorithm (<var_a> is int, <var_b> is int, <var_c> is int, <var_d> is int, <var_e> is int, <var_f> is int, <var_g> is int, <var_h> is int)
|
|
//
|
|
PROCEDURE MyAlgorithm(var_a is int, var_b is int, var_c is int, var_d is int, var_e is int, var_f is int, var_g is int, var_h is int)
|
|
RESULT var_a + var_b + var_c + var_d + var_e + var_f + var_g + var_h
|
|
|
|
|
|
// Summary: This function does a protection check and writes the string "Hello, World!" to the data area at offset 7
|
|
// In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
// NB you can easily modify the code to write a byte array instead of a string
|
|
// Syntax:
|
|
//[ <Result> = ] WriteString ()
|
|
// return value is 0 (success) or an error code
|
|
//
|
|
PROCEDURE WriteString()
|
|
hLib, ret_code are system int
|
|
OurString is fixed string on 1024 = "Hello, World!" // NB max. data write is 1K
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = WRITE_DATA_AREA // protection check and write specified data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.rw_offset = 7
|
|
DRIS.rw_length = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
|
|
DRIS.rw_data_ptr = &OurString
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked!")
|
|
|
|
|
|
// Summary: This function does a protection check and reads 13 bytes of data from the data area at offset 7
|
|
// In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
// NB you can amend this code to read a byte array instead of a string if you prefer.
|
|
// Syntax:
|
|
//[ <Result> = ] ReadString ()
|
|
// return value is 0 (success) or an error code
|
|
//
|
|
PROCEDURE ReadString()
|
|
hLib, ret_code are system int
|
|
OurString is fixed string on 1024 // NB max. data read is 1K
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = READ_DATA_AREA // protection check and read data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.rw_offset = 7
|
|
DRIS.rw_length = 13
|
|
DRIS.rw_data_ptr = &OurString
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
|
|
|
|
|
|
// Summary: this function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
|
// It will then do another protection check & decrypt the data. NB you can modify the code to encrypt byte arrays instead of strings
|
|
// NB you can amend this code to read a byte array instead of a string if you prefer.
|
|
// Syntax:
|
|
//[ <Result> = ] EncryptUserData ()
|
|
// return value is 0 (success) or an error code
|
|
//
|
|
PROCEDURE EncryptUserData()
|
|
hLib, ret_code are system int
|
|
OurString is fixed string on 1024 = "Hello, World!" // NB max. data we can encrypt is 1K
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = ENCRYPT_USER_DATA // protection check and encrypt specified data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.data_crypt_key_num = 1
|
|
DRIS.rw_length = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
|
|
DRIS.rw_data_ptr = &OurString
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
FreeDLL(hLib)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
|
|
|
|
// Now decrypt the same data to get the original values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = DECRYPT_USER_DATA // protection check and decrypt specified data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.data_crypt_key_num = 1
|
|
DRIS.rw_length = 13 // the length of the string (in this case 13 bytes)
|
|
DRIS.rw_data_ptr = &OurString // NB the data is encrypted at this point
|
|
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
|
|
|
|
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
|
|
|
|
|
|
// !!!!!!!!!!! all the functions listed below encrypt all parameters to our API !!!!!!!!!!!!!!!!!!!!!
|
|
// In order for them to work properly you need to choose "Encrypt DRIS" and "Encrypt Data passed to API"
|
|
// in the Extra Security tab of DinkeyAdd. In this example, for Data Encryption I use the r/w algorithm
|
|
// but the code can be modified easily to use the 3 encryption parameters.
|
|
|
|
// !!!! please overwrite this function with the one generated by DinkeyAdd for R/W Algorithm (you will have to adapt the C code generated by DinkeyAdd)
|
|
PROCEDURE MyRWAlgorithm(var_a is int, var_b is int, var_c is int, var_d is int, var_e is int, var_f is int, nVar_g is int, nVar_h is int)
|
|
RESULT BinaryXOR(BinaryXOR(BinaryXOR(BinaryXOR(BinaryXOR(var_a, var_b), var_c), var_d), var_e), var_f)
|
|
|
|
// !!!! please overwrite this function with the one generated by DinkeyAdd
|
|
// (just modify the parameters specified in DinkeyAdd in the positiions indicated below):
|
|
// Note arrays in Windev are 1-base which makes it a real pain
|
|
PROCEDURE CryptDRIS()
|
|
i, j, k are int
|
|
bigseed, S are array of 256 1-byte unsigned int
|
|
DRIS_bytes is an array of Length(DRIS) 1-byte unsigned int
|
|
temp, t are 1-byte unsigned int
|
|
|
|
FOR i = 1 _TO_ 256 STEP 8
|
|
Transfer(&bigseed[i], &DRIS.seed1, 4)
|
|
Transfer(&bigseed[i+4], &DRIS.seed2, 4)
|
|
END
|
|
|
|
FOR i = 0 _TO_ 255
|
|
S[i+1] = i
|
|
END
|
|
|
|
j = 0
|
|
FOR i = 0 _TO_ 255
|
|
j = (j + S[i+1] + bigseed[i+1] + 123) modulo 256 // parameter 1, modify 123
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
END
|
|
|
|
Transfer(&DRIS_bytes, &DRIS, Length(DRIS)) // convert DRIS to bytes
|
|
|
|
i = 0
|
|
j = 0
|
|
FOR k = 17 _TO_ Length(DRIS)
|
|
i = (i + 1) modulo 256
|
|
j = (j + S[i+1] + 212) modulo 256 // parameter 2, modify 212
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
t = (S[i+1] + S[j+1] + 97) modulo 256 // parameter 3, modify 97
|
|
DRIS_bytes[k] = BinaryXOR(DRIS_bytes[k], S[t+1])
|
|
END
|
|
|
|
Transfer(&DRIS, &DRIS_bytes, Length(DRIS)) // convert back again
|
|
|
|
|
|
|
|
// Note arrays in Windev are 1-base which makes it a real pain
|
|
// Summary: <specify the procedure action>
|
|
// Syntax:
|
|
//CryptApiData (<data>, <enc_length> is 4-byte unsigned int, <alg_ans> is int)
|
|
PROCEDURE CryptApiData(data, enc_length is unsigned int, alg_ans is int)
|
|
i, j, k are int
|
|
bigseed, S are array of 256 1-byte unsigned int
|
|
temp, t are 1-byte unsigned int
|
|
|
|
FOR i = 1 _TO_ 256 STEP 8
|
|
Transfer(&bigseed[i], &DRIS.seed1, 4)
|
|
Transfer(&bigseed[i+4], &DRIS.seed2, 4)
|
|
END
|
|
|
|
FOR i = 0 _TO_ 255
|
|
S[i+1] = i
|
|
END
|
|
|
|
j = 0
|
|
FOR i = 0 _TO_ 255
|
|
j = (j + S[i+1] + bigseed[i+1] + BinaryAND(alg_ans, 0xff)) modulo 256
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
END
|
|
|
|
i = 0
|
|
j = 0
|
|
FOR k = 1 _TO_ enc_length
|
|
i = (i + 1) modulo 256
|
|
j = (j + S[i+1] + (BinaryAND(alg_ans, 0xff00))/256) modulo 256
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
t = (S[i+1] + S[j+1] + (BinaryAND(alg_ans, 0xff0000))/65536) modulo 256
|
|
data[k] = BinaryXOR(data[k], S[t+1])
|
|
END
|
|
|
|
|
|
// Summary: does a standard protection check and encrypt the DRIS we pass and from the API.
|
|
// We encrypt the DRIS passed to the API. !!!! Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
|
|
// Syntax:
|
|
//[ <Result> = ] ProtCheckEnc ()
|
|
// return value is 0 (success) or an error code
|
|
PROCEDURE ProtCheckEnc()
|
|
hLib, ret_code are system int
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = PROTECTION_CHECK // standard protection check
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked!")
|
|
|
|
|
|
// Summary: does a standard protection check and executes an algorithm and encrypts the DRIS
|
|
// NB for this to work you must program at least one "user algorithm" into the dongle
|
|
// NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the
|
|
// sample code generated by DinkeyAdd for the algorithm that you are using. For Lite models copy the sample
|
|
// code from DinkeyLook.
|
|
// We encrypt the DRIS passed to the API. !!!! Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
|
|
// Syntax:
|
|
//[ <Result> = ] ProtCheckWithAlgEnc ()
|
|
// return value is 0 (success) or an error code
|
|
PROCEDURE ProtCheckWithAlgEnc()
|
|
hLib, ret_code are system int
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = EXECUTE_ALGORITHM // protection check and execute specified algorithm
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.alg_number = 1
|
|
// !!!! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
|
DRIS.var_a = 1 // sample values
|
|
DRIS.var_b = 2
|
|
DRIS.var_c = 3
|
|
DRIS.var_d = 4
|
|
DRIS.var_e = 5
|
|
DRIS.var_f = 6
|
|
DRIS.var_g = 7
|
|
DRIS.var_h = 8
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
DelayBeforeClosing(1000)
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
// if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code
|
|
// !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd
|
|
IF (MyAlgorithm(DRIS.var_a, DRIS.var_b, DRIS.var_c, DRIS.var_d, DRIS.var_e, DRIS.var_f, DRIS.var_g, DRIS.var_h) <> DRIS.alg_answer) THEN
|
|
Info("Dinkey protection error!", "You have not patched your algorithm in the MyAlgorithm routine")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked!")
|
|
|
|
|
|
// Summary: This function does a protection check and writes the string "Hello, World!" to the data area at offset 7
|
|
// In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
// NB you can easily modify the code to write a byte array instead of a string
|
|
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
|
|
// Syntax:
|
|
//[ <Result> = ] WriteStringEnc ()
|
|
// return value is 0 (success) or an error code
|
|
//
|
|
PROCEDURE WriteStringEnc()
|
|
hLib, ret_code are system int
|
|
alg_ans are int
|
|
OurString is fixed string on 1024 = "Hello, World!" // NB max. data write is 1K
|
|
OurString_bytes is array of 1024 1-byte unsigned int // byte-array of the encrypted string
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = WRITE_DATA_AREA // protection check and write specified data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.rw_offset = 7
|
|
DRIS.rw_length = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
|
|
DRIS.rw_data_ptr = &OurString_bytes // we convert the string to write to a byte array (so we can encrypt it) and then we pass that value to our API
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
|
|
alg_ans = MyRWAlgorithm(DRIS.var_a, DRIS.var_b, DRIS.var_c, DRIS.var_d, DRIS.var_e, DRIS.var_f, DRIS.var_g, DRIS.var_h)
|
|
|
|
// encrypt data we want to write (we must first convert it to a byte array so we can encrypt)
|
|
Transfer(&OurString_bytes, &OurString, DRIS.rw_length)
|
|
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
|
|
|
|
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
Info("It worked!")
|
|
|
|
|
|
// Summary: This function does a protection check and reads 13 bytes of data from the data area at offset 7
|
|
// In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
// NB you can amend this code to read a byte array instead of a string if you prefer.
|
|
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
|
|
// Syntax:
|
|
//[ <Result> = ] ReadStringEnc ()
|
|
// return value is 0 (success) or an error code
|
|
//
|
|
PROCEDURE ReadStringEnc()
|
|
hLib, ret_code are system int
|
|
alg_ans are int
|
|
OurString is fixed string on 1024 // NB max. data read is 1K
|
|
OurString_bytes is array of 1024 1-byte unsigned int // byte-array of the encrypted string
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = READ_DATA_AREA // protection check and read data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.rw_offset = 7
|
|
DRIS.rw_length = 13
|
|
DRIS.rw_data_ptr = &OurString_bytes // read it to our byte array first and then convert to a string
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
|
|
alg_ans = MyRWAlgorithm(DRIS.var_a, DRIS.var_b, DRIS.var_c, DRIS.var_d, DRIS.var_e, DRIS.var_f, DRIS.var_g, DRIS.var_h)
|
|
|
|
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// later in your code you can check other values in the DRIS...
|
|
IF (DRIS.sdsn <> MY_SDSN) THEN
|
|
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
RESULT -1
|
|
END
|
|
|
|
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
|
|
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
|
|
RESULT -1
|
|
END
|
|
|
|
// later on in your program you can check the return code again
|
|
IF (DRIS.ret_code <> 0) THEN
|
|
Info("Dinkey Dongle protection error")
|
|
RESULT -1
|
|
END
|
|
|
|
// decrypt data we have just read (then convert to string)
|
|
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
|
|
Transfer(&OurString, &OurString_bytes, DRIS.rw_length)
|
|
|
|
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
|
|
|
|
|
|
// Summary: this function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
|
// It will then do another protection check & decrypt the data. NB you can modify the code to encrypt byte arrays instead of strings
|
|
// NB you can amend this code to read a byte array instead of a string if you prefer.
|
|
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
|
|
// Syntax:
|
|
//[ <Result> = ] EncryptUserDataEnc ()
|
|
// return value is 0 (success) or an error code
|
|
//
|
|
PROCEDURE EncryptUserDataEnc()
|
|
hLib, ret_code are system int
|
|
alg_ans is int
|
|
OurString is fixed string on 1024 = "Hello, World!" // NB max. data we can encrypt is 1K
|
|
OurString_bytes is array of 1024 1-byte unsigned int // byte-array of the encrypted string
|
|
|
|
// set the DRIS to have random values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = ENCRYPT_USER_DATA // protection check and encrypt specified data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.data_crypt_key_num = 1
|
|
DRIS.rw_length = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
|
|
DRIS.rw_data_ptr = &OurString_bytes // we convert the string to encrypt to a byte array (so we can encrypt it) and then we pass that to the API
|
|
|
|
// Load the protection DLL.
|
|
hLib = LoadDLL(protectdllname)
|
|
IF hLib = 0 THEN
|
|
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
|
|
RESULT -1
|
|
END
|
|
|
|
// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
|
|
alg_ans = MyRWAlgorithm(DRIS.var_a, DRIS.var_b, DRIS.var_c, DRIS.var_d, DRIS.var_e, DRIS.var_f, DRIS.var_g, DRIS.var_h)
|
|
|
|
// encrypt data we want to write (we must first convert it to a byte array so we can encrypt)
|
|
Transfer(&OurString_bytes, &OurString, DRIS.rw_length)
|
|
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
|
|
|
|
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
//do a protection check
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
|
|
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
FreeDLL(hLib)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
|
|
|
|
// Now decrypt the same data to get the original values
|
|
RandomSet()
|
|
// then set the values we want to use
|
|
DRIS.header = "DRIS"
|
|
DRIS.size = Length(DRIS)
|
|
DRIS.dpfunction = DECRYPT_USER_DATA // protection check and decrypt specified data
|
|
DRIS.flags = 0 // no extra flags, but you may want to specify some if you want to start a network user or decrement execs...
|
|
DRIS.data_crypt_key_num = 1
|
|
DRIS.rw_length = 13 // the length of the string (in this case 13 bytes)
|
|
DRIS.rw_data_ptr = &OurString_bytes // NB this wil still be the encrypted data at this point
|
|
|
|
alg_ans = MyRWAlgorithm(DRIS.var_a, DRIS.var_b, DRIS.var_c, DRIS.var_d, DRIS.var_e, DRIS.var_f, DRIS.var_g, DRIS.var_h)
|
|
|
|
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
|
|
FreeDLL(hLib)
|
|
|
|
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
|
|
DisplayError(ret_code, DRIS.ext_err)
|
|
RESULT ret_code
|
|
END
|
|
|
|
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
|
|
|
|
// decrypt the returned value and convert to a string
|
|
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
|
|
Transfer(&OurString, &OurString_bytes, DRIS.rw_length)
|
|
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
|
|
|