Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Code Protection


  • Please log in to reply
33 replies to this topic
heopas
  • Members
  • 44 posts
  • Last active: Oct 26 2012 09:56 PM
  • Joined: 14 Apr 2010
I am looking for a way to protect source code. (e.x. Obfuscation)

Thanks in advance.

G. Sperotto
  • Members
  • 539 posts
  • Last active: Jun 20 2015 04:54 PM
  • Joined: 12 Dec 2011
Hi Heopas.

I can see you are very serious about the subject.

:arrow: Code obfuscation is nothing more than making it harder for people to grasp the inner logics of your scripted by reading the source code.

In that sense, let me referr to this little snippet from Uberi:

#:="chr",#@:=(#_:=(##:=($:=(#$:=(_:=!"")<<_)<<_)<<_)<<_)<<#$,@:=#_<<_|#@,_#:=%#%(@|#$|_),__:=%#%(@|$|_),_@:=%#%(@|#_|#$|_),_$:=%#%(#@|_),@#:=%#%(@|_),@_:=%#%(@|##|$|#$|_),@@:=%#%(@|#_|$|_),@$:=%#%(@|#_|$),$#:=%#%(@|##|$|#$),$_:=%#%(@|#_|#$),$@:=%#%(@|##|#$|_),$$:=%#%(#@|##),###:=%#%(@|$),##_:=%#%(@|##|$),%###%%##_%%##_%%_#%%@#%%##_%%##_%(%#%(#@|##|$|_) __ _@ _@ @# %#%(@|$|#$|_) __ %#%(#@|#$) @_ %#%(@|#_|##),%#%(#@|@|##|_) $# @$,!_,_@ @$ $_,%#%(#@|##|#$) @@ _@ @$ " " _$ $# @_ @$ %#%(@|##) __ $_ " " _$ @@ @$ @_ $$ @_ @$ $@ __ %#%(@|#_|##|_) " " $$ @# _# $@ __ $_,_@ @$ $_,"",%#%(#@|@|##|_) $# @$,!_)


Execute this code and you will see it does something that cannot be easily inferred from whats written.

Now check the snippet bellow:

msgbox % "Just Another AutoHotkey Hacker"

It's quite easy to read and undestand what the code does now right?

:arrow: Both scripts do the same. But the first is a highly obfuscated version of the second.

"What is a suitable automation? Whatever saves your day for the greater matters."
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!


Pulover
  • Members
  • 1596 posts
  • Last active: Apr 06 2016 04:00 AM
  • Joined: 20 Apr 2012
Hi, heopas!

I haven't tested it but did you try this one already? <!-- l --><a class="postlink-local" href="http://www.autohotkey.com/community/viewtopic.php?t=49952">viewtopic.php?t=49952</a><!-- l -->

Rodolfo U. Batista
Pulover's Macro Creator - Automation Tool (Recorder & Script Writer) | Class_LV_Rows - Copy, Cut, Paste and Drag ListViews | Class_Toolbar - Create and modify | Class_Rebar - Adjustable GUI controls

Join the New AutoHotkey Forum!


heopas
  • Members
  • 44 posts
  • Last active: Oct 26 2012 09:56 PM
  • Joined: 14 Apr 2010
My main job is to write softwares at C# for a betting company that i work, but we need something to work fast with keyboard this is the reason i choose autohotkey, my script is ready but i am looking for ways to protect it. Thanks for your interest.

heopas
  • Members
  • 44 posts
  • Last active: Oct 26 2012 09:56 PM
  • Joined: 14 Apr 2010

Hi Heopas.

I can see you are very serious about the subject.

:arrow: Code obfuscation is nothing more than making it harder for people to grasp the inner logics of your scripted by reading the source code.

In that sense, let me referr to this little snippet from Uberi:

