AutoHotkey Community

It is currently May 27th, 2012, 4:56 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 290 posts ]  Go to page 1, 2, 3, 4, 5 ... 20  Next
Author Message
 Post subject: SW copy protection
PostPosted: October 8th, 2005, 6:57 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Here is a "proof of concept" script providing SW copy protection. It needs the SafeSW.ini file with the user information and an unlock code, without it the script request registration and exits. The unlock code is computed by the same process at the provider of the SW (AuthData), and it has to be emailed back to the user.

1. To protect the code the AHK script has to be compiled to an executable with ahk2exe, which is part of the AHK distribution. To prevent de-compilation a (good) password has to be provided. This way the program runs normally, but an attacker would have difficulties modifying the program or getting out secrets (keys).

2. Collect some data specific to the target machine. For simplicity we use the following environment variables:

COMPUTERNAME
HOMEPATH
USERNAME
PROCESSOR_ARCHITECTURE
PROCESSOR_IDENTIFIER
PROCESSOR_LEVEL
PROCESSOR_REVISION

AHK built in variables:

A_OSVersion
A_OSType

These should not change at OS updates or changing the network environment.

In addition one can use disk volume identifiers by running the consol command VOL > info.txt:

Volume in drive C has no label.
Volume Serial Number is 24B5-2345

The MAC (Media Access Controller) address of the network cards can be used, too, by Getmac /NH >> info.txt:

00-20-30-F0-F1-F2 Media disconnected


(To be safe only the first 17 characters should be used, the MAC of the first network card.)

Instead of saving this data in a temporary file, one can use CMDret - return output from console programs [DLL version]

3. Having the machine/user specific data, we hash them all (Message Authentication Code = MAC with key 0), so no confidential data can be retrieved from it (for privacy concerns) and everybody can verify that no user secret is hidden in there. This is called the PC fingerprint. We ask the user to register the program via email, with the PC fingerprint and with a username and valid return email address, where we would send the unlock code.

4. We generate an unlock code from the data and send the whole SafeSW.ini file back to the user. S/he saves it into the script's working directory. At startup the program verifies if the user info, the PC fingerprint and the unlock code match. If not, it asks for registering the SW, otherwise it starts working.

Fingerprint = MAC(0_key; PC_data)
Registration_data = Username, Email, Fingerprint → emailed for registration
Authentication_data = Username, Email, MAC(secret_key, Username, Email, Fingerprint) ← emailed back from registration site

5. Operation

- If no or invalid format Authentication_data: Request registration, Exit
- Retrieve PC_data, Username, Email (from stored Authentication_data)
- Compute MAC(secret_key; Username, Email, Fingerprint)
- If invalid Authentication_data in the SafeSW.ini file: Request registration, Exit
- Else: display Username, Email; Start working
- Periodically re-compute Fingerprint, at change: Exit.

6. SafeSW.ini

It contains the following information:

[Registration]
User = Laszlo Hars
Email = Laszlo@Hars.US
UnlockCode = d0e8fd5f48edbc00

7. Notes

A malicious user could change the environment variables before the program starts, but it prevents normal operation, so he has to change it back. The periodic check of the PC fingerprint should make this attack more difficult.

MAC was used with key 0 for the Fingerprint, so users could verify the information sent for registration does not contain their secrets. A general, un-keyed hash is safer, as it is harder in the wrong PC to modify just one environmental variable to get a desired Fingerprint. We used MAC for simplicity.

There is more information that can be included in the machine specific data, like the physical serial number of the primary disk, the BIOS version, checksum, etc. You can make the sample script arbitrarily complex.

Some random, secret info can be written at installation somewhere hidden on the disk (e.g. in the registry) and it could be read back. (It is easy to catch the writing action, so this does not look very secure.) This random number could modify the executable itself, but it is complicated by the need of re-encrypting the code.

It is still possible to disassemble the program, and read the secret keys, but it is hard. Stronger protection is possible, but things would soon get very complicated.
Code:
; AutoHotkey Version: 1.0.39+
; Language:  English
; Platform:  Win2000/XP
; Author:    Laszlo Hars <www.Hars.US>
; Function:  SW copy protection

k0 = 0x11111111                  ; 128-bit secret key (example)
k1 = 0x22222222
k2 = 0x33333333
k3 = 0x44444444

l0 = 0x12345678                  ; 64- bit 2nd secret key (example)
l1 = 0x12345678

m0 = 0x87654321                  ; 64- bit 3rd secret key (example)
m1 = 0x87654321

IniFile = SafeSW.ini

