obfuscating / protecting LUA code

classic Classic list List threaded Threaded
28 messages Options
12
Reply | Threaded
Open this post in threaded view
|

obfuscating / protecting LUA code

bert-6
Hi,
 
I'm working on a piece of software in LUA that might be part of a commercial application later on (or might become the application by itself, since LUA is so nice...) and I'm trying to find out if there is a good way to protect LUA code from the outside world? Of course I could compile it using luac, but that wouldn't stop somebody from disassembling it and getting the source code?
 
Thanks,
Bert
 


New Yahoo! Messenger with Voice. Call regular phones from your PC and save big.
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Luiz Henrique de Figueiredo
> I could compile it using luac, but that wouldn't stop somebody from
> disassembling it and getting the source code?

Compiling with luac is a good option: Adobe distributes Lightroom with
lots of precompiled Lua code, for instance. They don't seem worried.

For non trivial programs, it is not easy to reconstruct the souce
code from the bytecode. The best effort in the direction is LuaDec
(http://luadec.luaforge.net/), but even that does not recover
complete source code.
--lhf
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Paul Smith-6
In reply to this post by bert-6
At 12:10 28/04/2006, you wrote:
>Hi,
>
>I'm working on a piece of software in LUA that might be part of a
>commercial application later on (or might become the application by
>itself, since LUA is so nice...) and I'm trying to find out if there is a
>good way to protect LUA code from the outside world? Of course I could
>compile it using luac, but that wouldn't stop somebody from disassembling
>it and getting the source code?

Well, as some totally un-thought-through thoughts...

- You could encrypt your script however you want and save it as a binary
file. Then, when you want to run it, load the binary file, decrypt it to a
long string and pass it to luaL_loadbuffer.

- You could change the order of the 'RESERVED' enum in llex.h (read the
comment before that and do what it says). then compile the code. That way I
guess an 'off the shelf' decompiler will probably have trouble
understanding the compiled code.




Paul                            VPOP3 - Internet Email Server/Gateway
[hidden email]                      http://www.pscs.co.uk/


Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Erik Hougaard
In reply to this post by bert-6
bert wrote:

> Hi,
>  
> I'm working on a piece of software in LUA that might be part of a
> commercial application later on (or might become the application by
> itself, since LUA is so nice...) and I'm trying to find out if there
> is a good way to protect LUA code from the outside world? Of course I
> could compile it using luac, but that wouldn't stop somebody from
> disassembling it and getting the source code?
>  
> Thanks,
> Bert
>  
>
> ------------------------------------------------------------------------
> New Yahoo! Messenger with Voice. Call regular phones from your PC
> <http://us.rd.yahoo.com/mail_us/taglines/postman5/*http://us.rd.yahoo.com/evt=39666/*http://messenger.yahoo.com>
> and save big.

There are two ways,

1. Encrypt your source files (either bytecode or real source) - This is
the only real way.

2. Obfuscating your bytecode files (luac output) be different means. you
could change lopcodes.h so you use your own opcodes-order ... that would
require a fair amount of analyse.

/Erik
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Luiz Henrique de Figueiredo
In reply to this post by Paul Smith-6
> - You could change the order of the 'RESERVED' enum in llex.h

No, compiled code contains no lexical elements.

You could reorder the VM instructions in lopcodes.h, but then you need
to fix lopcodes.c. It's simpler to swap the position of the B and C
fields in the VM instructions, if you want to go this way.

A much simpler solution is to write your own format for precompiled
code. Simply reorder the items in DumpFunction (and LoadFunction).
Or reorder or alter the items in luaU_header (this seems the simplest solution).
And don't tell anyone!
--lhf
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

bert-6
Just wanted to thank all of you for the great replies :-) power to Lua !

Luiz Henrique de Figueiredo <[hidden email]> wrote:
> - You could change the order of the 'RESERVED' enum in llex.h

No, compiled code contains no lexical elements.

You could reorder the VM instructions in lopcodes.h, but then you need
to fix lopcodes.c. It's simpler to swap the position of the B and C
fields in the VM instructions, if you want to go this way.

A much simpler solution is to write your own format for precompiled
code. Simply reorder the items in DumpFunction (and LoadFunction).
Or reorder or alter the items in luaU_header (this seems the simplest solution).
And don't tell anyone!
--lhf


Blab-away for as little as 1ยข/min. Make PC-to-Phone Calls using Yahoo! Messenger with Voice.
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Andy Stark
In reply to this post by Luiz Henrique de Figueiredo
Lua list <[hidden email]> on  at   wrote:
>You could reorder the VM instructions in lopcodes.h, but then you need
>to fix lopcodes.c.

The lopcodes.h and lopcodes.c source files are quite short and have a
fairly simple structure. Perhaps a future distribution of Lua could
include a Lua script that generates these two files and has an option to
permute the order of opcodes using a seed specified by the user. For
simplicity you could use

        (standardOpcodeNumber * primeNumber) % numberOfOpcodes

but some kind of seeded pseudo-random ordering would be more secure.