#:="chr",#@:=(#_:=(##:=($:=(#$:=(_:=!"")<<_)<<_)<<_)<<_)<<#$,@:=#_<<_|#@,_#:=%#%(@|#$|_),__:=%#%(@|$|_),_@:=%#%(@|#_|#$|_),_$:=%#%(#@|_),@#:=%#%(@|_),@_:=%#%(@|##|$|#$|_),@@:=%#%(@|#_|$|_),@$:=%#%(@|#_|$),$#:=%#%(@|##|$|#$),$_:=%#%(@|#_|#$),$@:=%#%(@|##|#$|_),$$:=%#%(#@|##),###:=%#%(@|$),##_:=%#%(@|##|$),%###%%##_%%##_%%_#%%@#%%##_%%##_%(%#%(#@|##|$|_) __ _@ _@ @# %#%(@|$|#$|_) __ %#%(#@|#$) @_ %#%(@|#_|##),%#%(#@|@|##|_) $# @$,!_,_@ @$ $_,%#%(#@|##|#$) @@ _@ @$ " " _$ $# @_ @$ %#%(@|##) __ $_ " " _$ @@ @$ @_ $$ @_ @$ $@ __ %#%(@|#_|##|_) " " $$ @# _# $@ __ $_,_@ @$ $_,"",%#%(#@|@|##|_) $# @$,!_)


Execute this code and you will see it does something that cannot be easily inferred from whats written.

Now check the snippet bellow:

msgbox % "Just Another AutoHotkey Hacker"

It's quite easy to read and undestand what the code does now right?

:arrow: Both scripts do the same. But the first is a highly obfuscated version of the second.

Editing...

And you did that with?

G. Sperotto
  • Members
  • 539 posts
  • Last active: Jun 20 2015 04:54 PM
  • Joined: 12 Dec 2011

And you did that with?


I didn't. Uberi did. There is currently no obfuscator script for AutoHotkey afaik, but i can show you how he did it if you are unable to translate the snippet. But first let´s talk a little bit more about obfuscation :wink:

If you are going to obfuscate a source code, you will probably make use of a lot of useless code and a lot of diversion code. A script is a text file that is based on a programming language, which is a language that can serve as means of communication between the human programmer AND the interpreter/compiler.

The thing is, although both of them are making use of the same language, they understand it differently. Humans read the language in an extremely slow pace compared to the machine, but the machine (albeit being a faster reader) is unable to grasp the abstract meaning of the code (the logic of the script).

These key differences between the types of readers allow obfuscation by the means of making the code much harder for a human to read without significantly altering the expected results of the execution.

In that sense, even the most simple techniques could provide some level of obfuscation:

Dummy function calls (useless code), lots of comments with a different comment flag (diversion AND useless code), inexpressive function and variable names (diversion), useless lines (useless code), etc

Example:

msgbox % "Hello world"

Could be obfuscated to:

O := "ba"
, F := "g", ll := "wo", Y := "rk"
A = o
C := he,Y := "p", D := "lo"
X := he
O := "he", B := "wo"
, H := "pr"
C =  d
ll = "bo"
Msgbox % O "ll" A " " B "rl" C

The interpreter will read both scripts so fast that they will seemingly do the same. But a human programmer will find the second significantly harder to understand.

Obfuscation is mostly an art by itself. You could go on and create a script that will auto-obfuscate other scripts, or you could go on and obfuscate it manually. It's not hard at all, just put together some concepts of the language to script the same routines in a seemingly unreadable manner.

Uberi made use of the following aspects of the AutoHotkey programming language to create that obfuscated snippet:


1 - The chr() function: A built-in function that allows one to retrieve any character from it's ASCII value. As any function parameter, the value to be passed can be the result of an expression (such as the bitwise or'ing of two numbers with | operator or the left/right shiftings with >> and << operators)
2 - Lot's of #'s, @'s, $'s and _'s: these symbols are allowed into variable names and can be easily mistaken for operators.
3 - Commas (,): They allow multiple mathematical assignments to be declared in the same line.
4 - Dereferencing variables into function names: a function call can be succesfully implemented by dereferencing the contents of variables. Dllcall() is a function and chr() is a function too, so both can be succesfully called in this manner.
And maybe some others that i cannot remember atm.

This article, albeit being intentionally a joke, contains lots of ideas on how to obfuscate a script and it's a well worth reading :p

Best wishes :wink:

"What is a suitable automation? Whatever saves your day for the greater matters."
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!


