PDA

View Full Version : BUG! EncryptScript and OpenEncryptedFile


reForm
12-06-2008, 02:36 PM
I'm trying to write an encripted script. Using the code from the helpfile, I can make the dat file, and read it back, and verify the lockID. No problems...
But when the script that does all this is itself encrypted using encryptscript() The script fails when it tries to open the encrypted dat file. Its as though openencryptedfile, or readvalue doesnt work from within an encrypted script.

code to create the dat file:-

file = (getdir #scripts)+"\lock3.tmp"
dat = (getdir #scripts)+"\lock3.dat"
f = createFile file
format "%" hardwareLockID to:f
close f
encryptFile file dat ####
deleteFile file


code to read the dat file :-


id = undefined
file = (getdir #scripts)+"\lock3.dat"
f = openEncryptedFile file ####
id = readValue f
close f


the error when running the .mse file


-- Error occurred during fileIn in <File:C:\Program Files\Autodesk\3ds Max 2009\scripts\script.mse>
-- Error occurred in execute(); filename: C:\Program Files\Autodesk\3ds Max 2009\scripts\script.mse; position: 1255
-- Defined in encrypted script
-- called in anonymous codeblock
-- Defined in encrypted script
>> MAXScript MacroScript Error Exception: -- Syntax error: at bad, expected <factor>
-- In line: <<


Am I doing something wrong? Is there another way to get this to work?
Many thanks for any help!

MarcoBrunetta
12-06-2008, 03:02 PM
This has been posted before. AFAIK there is no "easy" workaround this bug. Thing you could try would be:

-Using .NET to encrypt/decrypt
-Creating you own encryption/decryption function
-Having the openEncyptedFile function inside a control in a rollout seemed to work fine (if I remember correctly)

ZeBoxx2
12-06-2008, 05:55 PM
Might be a bug, might be on purpose for some reason... it's been there at least since 3ds Max 5.

I wouldn't recommend maxscript's encryption for anything vital.. the encryption routine is okay, the access methods not so much.

The UI path works...

rollout test "" (
timer tick_tock active:true interval:1
on tick_tock tick do(
myFile = openEncryptedFile ((getdir #scripts)+"\lock3.dat") 1234
print (readValue myFile)
close myFile
destroyDialog test
)
)
createDialog test

...but is a pretty iffy approach. Note that you can't plate it in an on <rollout> open event... seems it still throws the same error.

reForm
12-06-2008, 11:32 PM
Hey guys, thanks for your replies, they have been very helpful. I managed to get it working by puting the script within a rollout as suggested. I'm interested what the security downsides are for doing it this way?
I think the bottom line is, whatever you do , it will get cracked, but some form of basic encryption is good enough to stop casual users from just taking your work. Most people, if they value your work, will pay for it. The people who don't want to pay for it, never will! Such is life :)

Besides this, if I was to look at other methods of encryption, whats the easiest approach? some dotnet or other language? Are there any resources on the web that you can recommend I read?

Thanks again.
p.

ZeBoxx2
12-07-2008, 12:07 AM
security of having it within the rollout (via a timer or otherwise) should be fine; I don't think you can get the source definition of a random rollout.

As for going with other encryption methods.. Marco might be able to help - he was working on the .NET approach in a previous thread:
http://forums.cgsociety.org/showthread.php?f=98&t=638998&highlight=encryption

This is also a good thread on maxscript encryption in general
http://forums.cgsociety.org/showthread.php?f=98&t=640226&highlight=encryption

MarcoBrunetta
12-08-2008, 02:10 PM
On the script I'm working on I went with "-Creating you own encryption/decryption function" actually. The NET stuff seamed doable but a bit too daunting. And like you said my only intention with this was to make it secure enough so that the casual user would not be able to hack it. I've seen enough of the internet's underworld to know that no security measure is bulletproof.

So anyways, I created a function that can do a bunch of funny operations to a string that can then be completely reversed to return to the original string. The function is then saved within an encrypted mse file so that it's not visible. The rest is easy, if someone wants to purchase the script they send their HardwareLockID to me. I run the value through the function and it returns the "scrambled" version which I then send back to the buyer. Once the string is intered in the appropiate field the script verifies that the scrambled version of the HardwareLockID and the one the user inputed match and then it autorizes the script.


I hope that was clear enough....I'm too lazy to proof-read it :blush:

ZeBoxx2
12-08-2008, 11:39 PM
ROT13? ;)

What were the problems you ran into with the .NET route, specifically?

MarcoBrunetta
12-08-2008, 11:55 PM
Hehe it's slightly more elaborated than that...but not a lot actually.

Well, there weren't any problems per se. I actually had a decent idea on how to make it work. But I just thought there wasn't any real point to it. Like I said before, I just need security so that the casual user won't be able to hack it (like doing something like setting back the system clock or so). Anything more elaborated than that just seems a waste of time to me... if somebody REALLY wants to crack your software they can...

ZeBoxx2
12-09-2008, 01:01 AM
true, though proper encryption is still better than scrambling.. although scrambling works.

Example scrambler...

fn findCharCS haystack needle = (
for i = 1 to haystack.count do (
if (hayStack[i] == needle) then ( return i )
)
undefined
)

fn scrambleScript f k = (
setWaitCursor()
seed k
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!-+*/^&=%\"$#.()[]{}<> \t\\"
alphabetCount = alphabet.count
fIn = openFile f mode:"r"
fOutName = ((getFilenamePath f) + (getFilenameFile f) + ".mss")
fOut = createFile fOutName
while (not (eof fIn)) do (
fLineIn = readline fIn
fLineOut = ""
for i = 1 to fLineIn.count do (
fCharIn = fLineIn[i]
fCharInIndex = findCharCS alphabet fCharIn
if (fCharInIndex == undefined) then ( fCharOut = fCharIn )
else (
fCharOutIndex = (mod (fCharInIndex - 1 + (random 1 k)) alphabetCount ) + 1
fCharOut = alphabet[fCharOutIndex]
)
fLineOut += fCharout
)
format "%\n" fLineOut to:fOut
)
close fOut
setArrowCursor()
fOutName
)

fn unscrambleScript f k = (
setWaitCursor()
seed k
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!-+*/^&=%\"$#.()[]{}<> \t\\"
alphabetCount = alphabet.count
fIn = openFile f mode:"r"
fOutName = ((getFilenamePath f) + (getFilenameFile f) + ".msu")
fOut = createFile fOutName
while (not (eof fIn)) do (
fLineIn = readline fIn
fLineOut = ""
for i = 1 to fLineIn.count do (
fCharIn = fLineIn[i]
fCharInIndex = findCharCS alphabet fCharIn
if (fCharInIndex == undefined) then ( fCharOut = fCharIn )
else (
fCharOutIndex = (mod (fCharInIndex - 1 - (random 1 k)) alphabetCount) + 1
if (fCharOutIndex < 1) then ( fCharOutIndex = alphaBetCount + fCharOutIndex )
fCharOut = alphabet[fCharOutIndex]
)
fLineOut += fCharout
)
format "%\n" fLineOut to:fOut
)
close fOut
setArrowCursor()
fOutName
)

This is a pretty simple scrambler, mostly due to the fact that it only takes a single key of integer size. Small values shouldn't be used as somebody could easily run the descrambling routine within a loop until the output makes sense.
Not that you should use the above 'as is'. The idea is that you adjust the above with a few math operators or bits and pieces here and there, encryptScript() the new functions, and never reveal the source :)

A few notes...
It only has a limited alphabet this to prevent any special characters from throwing errors. This does weaken things a bit, in case I missed any obvious characters that would reveal code structure easily. I can't think of any, but there you go.
In addition, it doesn't include cr/lf in the alphabet, this to prevent very-long-lines in the output. That does reveal code structure slightly.

Example usage:

scriptOriginalName = getOpenFilename caption:"Script to encrypt..." types:"MaxScript (*.ms)|*.ms"

if (scriptOriginalName != undefined) do (
scriptScrambledName = scrambleScript scriptOriginalName 555
edit scriptScrambledName

scriptUnscrambledName = unscrambleScript scriptScrambledName 555
edit scriptUnscrambledName

)
Should open two files.. the scrambled and the unscrambled version. Haven't found any cases yet where the result differs from the original, but... use at your own peril.

MarcoBrunetta
12-09-2008, 10:41 AM
Well, I was only "encrypting" a serial number and not a whole script...but the principle is the same I guess. That's a pretty good example.

I had a laugh with the "find a needle in a haystack" function.

CGTalk Moderation
12-09-2008, 10:41 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.