Having the opcode information in a Lua table in the script might be useful
for other purposes too, for documentation or writing disassemblers, etc.

&.

PS - standard pre-generated versions of lopcodes.h and lopcodes.c should
still be supplied with Lua - the script should just be an extra tool for
those who need it.


#####################################################################################
This e-mail message has been scanned for Viruses and Content and cleared
by NetIQ MailMarshal.
The Blackpool Sixth Form College.
#####################################################################################
Reply | Threaded
Open this post in threaded view
|

Negative zero value

Andy Stark
In reply to this post by Erik Hougaard
I've just written a quick Lua script to look at the permutation expression
I mentioned in the thread about obfuscating Lua bytecode. The first
iteration of the loop executes as

        (0 * 13) % 38

The value is zero, of course, but it prints out as -0! It turns out that
zero mod anything gives -0 as a result. Bug or feature? (It's on MacOSX
10.3 PPC if that makes any difference.)

&.


#####################################################################################
This e-mail message has been scanned for Viruses and Content and cleared
by NetIQ MailMarshal.
The Blackpool Sixth Form College.
#####################################################################################
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Kein-Hong Man
In reply to this post by Andy Stark
Andy Stark wrote:

> Lua list <[hidden email]> on  at   wrote:
>> You could reorder the VM instructions in lopcodes.h, but then you need
>> to fix lopcodes.c.
>
> The lopcodes.h and lopcodes.c source files are quite short and have a
> fairly simple structure. Perhaps a future distribution of Lua could
> include a Lua script that generates these two files and has an option to
> permute the order of opcodes using a seed specified by the user. For
> simplicity you could use
> [snip]

Once someone finds the main VM function using a debugger, the game
of hide-and-seek is essentially over. If the Intellectual Property
is really, really valuable, legal action is probably the only way
to stop commercial duplication of your work. Reverse engineering
is hard to stop. What method you choose depends very much on the
"whole picture".

> Having the opcode information in a Lua table in the script might be useful
> for other purposes too, for documentation or writing disassemblers, etc.

But since the internals of Lua change from version to version,
keeping in touch with the internals is going to be a little
masochistic. :-)

--
Cheers,
Kein-Hong Man (esq.)
Kuala Lumpur, Malaysia

Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

David Given
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kein-Hong Man wrote:
[...]
> Once someone finds the main VM function using a debugger, the game of
> hide-and-seek is essentially over. If the Intellectual Property is
> really, really valuable, legal action is probably the only way to stop
> commercial duplication of your work. Reverse engineering is hard to
> stop. What method you choose depends very much on the "whole picture".

*nods*

After all, the *computer* has to figure out what the code does in order to
execute it; this means that a human can, too. The best you can do is to make
this hard. You can't make it impossible. Make things *too* hard and you end up
shooting yourself in the foot, because you'll end up making your life a misery
for yourself.

