Saturday, 19 January 2013

protect ea

http://articles.mql4.com/934


Protect Yourselves, Developers! ru ]

Protection of intellectual property is still a big problem. This article describes the basic principles of MQL4-programs protection. Using these principles you can ensure that results of your developments are not stolen by a thief, or at least to complicate his "work" so much that he will just refuse to do it.


Introduction

When I started to get acquainted with MQL, through rose-colored glasses of beginner MQL-programmer I saw picture, "pleasant in all respects": I'm understandably told how to trade. I am no less clearly writing a program. Then everyone, who has got it for work, after the first earned profit transfers me small part of it as a gratitude for product of high quality.
The beginning trader, who has earned first $5 on first $20 deposit, enthusiastically transfers me $2, and some ace of trade, once again withdrawing 2K, thanks me as much as much as $200. Everything looked completely honest: I'm doing the work that can't be done by trader, who will use it to earn more\frequently\easier\constantly than without it. Together we have worked successfully and have got excellent financial result, which can be divided on equity basis. I've even invented the special distribution terms for this -FairWare.
Imagine my surprise when, in spite of the decent number of my first instruments downloads and constant questions & consultations on them, I have only received one $3 payment, in which the man had clearly referred to my FairWare conditions. So, the honesty of anonymous users of my products was rather poor, and I decided to set at least some minimum payment for the use of my tools on real accounts.
For this I had to protect them and switch on the principles of Shareware. As my tools became more mature, the more strict became wishes to protect them, and so far I've collected a few proven ways, which I decided to share with MQL-coding fellows. All of us more or less have been walking the way, I described earlier in this article. And information on this issue, gathered in one place, will certainly ease these "protection sufferings".
So, let's start: from simple to complex...

Protecting String Constants

The first thing you want to protect - is your copyright. Not just to be proud and to boast that you are a cool programmer, that wrote such a cool thing, but also to ensure that users have the opportunity to get feedback from the developer. As stated in Murphy's Law, "every last bug you found is actually the penultimate," and it is likely that you do not stumble on it during testing, and another will find something that slipped past you. In this case, you have to make the text string with your e-mail or website address to remain unchanged, when it is displayed in Expert Advisor's window. Consider a simple code:
//+------------------------------------------------------------------+
//|                                                  Protect-001.mq4 |
//|                                Copyright © 2009, Sergey Kravchuk |
//|                                         http://forextools.com.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start()
{
  Comment("Copyright © 2009, Sergey Kravchuk");
  return(0);
}
All is plain and open. The script displays your comment. However, looking inside the ex4-file we see all texts abroach.
Any HEX-editor will allow to easily replace the visible text, and the modified script will loose your copyright.
Now let's think: what is a text string? This is a sequence of characters, linked to each other. Who prevents us to write such a string "character by character"? However, before doing so, we will prepare the collector of encoded strings. Here is its source code:
//+------------------------------------------------------------------+
//|                                                  Protect-002.mq4 |
//|                                Copyright © 2009, Sergey Kravchuk |
//|                                         http://forextools.com.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

#property show_inputs

extern string prefix = "char";
extern string text   = "input your text for encoding";
string rez           = ""; // here we will assemble the result