GoSub    CheckAuth
SetTimer CheckAuth,1000
MsgBox,,,This SW is registered to`n%User% at %Email%,4

MsgBox OK   ; add your code here
Sleep 10000 ; add your code here

ExitApp

;---- End autoexecute secsion ----;

CheckAuth:
   IniRead User, %IniFile%, Registration, User
   IniRead Email,%IniFile%, Registration, Email
   IniRead Code, %IniFile%, Registration, UnlockCode
   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)
   Together = %User%%Email%%Fingerprint%
   AuthData := XCBC(Hex(Together,StrLen(Together)), 0,0, k0,k1,k2,k3, l0,l1, m0,m1)
   If (User="Error" || Email="Error" || Code <> AuthData)
   {
      S =
      (  LTrim
         To: Registration@MyOwn.com
         Username = <enter your full name here>
         Your email address = <where you want the unlock code sent>
         PC Fingerprint = %Fingerprint%
      )
      ClipBoard = %S%
      MsgBox Please Register! Email the following information`n`n%S%`n`n(it has been copied to the ClipBoard)
      ExitApp
   }
Return

;---- Crypto functions ----;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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
}


Last edited by Laszlo on October 9th, 2005, 6:33 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2005, 2:18 am 
Offline

Joined: September 2nd, 2004, 1:08 am
Posts: 124
Location: Sunnyvale
Weird. I did kind of a similar thing just two days ago. I really wanted to prevent a users ini file that contained some info about their account (not passwords or anything like that) from being used by someone else. One of the things that I did was save some info about the users environment to the ini file (computer name was one of them), but in encrypted format. This prevents anyone from knowing what it is in plain text. Then when the program starts up, it verifies that its running on the machine that it was first authenticated on.

What you've done looks pretty cool. I know that I will be using it soon.

_________________
I am he of whom he speaks!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2005, 4:39 am 
Offline

Joined: October 4th, 2005, 4:17 am
Posts: 35
I hate to ask, simply because this code is so far advanced from anything I could ever make, but could you please write a short script for creating the unlock code?

also, in this line there is a spelling error:

If (User="Error" || Eamil="Error" || Code <> AuthData)


I think I speak for everyone when I say... wow.. what a great contribution for the community. Thanks!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2005, 6:31 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
I fixed in the original post a couple of bugs. Thanks, JohnL!

To generate the SafeSW.ini file replace the code between the line IniFile = ... and ExitApp with the following:
Code:
InputBox User, User,  Enter the User's name,,   220,140
InputBox Email,Email, Enter the User's Email,,  220,140
InputBox FGprt,FGprt, Enter the PC Fingerprint,,220,140
Together = %User%%Email%%FGprt%
Auth := XCBC(Hex(Together,StrLen(Together)), 0,0, k0,k1,k2,k3, l0,l1, m0,m1)
IniWrite %User%, %IniFile%, Registration, User
IniWrite %Email%,%IniFile%, Registration, Email
IniWrite %Auth%, %IniFile%, Registration, UnlockCode
You can remove the CheckAuth subroutine, too, but it does not matter.


Report this post
Top
 Profile  
Reply with quote  
PostPosted: October 17th, 2005, 5:31 am 
Hi,

All very cool, but I would skip the Hard Drive test... of all the computers I've owned, every single one of them, had a new hard drive installed at one point.

I would be very annoyed (as an end customer), if my Software didn't work, after a clean install.

Just my 2 cents.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 17th, 2005, 8:00 am 
Offline

Joined: July 12th, 2005, 1:21 pm
Posts: 633
I think that's the post I was looking for!
I didn't read the code, only description but it looks like that what I need!

Big thanks to Laszlo (and to Bonzo who put the topic on top :D )!

@Bonzo
I think this way of protecting is very personal, so it wouldn't be hard to tell the user that he has to re-register the programm after changing hardware!

THX!
Thalon


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 17th, 2005, 4:26 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
The more information on the user's system we include in the PC fingerprint, the more often s/he needs to re-register the SW. Network cards get also replaced or new adapters added, the original disk could become secondary, when a larger one is installed, BIOS can be updated, etc. Using fewer pieces of configuration data makes the copy protection easier to break. I think the information used in the original post represent a good security/convenience tradeoff, and also high speed, simple code.

Another variation of the theme is when the user first receives (downloads) the compiled script, without the code doing the useful work. In response of the registration we send back the fully functional program with the information User, Email and UnlockCode hard coded. The original setup program then can be deleted. This way there is no need for the .ini file, but our email response has to contain a large attachment.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 9th, 2005, 6:50 pm 
Offline

Joined: November 7th, 2005, 8:32 pm
Posts: 10
Location: Germany
Laszlo, thanks for this great solution - you are a genious!
I am developing a somewhat bigger program and want to share it.
But I definitely cannot give away the source by now, only the exe file (too much nights without getting sleep and too much justified complaints
by my family members). I would like to know, how many people still use it after a period of 90 days.

So I want to ask your permission to integrate this solution in my script.
Of course I could give credits to you, in whatever form you want
(in the registration-Gui, in the email with the code, in the documentaion, ...)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 9th, 2005, 7:42 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Whatever I post in the AHK forum is FREE, you can use it without any restriction, but I cannot guarantee anything about the scripts, either. I would be glad if you give me credit for the copy protection scheme in the documentation (my website is in my AHK profile).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 9th, 2005, 9:34 pm 
Offline

Joined: November 7th, 2005, 8:32 pm
Posts: 10
Location: Germany
Thank you!
I expected an answer like that, but anyway, I felt bad to use it without your
explicit permission.

The credits will be given, and I hope, my program will be of some use for you too, so I can give something back.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 17th, 2006, 1:25 pm 
so when i get the persons info sent to my email

do i edit the .ini file or something please explian how i edit it


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: July 17th, 2006, 8:13 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
As described above, you need a second version of the script, with the replacement code. You run it, enter (copy & paste) the user information you received via email, and it creates the ini file for you. Its path\name is assigned to "IniFile".


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 18th, 2006, 12:20 pm 
Offline

Joined: July 18th, 2006, 12:18 pm
Posts: 403
got it thanks nice work


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 25th, 2007, 8:04 pm 
Offline

Joined: June 19th, 2007, 12:04 am
Posts: 174
I'm just not understanding the 2nd part of this, how do i create the ini file and the location of it, lol?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 25th, 2007, 9:31 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
This post explains how you generate the personalized ini file.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 290 posts ]  Go to page 1, 2, 3, 4, 5 ... 20  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot] and 10 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group