I'd suggest that probably the best thing to do is to compile the bytecode with
luac (so there isn't obvious source code lying around), and then put a licence
on the finished product saying that your users aren't allowed to copy it.

- --
+- David Given --McQ-+ "If you're up against someone more intelligent
|  [hidden email]    | than you are, do something insane and let him think
| ([hidden email]) | himself to death." --- Pyanfar Chanur
+- www.cowlark.com --+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEUlmQf9E0noFvlzgRArRIAKDeI9TBhxNrRhNBpkoSPqOMbS7KHwCfe+Mi
0xBurM6MU9M1DTc9Ra86AjM=
=DDRf
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Luiz Henrique de Figueiredo
> probably the best thing to do is to compile the bytecode with luac

As I suggested earlier, if you are concerned that users will simply run
"luac -l" on the compiled code and see what the program does, you can
just change LUA_SIGNATURE to something else (but keep a non-printable
char as its first byte) and possibly also reorder the fields in the
header. This will make off-the-shelf luac choke. Most users will just
give up right there. Those that don't won't be stopped by anything more
complicated.

--lhf
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Shmuel Zeigerman-2
In reply to this post by bert-6
bert wrote:
> I'm working on a piece of software in LUA that might be part of a
> commercial application later on (or might become the application by
> itself, since LUA is so nice...) and I'm trying to find out if there is
> a good way to protect LUA code from the outside world? Of course I could
> compile it using luac, but that wouldn't stop somebody from
> disassembling it and getting the source code?

There's one point that seems to be not mentioned yet - obfuscating names
of variables. It's not easy to understand non-trivial code as it is, but
if all the variables look like a137, d86, etc., the cracker's task
should be much harder to accomplish.

--
Shmuel
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

David Given
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Shmuel Zeigerman wrote:
[...]
> There's one point that seems to be not mentioned yet - obfuscating names
> of variables. It's not easy to understand non-trivial code as it is, but
> if all the variables look like a137, d86, etc., the cracker's task
> should be much harder to accomplish.

If you use locals everywhere you can, rather than global variables (a good
idea anyway because it'll speed things up), then the compiler doesn't keep
track of the names therefore they won't get emitted. (Except in the debugging
code, with you remove with the luac -s option.)

Global variables are, after all, just syntactic sugar for accessing the _G table.

*Don't* obfuscate your source code unless you truly desire a long stay at
Arkham Asylum!

- --
+- David Given --McQ-+ "If you're up against someone more intelligent
|  [hidden email]    | than you are, do something insane and let him think
| ([hidden email]) | himself to death." --- Pyanfar Chanur
+- www.cowlark.com --+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEUoYLf9E0noFvlzgRAuVbAJ4gTJcdZoN/r78ZsItb9hacG4QUwQCffZXx
vQb2qs6YtD8KpgRWqtbtNxQ=
=0799
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Mike Pall-4-2
Hi,

David Given wrote:
> (Except in the debugging
> code, with you remove with the luac -s option.)

Which reminds me: I don't need it for obfuscation, but to save
space. luac uses the internal function luaU_dump() since the
option to strip debug symbols is missing from string.dump and
lua_dump().

To the Lua team: Can we get this functionality exposed to the
API? Thank you!

Bye,
     Mike
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Shmuel Zeigerman-2
In reply to this post by David Given
David Given wrote:
> If you use locals everywhere you can, rather than global variables (a good
> idea anyway because it'll speed things up), then the compiler doesn't keep
> track of the names therefore they won't get emitted. (Except in the debugging
> code, with you remove with the luac -s option.)

That's right regarding local variables' names, but what about table
fields' names? luac keeps them intact, even with the -s option.

> *Don't* obfuscate your source code unless you truly desire a long stay at
> Arkham Asylum!

I meant automatic obfuscating of variables' names, an additional
"compilation" step, part of the make process. This shouldn't hurt the
original source code.

--
Shmuel
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Luiz Henrique de Figueiredo
> I meant automatic obfuscating of variables' names, an additional
> "compilation" step, part of the make process. This shouldn't hurt the
> original source code.

This can be easily done by having DumpString do something with the
string before dumping it. (ROT 13 comes to mind as a simple example.)
Of course, LoadString will then have to undo it.
--lhf
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

David Given
In reply to this post by Shmuel Zeigerman-2
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Shmuel Zeigerman wrote:
[...]
> That's right regarding local variables' names, but what about table
> fields' names? luac keeps them intact, even with the -s option.

You can't change these without changing the behaviour of your program ---
table fields are data, not code.

for i, j in pairs(...) do
  print(i, j) -- will break if i has been munged!
end

- --
+- David Given --McQ-+ "If you're up against someone more intelligent
|  [hidden email]    | than you are, do something insane and let him think
| ([hidden email]) | himself to death." --- Pyanfar Chanur
+- www.cowlark.com --+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEUpRmf9E0noFvlzgRAvkcAJwKqG74Qev+Wrsc1aFpAjkzBapy3ACffCwx
lC+ZXeQ1rDpB6g5SCzOeOTk=
=wbHs
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Shmuel Zeigerman-2
David Given wrote:

> Shmuel Zeigerman wrote:
>>That's right regarding local variables' names, but what about table
>>fields' names? luac keeps them intact, even with the -s option.
>
> You can't change these without changing the behaviour of your program ---
> table fields are data, not code.
>
> for i, j in pairs(...) do
>   print(i, j) -- will break if i has been munged!
> end

I'm afraid I don't understand you. It's not `i' (a local variable) that
should have been munged, but table field names (keys of string type).

E.g., instead of:
   local t1 = { height=10, width=20 }
will be:
   local t1 = { a45=10, b099=20 }

--
Shmuel
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

David Given
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Shmuel Zeigerman wrote:
[...]
> I'm afraid I don't understand you. It's not `i' (a local variable) that
> should have been munged, but table field names (keys of string type).

Yeah, sorry, it's late.

Try this instead, which is a common idiom:

d = {
        one = 1, [1] = "one",
        two = 2, [2] = "two",
        three = 3, [3] = "three"
}

Renaming field names will horribly mangle this.

My point is that field names are not just arbitrary symbols (like local
variable names). They're actually *data*, which your program may need to
process, and therefore changing them will break your program.

- --
+- David Given --McQ-+ "If you're up against someone more intelligent
|  [hidden email]    | than you are, do something insane and let him think
| ([hidden email]) | himself to death." --- Pyanfar Chanur
+- www.cowlark.com --+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEUqpKf9E0noFvlzgRAtDZAJ4jsoJBPTJlGS1FluRtC8MA9kOccACfdNgT
+waCteq9mxOFthP9ccqHKyg=
=36XM
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: obfuscating / protecting LUA code

Shmuel Zeigerman-2
David Given wrote:

> Try this instead, which is a common idiom:
>
> d = {
> one = 1, [1] = "one",
> two = 2, [2] = "two",
> three = 3, [3] = "three"
> }
>
> Renaming field names will horribly mangle this.
>
> My point is that field names are not just arbitrary symbols (like local
> variable names). They're actually *data*, which your program may need to
> process, and therefore changing them will break your program.

I can see your point. This may possibly be considered as a special case
for the obfuscator to handle. The obfuscator can be made smart! :)

--
Shmuel
12