int start()
{
  // enter the original text to see what this string is
  rez = "/* " + text + " */ "; 
  
  for (int i = 0; i < StringLen(text); i++) 
  rez = rez + prefix + "[" + StringGetChar(text, i) + "]+";
  
  // cut the last '+' character and print string to the log
  Print(StringSubstr(rez, 0, StringLen(rez)-1)); 
}
I hope, working algorithm is obvious: we enter a comment to see what has been coded, and concatenate character by character to get the code of string, assembled from individual characters. The resulting string is printed to log. Copy it from there and insert into original source code.
To understand how it works, let's look at the source with encoded string.
//+------------------------------------------------------------------+
//|                                                  Protect-003.mq4 |
//|                                Copyright © 2009, Sergey Kravchuk |
//|                                         http://forextools.com.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start()
{  
  string char[256]; int i;

  for (i = 0; i < 256; i++) char[i] = CharToStr(i);

  Comment
  (
    /* Copyright © 2009, Sergey Kravchuk*/ 
    char[67]  + char[111] + char[112] + char[121] + char[114] + char[105] + char[103] +
    char[104] + char[116] + char[32]  + char[169] + char[32]  + char[50]  + char[48]  +
    char[48]  + char[57]  + char[44]  + char[32]  + char[83]  + char[101] + char[114] +
    char[103] + char[101] + char[121] + char[32]  + char[75]  + char[114] + char[97]  +
    char[118] + char[99]  + char[104] + char[117] + char[107]
  );
  return(0);
}
As you can see, first we've declared the string array of all possible 256 characters of the main ASCII table and fill each element with corresponding character. Then we have replaced original string with encoded text, copied from the Experts tab log in Terminal window, compiled it, and here is the result.
As a result, the contents were encrypted, and we don't see our encoded string anymore. After all, it's gone - instead there is a set of commands, that assemble it from separate characters. The remaining unencrypted strings - are constants from the #property copyright and #property link. Unfortunately, they can't be encoded because they are set as strings, and no assembly codes are allowed.
So, every string we want to protect against possible changes in HEX-editor can be encoded in this way. You can get its encrypted form using the Protect-002.mq4 script. When using such an assembly, you must bear in mind that such an operation takes some time. Therefore, do not insert such blocks of code directly into the expert body, not to use them a hundred times on each tick. It's enough to declare the required string variables, initialize them once with encoded assembly on indicator or expert initialization, and then use these variables.

Protection Against Unauthorized Use

Well, we have protected our copyright and came to another problem. Your Expert Adviser may be copied by someone without your knowledge (for example, when you're away from your computer on DC's trading floor), and later it is used without your knowledge. If you're going to use it only by yourself or to sell it, this "leak" of course is not in your interest.
There are many mechanisms of protection against unauthorized use: from simple serial numbers generators to protections using online services and/or electronic security keys. The last way - is the most reliable, but at the same time the most labor-intensive. However, MetaTrader client terminal has its own specific trait, which together with the object of protection specifics allows to use more simple, but nevertheless reliable method.
In fact, you need to make your Expert Advisor or Indicator to work only for those traders, whom you gave it or sold it. To definitely identify the owner, there is one thing completely unique for each user: the number of his working account. And in conjunction with the name of trade server, it becomes totally unique "electronic passport" of Expert Advisor's owner.
Here is an example of a simple code that implements this scheme of protection:
//+------------------------------------------------------------------+
//|                                                  Protect-004.mq4 |
//|                                Copyright © 2009, Sergey Kravchuk |
//|                                         http://forextools.com.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start()
{  
  string char[256]; int i;

  for (i = 0; i < 256; i++) char[i] = CharToStr(i);
  // Account number, on which expert is allowed to work
  int    AllowedAccountNo = StrToInteger(/* 49153 */ char[52]+char[57]+char[49]+char[53]+char[51]); 
  string AllowedServer = /* UWC-Demo.com */ char[85]+char[87]+char[67]+char[45]+char[68]+
  char[101]+char[109]+char[111]+char[46]+char[99]+char[111]+char[109];

  if (AccountNumber() != AllowedAccountNo || AccountServer() != AllowedServer) 
  {
    Print("You don't have permission to use this script!");
    return(1);
  }
  
  Print("You can use this script!");
}
Here we've used our previous method of hiding account number and trade server name as encrypted strings, and can be relatively sure that your ex4 won't be "corrected" in a way to make it work on other accounts and servers.
Organizing such protection (each time to rebuild an Expert Advisor for each permitted customer or to invent some sort of a universal protection scheme, that uses encoded strings mechanism) is beyond the scope of this article. And its not secure to openly discuss the logic of such universal protection. Otherwise, it will be available not only for developers, but also for crackers - so why to facilitate their work on breaking our programs? 