Uberi
  • Moderators
  • 1119 posts
  • Last active: May 02 2015 06:05 PM
  • Joined: 23 Aug 2010

Uberi made use of the following aspects of the AutoHotkey programming language to create that obfuscated snippet:


1 - The chr() function: A built-in function that allows one to retrieve any character from it's ASCII value. As any function parameter, the value to be passed can be the result of an expression (such as the bitwise or'ing of two numbers with | operator or the left/right shiftings with >> and << operators)
2 - Lot's of #'s, @'s, $'s and _'s: these symbols are allowed into variable names and can be easily mistaken for operators.
3 - Commas (,): They allow multiple mathematical assignments to be declared in the same line.
4 - Dereferencing variables into function names: a function call can be succesfully implemented by dereferencing the contents of variables. Dllcall() is a function and chr() is a function too, so both can be succesfully called in this manner.


Most importantly, you can build up any integer by setting its bits correctly. Any integer between 0 and 255 would require no more then 8 variables shifted and bitwise-OR'd together.

Back to the subject, though, obfuscation is the only real way to protect AHK source code as of now, since the source is what is input to the AHK interpreter. That said, there is no fully automated, well maintained obfuscator available for AHK as of the moment. However, this might get you on the right track:

#NoEnv

Loop,1{
}Var=1

Var := 1
++ Var
Var := 2
 - 3 + 1

Var = 

/*
bla
 ;blasdjsdjkjk
   ;test
 Bla
;hello
*/

