Self Encrypting Code

Foreground

This is another technique I created as part of the protection for the trainer engine project in early 2004. Coincidentally, someone had the same idea on the board a couple of months later.

This technique involves FASM's ability to manipulate the bytes of the code it had already assembled. In this case, we use a simple cryptor to encrypt a chunk of assembled code during compile time. At run-time, we run a short loop that decrypts the code in memory.

One particular thing to note is that the .code section is marked as writeable. This is needed so the code can be decrypted and written back at run-time.

You can find a more elaborate encryption algorithm as part of trainer engine.

 

Code

  1. ; selfencrypt
  2. ; 04.07.2008
  3.  
  4. format PE GUI 4.0
  5. entry start
  6.  
  7. include "%include%/win32a.inc"
  8.  
  9. ;
  10. ; This is the encryption macro.
  11. ; It is a simple XOR with 0xAA (10101010 in binary).
  12. ;
  13. macro encrypt dstart,dsize {
  14.     local ..char,..key,..shift
  15.     repeat dsize
  16.         load ..char from dstart+%-1
  17.         ..char = ..char xor $AA
  18.         store ..char at dstart+%-1
  19.     end repeat
  20. }
  21.  
  22. section ".code" code readable writeable executable
  23. start:
  24.         ;
  25.         ; This will be the only non-encrypted part of the code.
  26.         ; Here we will decrypt the code at run-time.
  27.         ;
  28.         mov     edx,real_start
  29.         xor     eax,eax
  30.         mov     ecx,code_size
  31. @@:     xor     byte [edx],$AA
  32.         inc     edx
  33.         loop    @B
  34.  
  35. real_start:
  36.         ;
  37.         ; Everything from here on will be encrypted.
  38.         ;
  39.         stdcall [MessageBox],0,HelloWorld,HelloWorld,MB_ICONASTERISK
  40.  
  41.         stdcall [ExitProcess],0
  42.  
  43.         ;
  44.         ; Encrypt everything from real_start to here.
  45.         ;
  46.         display "Encrypting code... "
  47.         code_size = $ - real_start
  48.         encrypt real_start,code_size
  49.         display "done",13,10
  50.  
  51. section ".data" data readable writeable import
  52.         library kernel32,"kernel32.dll",user32,"user32.dll"
  53.         include "%include%/api/kernel32.inc"
  54.         include "%include%/api/user32.inc"
  55.  
  56.         HelloWorld      db      "Hello World!",0