Protection by Time

Another way to protect an Expert Advisor is to limit its work by time. You can let it work only until a certain date on any account or server. When demo period expires, the Expert Advisor will no longer work and user will have to ask you for properly protected version of the expert.
Here is the text of the script with this mechanism of protection.
//+------------------------------------------------------------------+
//|                                                  Protect-005.mq4 |
//|                                Copyright © 2009, Sergey Kravchuk |
//|                                         http://forextools.com.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start()
{  
  string char[256]; int i;

  for (i = 0; i < 256; i++) char[i] = CharToStr(i);

  // Date, until which the expert is allowed to work
  int LastAllowedDate = StrToTime(
  /* 2009.09.11 23:59:00 */ 
  char[50]+char[48]+char[48]+char[57]+char[46]+char[48]+char[57]+char[46]+char[49]+
  char[49]+char[32]+char[50]+char[51]+char[58]+char[53]+char[57]+char[58]+char[48]+char[48]

  ); 

  if (TimeCurrent() >= LastAllowedDate) 
  {
    Print("Demo period has expired " + TimeToStr(LastAllowedDate,TIME_DATE|TIME_SECONDS));
    return(1);
  }
  
  Print("You can work until "+ TimeToStr(LastAllowedDate,TIME_DATE|TIME_SECONDS));
}
It also uses the encryption of string, containing date of demo period end, so it will be impossible to "renew" it by editing ex4-file.

Protection from Decompilation

Unfortunately, all these methods work successfully only if the attacker has no access to source code of an expert. However, everything that has been built - can always be broken. There is a utility available over the Internet, that allows to decompile ex4-files. Its authors have protected this software and are selling it.
But this utility has also been cracked, and now everyone who managed to get it can decompile your expert and get its source code. It's possible to make necessary changes in this decompiled code (for example, just remove the block that analyses dates, accounts and servers), recompile it and get totally unprotected version of your Expert Advisor. 
MQL4 compiler developers are struggling with this problem. The details of this struggle, of course, will never be announced. But, unfortunately, the source code can often be restored. Although its text will be difficult to read: all identificators instead of meaningful names will have mechanically created names. This, of course, greatly complicates the process of reviewing and reconstructing the algorithm. In big files, with lots of functions, it can become almost unsolvable problem. However, when an expert is small, it can be restored to almost original condition.
And here in the first place comes the art of programming. The task of protection system developer (while knowing in what form the decompiler will restore the source code), is to write it in such way that the possibility of finding and disabling the protection will be the most difficult for an attacker. This part certainly will not be detailed - you have to invent methods of such protection by yourself.
The most common recommendation is to spread the security code across the entire module. Attacker must be exhausted while analyzing your code, so that he won't desire to mess with hacking. Values of control variables must be collected in different locations of source code, and the more unsuspected is the place, the harder it will to guess that this is the piece of security code.
For example, assembling the end date can be divided into two parts: set the year at the beginning of the Expert Advisor, and the month, day and time will be added while calculating trade signals. The analysis of violations can also be done in one location, and the actions on its results (emergency exit or reducing the functionality) - in another.  
Existing decompiler of ex4-files is not able to restore variable names, but is capable of restoring function names. Unlike variable names they are present in ex4-file, from which they are selected by decompiler. Therefore, if you use function with name IsDemoMode(), you thereby is giving a direct indication where to turn off your protection.
If we rewrite our script a little to check the demo period by date, like this "wrong":
//+------------------------------------------------------------------+
//|                                                  Protect-006.mq4 |
//|                                Copyright © 2009, Sergey Kravchuk |
//|                                         http://forextools.com.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start()
{  
  string char[256]; int i;

  for (i = 0; i < 256; i++) char[i] = CharToStr(i);

  // Date, until which the expert is allowed to work
  int LastAllowedDate = StrToTime(
  /* 2009.09.11 23:59:00 */ 
  char[50]+char[48]+char[48]+char[57]+char[46]+char[48]+char[57]+char[46]+char[49]+
  char[49]+char[32]+char[50]+char[51]+char[58]+char[53]+char[57]+char[58]+char[48]+char[48]

  ); 

  if (IsDemoMode(LastAllowedDate)) 
  {
    Print("Demo period has expired " + TimeToStr(LastAllowedDate,TIME_DATE|TIME_SECONDS));
    return(1);
  }
  
  Print("You can work until "+ TimeToStr(LastAllowedDate,TIME_DATE|TIME_SECONDS));
}