(LTrim0 Join`n
 ;test
;another comment
Bla
;A continuation section.
  Hello, World!
)

FileRead, Code, %A_ScriptFullPath%
MsgBox % Clipboard := Minify(Code)

Minify(Code,MinifyNames = -1)
{
 StringReplace, Code, Code, `r,, All ;remove carriage returns for easier processing
 Code := MinifyContinuationSections(Code) ;collapse continuation sections
 Code := RegExReplace(Code,"`nmS)(?:^| |\t)`;.*$") ;remove single line comments
 Code := RegExReplace(Code,"`nmsS)^[ \t]*/\*.*?\n[ \t]*\*/") ;remove multiline comments
 StringReplace, Code, Code, `n{, `n{`n, All ;normalize opening braces
 StringReplace, Code, Code, `n}, `n}`n, All ;normalize closing braces
 Code := RegExReplace(Code,"`nmS)^[ \t]+|[ \t]+$") ;remove beginning and ending whitespace
 While, InStr(Code,"`n`n") ;collapse empty lines
  StringReplace, Code, Code, `n`n, `n, All
 StringReplace, Code, Code, `n'Continuation:,, All ;combine continuation sections with the lines they belong to
 If (SubStr(Code,1,1) = "`n")
  Code := SubStr(Code,2)
 If (SubStr(Code,0) = "`n")
  Code := SubStr(Code,1,-1)
 ;Code := RemoveLiterals(Code,LiteralsList) ;wip
 Code := RegExReplace(Code,"`nmS)\n(?=[^\w#@\$\{}%\+-]|\+[^\+]|-[^-])(?!.*::)"," ") ;collapse multiline expressions to a single line (excluding lines beginning with ++ and --, or hotstrings)
 Code := MinifyCommands(Code)
 If MinifyNames = -1 ;detect whether or not names can be minified safely
 {
  If RegExMatch(Code,"S)%[\w#@\$]+%") ;dynamic variable reference or function call
   MinifyNames := 1
  Else If Code Contains IsFunc(,IsLabel( ;dynamic function or label checking
   MinifyNames := 1
  Else
   MinifyNames := 0
 }
 If MinifyNames ;allow the changing of symbol names, which may break some dynamic features
 {
  Code := MinifyVariables(Code)
  Code := MinifyFunctions(Code)
  Code := MinifyLabels(Code)
 }
 Code := MinifyExpressions(Code)
 Code := RegExReplace(Code,"`nmiS)^(?:While[, \(]|If ?\(|Else[ ,]?|[\w#@\$]+\().*?\K(?:\n|[ \t]+){","{") ;use OTB where possible
 Code := RegExReplace(Code,"`nmS)\n\{\n(?!.*::|[^, \t``]+:$)","`n{") ;minify opening braces, unless there is a label immediately after
 Code := RegExReplace(Code,"S)\n}\n(?![\w#@\$\{}]+\(.*\)(?:\n|[ \t]*)\{)","`n}") ;minify closing braces, unless there is a function definition immediately after
 ;Code := RestoreLiterals(Code,LiteralsList) ;wip
 StringReplace, Code, Code, `n, `r`n, All ;restore carriage returns
 Return, Code
}

MinifyCommands(Code)
{
 ;wip: remove spaces from the commas delimiting command parameters (commas can be cleaned globally, after quoted strings and classic assignments are escaped)
 ;Code := RegExReplace(Code,"`nmS)^(\w+)[ \t]*(?:,[ \t]*| [ \t]*(?!\W=))","$1,") ;remove whitespace after command name
 Return, Code
}

MinifyVariables(Code) ;wip: change variable names to shorter ones
{
 
 Return, Code
}

MinifyFunctions(Code) ;wip: change all function names to shorter ones
{
 Code := RegExReplace(Code,"`nmS)^([\w#@\$\{}]+)(\(.*\))(?:\n|[ \t]*)\{","$U{1}$2`n{") ;find function definitions
 Return, Code
}

MinifyLabels(Code) ;wip: change label names to shorter ones
{
 
 Return, Code
}

MinifyExpressions(Code) ;wip: remove all whitespace from expressions, except where needed, like concatenation or ternary expressions
{
 
 Return, Code
}

MinifyContinuationSections(Code)
{
 FoundPos := 1, FoundPos1 := 1
 While, (FoundPos := RegExMatch(Code,"sS)\n[ \t]*\((.*?)\n[ \t]*\)",Match,FoundPos)) ;loop through each continuation section
 {
  Temp2 := InStr(Match1 . "`n","`n"), Temp1 := SubStr(Match1,1,Temp2 - 1), Match1 := SubStr(Match1,Temp2 + 1) ;extract continuation section options and actual text
  StringReplace, Temp1, Temp1, %A_Tab%, %A_Space%, All ;convert tabs to spaces
  While, InStr(Temp1,"  ") ;collapse spaces
   StringReplace, Temp1, Temp1, %A_Space%%A_Space%, %A_Space%, All
  JoinString := "`n", TrimRight := 1, AllowComments := 0, LiteralCommas := 1
  Loop, Parse, Temp1, %A_Space% ;process options
  {
   If (SubStr(A_LoopField,1,4) = "Join")
    JoinString := SubStr(A_LoopField,5)
   Else If (SubStr(A_LoopField,1,5) = "LTrim")
    % (SubStr(A_LoopField,6) <> 0) ? (Match1 := RegExReplace(Match1,"`nmS)^[ \t]+")) ;remove leading whitespace
   Else If (SubStr(A_LoopField,1,5) = "RTrim")
    TrimRight := SubStr(A_LoopField,6), (TrimRight = "") ? (TrimRight := 1)
   Else If (SubStr(A_LoopField,1,1) = "C")
    AllowComments := SubStr(A_LoopField,0), (AllowComments = "") ? (AllowComments := 1)
   Else If (A_LoopField = "%")
    LiteralPercentSigns := 1
   Else If (A_LoopField = ",")
    LiteralCommas := 0
   Else If (A_LoopField = "``")
    LiteralBackTicks := 1
  }
  If TrimRight
   Match1 := RegExReplace(Match1,"`nmS)[ \t]+$") ;remove ending whitespace
  If AllowComments
   Match1 := RegExReplace(Match1,"`nmS)(?:^| |\t)`;.*?(?:\n|$)") ;remove single line comments
  Else
   Match1 := RegExReplace(Match1,"`nmS)(^| |\t)`;","$1```;") ;escape single line comments
  If LiteralPercentSigns
   StringReplace, Match1, Match1, `%, ```%, All ;escape percent signs
  If LiteralCommas
   StringReplace, Match1, Match1, `,, ```,, All ;escape commas
  If LiteralBackTicks
   StringReplace, Match1, Match1, ``, ````, All ;escape backticks
  JoinString := EscapeSpecialChars(JoinString)
  StringReplace, Match1, Match1, `n, %JoinString%, All ;join the string
  Code1 .= SubStr(Code,FoundPos1,FoundPos - FoundPos1) . "`n'Continuation:" . Match1, FoundPos += StrLen(Match), FoundPos1 := FoundPos
 }
 Return, Code1 . SubStr(Code,FoundPos1)
}

EscapeSpecialChars(String)
{
 Chr1 := Chr(1)
 StringReplace, String, String, ````, %Chr1%, All ;temporarily replace escaped backtick with an unused character
 StringReplace, String, String, `n, ``n, All ;newline
 StringReplace, String, String, `r, ``r, All ;carriage return
 StringReplace, String, String, `b, ``b, All ;backspace
 StringReplace, String, String, %A_Tab%, ``t, All ;horizontal tab
 StringReplace, String, String, `v, ``v, All ;vertical tab
 StringReplace, String, String, `a, ``a, All ;bell
 StringReplace, String, String, `f, ``f, All ;formfeed
 StringReplace, String, String, %Chr1%, ````, All ;restore backticks
 Return, String
}

The above is a basic source code minifier I had lying around. It will remove whitespace, continuation sections, and generally make the code more compact. It will not mangle names, add dead code, or fold expressions, though.

heopas
  • Members
  • 44 posts
  • Last active: Oct 26 2012 09:56 PM
  • Joined: 14 Apr 2010
I have seen that similar tools (AutoI*) already have code obfuscator. AHK need one too ^^.

tidbit
  • Administrators
  • 2709 posts
  • Hates playing Janitor
  • Last active: Jan 15 2016 11:37 PM
  • Joined: 09 Mar 2008
lots of languages have lots of tools that lots of other languages could use. but every language is different. We here at AHK do not monitor or stalk the AutoIt community to create what they do. are are our own community, not some jealous Autoit wannabe's.

Only a small handful of AHK users have wanted/needed there code super secure. The best you might be able to get is the CamoAHK compiler. search for it.

rawr. be very afraid
*poke*
. Populate the AutoHotkey city. Pointless but somewhat fun. .


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
‚ := 1
ListVars
Pause
... works for me. Now that's an obscure variable name.

Better yet, use a non-breaking space.

Azevedo
  • Members
  • 179 posts
  • Last active: Nov 04 2015 04:37 PM
  • Joined: 07 Mar 2012

Hi, heopas!

I haven't tested it but did you try this one already? <!-- l --><a class="postlink-local" href="http://www.autohotkey.com/community/viewtopic.php?t=49952">viewtopic.php?t=49952</a><!-- l -->



I think UPX has 2 major issues:

1: won't work with 64bit executables.
2: can be unpacked (no protection)

heopas
  • Members
  • 44 posts
  • Last active: Oct 26 2012 09:56 PM
  • Joined: 14 Apr 2010
I am doing several tests with Enigma Protector owner. I will inform you when i find a method to protect source code.

Klark92
  • Members
  • 870 posts
  • Last active: Dec 29 2015 09:47 PM
  • Joined: 19 Feb 2012
@Azevedo:
you must not use UPX for Basic or _L version .. look it my signature .. I can compile my scripts with mpress for Basic verson (Klark92's Script2Exe Wizard) ..

I CAN PROTECT YOUR SCRIPT (ANTI-DECOMPILER by Klark92) (AHK_L*)(PM)
Klark92's Script2Exe Wizard
AHK_L / AHK COMPILED EXE / BIN ICON CHANGER


Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
Obfuscate all you want. But, if someone realy wants your source code they will get it. AHK is a scripting language and as such the packed exe needs to be able to read the script in order to run. If it can read it, then a human can eventually read it. You will have to use a compiled language if you want to protect your source code.

Uberi
  • Moderators
  • 1119 posts
  • Last active: May 02 2015 06:05 PM
  • Joined: 23 Aug 2010
And even then, with enough time and resources, it can be reconstructed. After all, it's got to execute on a machine eventually.

(Unless you have a hardware dongle containing a processor with a self destruct mechanism that blows up if you try to open it :p)