bool IsDemoMode(int LastAllowedDate)
{
  if (TimeCurrent() >= LastAllowedDate) return(true); else return(false); 
}
then decompiler will give the following result:
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start() {
   string lsa_0[256];
   for (int l_index_4 = 0; l_index_4 < 256; l_index_4++) lsa_0[l_index_4] = CharToStr(l_index_4);
   int l_str2time_8 = StrToTime(lsa_0[50] + lsa_0[48] + lsa_0[48] + lsa_0[57] + lsa_0[46] + 
      lsa_0[48] + lsa_0[57] + lsa_0[46] + lsa_0[49] + lsa_0[49] + lsa_0[32] + lsa_0[50] +
      lsa_0[51] + lsa_0[58] + lsa_0[53] + lsa_0[57] + lsa_0[58] + lsa_0[48] + lsa_0[48]);
   if (IsDemoMode(l_str2time_8)) {
      Print("Demo period has expired " + TimeToStr(l_str2time_8, TIME_DATE|TIME_SECONDS));
      return (1);
   }
   Print("You can work until " + TimeToStr(l_str2time_8, TIME_DATE|TIME_SECONDS));
   return (0);
}

bool IsDemoMode(int ai_0) {
   if (TimeCurrent() >= ai_0) return (TRUE);
   return (FALSE);
}
As you can see, the string with date is encoded and at first glance you can't understand what is checked and how. However, the by the source code it's quite clear where and what to edit in the IsDemoMode function, so that protection is disabled.

MQLEnigma - Encoder of MQ4 Source Codes

To struggle against existing decompiler, we have to learn how to replace the names of used functions. This is virtually impossible by means of MQL4 (well, except that you do content replacement of normal names with outright rubbish). So I had to write encoder program using VB.NET. 
Why VB.NET? Just because for the last few years I do a lot of coding on VBA and VB.NET, so with its help I was able to accomplish this task quickly and easily. In addition, the compilation was made in Visual Studio Express, which is completely free to use.
The only disadvantage for future users of this program - they need to have .NET FrameWork 3.5 installed on their systems. But, despite of its decent amount, it may be already installed on systems with modern software, which is often written on .NET and installed along with it. If there is no .NET Framework in your system, you can download it fromhere and install it by yourself.
MQLEnigma - is a console application. It has a mandatory parameter - the name of file for encoding. After that the following manipulations are made with text:
  1. Insert all #include files. If you have global variables that are used in different files in other Expert Advisors, they must be gathered in one common file. So replacement will affect only this particular Expert Advisor, and others will continue to use the included file with unencrypted names.
  2. Cut off all comments from the resulting total text (not to run into something like // int i=0;).
  3. Divide cleared text into two parts: the function bodies (these are cut off and analyzed separately), and all external variables and #define (as well as function declarations).
  4. Remove all descriptions of imported functions from the block of external texts. Their names are given from the outside and can not be encoded.
  5. Find descriptions of common types like int, string, etc. in both blocks of text (internal and external). Delete variable initializations and array dimensions from these types. 
  6. Delete the #define keyword and parameter setting from the #define sections, so that only defined names are left. Also delete reserved keywords (i.e. that you won't accidentally replaced the name of Magenta color with some garbage).
  7. As a result, only the names of variables, internal functions, and declared constants are left. These names are collected into common list, from which the duplicates are removed (description like int i=0; can occur within several functions). Created are the "garbage" names of variable for replacements and determined are the lengths of found identificators to perform replacements from the longest ones. Otherwise, in case of two variables like str and str2str, the longest str2str can have the wrong name, if two str "parts" of it would be replaced first.
That's it: cleaned full text of Expert Advisor file, with all the #includes inserted into it, is written into a separate file with the Open suffix. After that the identificators are replaced. The table of matching identificator names is written into a separate file with the Encodings suffix, and the encoded file is written with the Encoded suffix. You'll need to compile this very file and distribute the resulting ex4.
New names can be assembled as you like, but they must by meaningless and unique. I used a simple method: I took the maximal integer, from the left appended it to the valid, but "invisible" character with code 160 (non-breaking space) and added random numbers to left and right of the main number to increase the garbage. When forming the next name the 1 is subtracted from the previous main number (to ensure uniqueness of the name) and then garbage and invisible space are appended.
In order not to replace the variable names in the text constant like:
Print(" LotSize = " + DoubleToStr(LotSize,2));
I've used the following trick: before replacing the variables, after each character within constant I've inserted the character with code 3. It can be simply typed on the keyboard, and therefore it can't be in your text. As a result of the "LotSize =" constant transformed into "#L#o#t#S#i#z#e# #=# #" (where # means the character with code 3). Now if I have to search for substring to replace LotSize in string constant, I simply won't find it and it will remain unnoticed. After all these variables will be replaced, I'll simply cut all characters with code 3 and the original string constants will be restored.
When we've replaced the text of the previous example, the variables found according to this list (the first number - the number of found occurrences of the identificator in the source code):
21      char             2114319876214748364748749 
6       i                1596751872214748364643597 
1       IsDemoMode       158651616521474836452710 
5       LastAllowedDate  3650920921474836448123 
then we've got the following file:
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"
int start()
{
  string  2114319876214748364748749 [256]; int  1596751872214748364643597 ;
  for ( 1596751872214748364643597  = 0;  1596751872214748364643597  < 256;  1596751872214748364643597 ++)
  2114319876214748364748749 [ 1596751872214748364643597 ] = CharToStr( 1596751872214748364643597 );
  int  3650920921474836448123  = StrToTime(
  2114319876214748364748749 [50]+ 2114319876214748364748749 [48]+ 2114319876214748364748749 [48]+
  2114319876214748364748749 [57]+ 2114319876214748364748749 [46]+ 2114319876214748364748749 [48]+
  2114319876214748364748749 [57]+ 2114319876214748364748749 [46]+ 2114319876214748364748749 [49]+
  2114319876214748364748749 [49]+ 2114319876214748364748749 [32]+ 2114319876214748364748749 [50]+
  2114319876214748364748749 [51]+ 2114319876214748364748749 [58]+ 2114319876214748364748749 [53]+
  2114319876214748364748749 [57]+ 2114319876214748364748749 [58]+ 2114319876214748364748749 [48]+
  2114319876214748364748749 [48]
  );
  if ( 158651616521474836452710 ( 3650920921474836448123 ))
  {
    Print("Demo period has expired " + TimeToStr( 3650920921474836448123 ,TIME_DATE|TIME_SECONDS));
    return(1);
  }
  Print("You can work until "+ TimeToStr( 3650920921474836448123 ,TIME_DATE|TIME_SECONDS));
}
bool  158651616521474836452710 (int  3650920921474836448123 )
{
  if (TimeCurrent() >=  3650920921474836448123 ) return(true); else return(false);
}
Such encoding of the source text has one amusing feature: suppose that you have Expert Advisor source code, but you do not want to let it go. But now you can give this encoded text, in fact you've still given the source code, but the secret of its algorithm was not disclosed.
After its decompilation we get the following code:
#property copyright "Copyright © 2009, Sergey Kravchuk"
#property link      "http://forextools.com.ua"

int start() {
   string lsa_0[256];
   for (int l_index_4 = 0; l_index_4 < 256; l_index_4++) lsa_0[l_index_4] = CharToStr(l_index_4);
   int l_str2time_8 = StrToTime(lsa_0[50] + lsa_0[48] + lsa_0[48] + lsa_0[57] + lsa_0[46] + 
      lsa_0[48] + lsa_0[57] + lsa_0[46] + lsa_0[49] + lsa_0[49] + lsa_0[32] + lsa_0[50] +
      lsa_0[51] + lsa_0[58] + lsa_0[53] + lsa_0[57] + lsa_0[58] + lsa_0[48] + lsa_0[48]);
   if (f0_1276(l_str2time_8)) {
      Print("Demo period has expired " + TimeToStr(l_str2time_8, TIME_DATE|TIME_SECONDS));
      return (1);
   }
   Print("You can work until " + TimeToStr(l_str2time_8, TIME_DATE|TIME_SECONDS));
   return (0);
}

bool f0_1276(int ai_0) {
   if (TimeCurrent() >= ai_0) return (TRUE);
   return (FALSE);
}
It has no meaningful names (well, except for reserved 'start' and standard function names), and although you can sort out this simple example, but more complex text with lots of variables will be completely inadequate. Its hacking cost will be so high that it will be cheaper and easier to buy Expert Advisor from its author, while receiving official support.

Conclusion

To be honest, MQLEnigma was developed in the worst traditions of Extreme Programming. I assumed that the input source text is syntactically "correct." Well, for example, there must be no mismatching braces of functions, type declarations without variable names (int;), etc. The algorithm was developed "on the fly" - I took my largest project and gradually cut out all unnecessary, while looking at the resulting text - after all, only variable names have to remain. That's why I did not include numerous exceptions and possible errors handling.
In addition, the upcoming MQL5 will have protection against decompilation, so this work makes sense only for MQL4 programs. For the same reason, I've chosen VB.NET - using this (VBA, to be more precise) tool I'm doing my every day job, so it was more easier, faster and comfortable for me to harness it.
Despite this inaccurate way of programming MQLEnigma works, and yet I haven't run into a source code, that was wrongly processed and its compilation would lead to errors. But this does not mean, that this way is absolutely correct. That's why I give its full source code. If you have MQLEnigma to work incorrectly, you will able to find the cause and, if necessary, correct it by yourself (if this happens, please do not forget to inform me about the modification made in the discussion of this article).
This article considers only the simplest ways of protection, but nevertheless they can effectively protect your developments. Going back to what I wrote in the beginning of this article, I can say the same thing that I've wrote in the conclusion of my very first license FairWareThe author have helped you, by writing programs that you may never have been invented or written by yourself. Now - its your turn to help the author, as you can :-) .
The source code of MQLEnigma may contain some logic errors that were not apparent on those texts that I have during debugging. If you find them, please let me know so I can make changes and update the files attached to this article. If you know other ways of protection, that can be openly published without being an aid for hackers, leave your comments. I and other members of our MQL4 community will be grateful to you for your contribution.
Well, the final conclusion: subject of source code protection is very challenging. Sharing all the secrets is not a good idea, because thus you show potential attackers your weaknesses. I decided to publish this article only because there is nothing new for decoders. However, these are the first well known methods of protection, that work quite effectively, and they can be useful, especially for beginners in MQL programming.
Attachments: 
 files_en.zip (29.2 Kb)

2 comments:

  1. Hey Everybody,

    I've attached a list of the most recommended forex brokers:
    1. Best Forex Broker
    2. eToro - $50 minimum deposit.

    Here is a list of the best forex tools:
    1. ForexTrendy - Recommended Probability Software.
    2. EA Builder - Custom Strategies Autotrading.
    3. Fast FX Profit - Secret Forex Strategy.

    I hope you find these lists helpful.

    ReplyDelete
  2. GPS robot [10 times increase of the deposit amount]

    I just finished a webinar with Mark and his partner, Antony, two days ago and it was AWESOME.

    During the webinar Mark and Antony shared their secrets to success and answered questions about their new release of the GPS Forex Robot that is coming out TODAY!

    ReplyDelete