Hi all, I come today to talk about Lua encyption and security. I have recently seen quite a few threads pop up about decrypting of lua cache files (which has been around since the beginning of lua cache files in gmod), and an (bad) attempt to secure lua files using some default lua functions.
So after some thought, I have come up with a few things that would seem like a fairly good attempt at securing our client/shared files, but some problems exist with them.
[B]Solution 1: (XOR)[/B]
I have found that we can actually use xor encyption in glua, manipulating string.byte and bit.bxor. This way we can make our own unique keys and own unique ways of encrypting data. Here is a simple function that allows you to pass a string and a key to it, and it will return the xor'd version:
[code]
function xorstring(toenc, key)
local endstr = "";
for i = 1, #toenc do
local keyind = ((i - 1) % #key) + 1
endstr = endstr..string.char(bit.bxor(string.byte(toenc[i]), string.byte(key[keyind])))
end
return endstr;
end
[/code]
This function paired up with these next two can do a lot:
[code]
function fillleft(str, amt, rep) -- not sure if there is a default function for this
local rep = tostring(rep);
local str = tostring(str);
for i = #str, amt - 1 do
str = rep..str;
end
return str;
end
function readbytes(str)
local ends = "";
for i = 1, #str do
ends = string.format("%s%s ", ends, fillleft(string.byte(str[i]), 2, 0));
end
return ends
end
[/code]
For example if we were to do this:
[code]
print(readbytes(xorstring("Blob Dillon", "Alphabet")));
[/code]
It would print: 03 00 31 10 65 38 12 24 45 03 30
Calling this function again with the same key would output the original function:
[img]http://puu.sh/6tgFF.png[/img]
[B]Solution 2: (Running Bytecode)[/B]
I have found out that some default lua functions allow you to read and run bytecode, but unfortunately the running of bytecode is not supported in glua.
I have researched this a bit and found out that there could be a risk for hacks when allowing people to load bytecode, but, this simply [b]does not make sense[/b]. People can easily load hacks without using bytecode, why limit the possibilities just because of a really low risk of someone having to load bytecode instead of regular lua hacks? (garry pls fix it the way it is meant to be? :D)
Now, instead of me getting sidetracked into this hacking area of glua, I will explain how bytecode can secure your client and shared lua files.
Think of it this way, Lua reads your text data and converts it into bytes that can be interpreted to do something else, much like any other language (C++, C, .NET). string.dump allows you to dump the function you pass to it's bytes into a string. You could pass this to a client and call loadstring or load with this string. This would load the function without having any text with it, thus making it [b]harder[/b] (not impossible) for many people to get the text associated with it, and make the need for encoding the plain text not needed.
What are your thoughts on the matter? Do you have any ideas for securing lua files/code? Am I trying too hard? Post below!
When will people realize encryption is useless if all it takes is RunString = print?
[QUOTE=Linda;43622113]When will people realize encryption is useless if all it takes is RunString = print can make it useless.[/QUOTE]
You do realize that can be easily bypassed if one wanted it to be, in init.lua do:
[code]
SomeOtherFuncName = RunString;
RunString = function() SomeOtherFuncName() end -- in case of emergency!
[/code]
But what do you think about the second encyption method? It does not need the use for running any string at all.
If I override RunString first then you'll just be declaring the new var as whatever I changed RunString to. I'll address your other stuff when I get home.
[QUOTE=Linda;43622162]If I override RunString first then you'll just be declaring the new var as whatever I changed RunString to. I'll address your other stuff when I get home.[/QUOTE]
Changing RunString can also be detected by just using string.dump and comparing it to the real value of string.dump(RunString), but yes that can be detoured to and, yes, everything that can detect everything can be detoured successfully, so it is only a matter of "who can be the biggest no lifer" when it comes to detecting it.
You can't dump RunString or print. They're declared in C. Go try it.
These aren't solutions. But let's assume that for some reason, we couldn't detour RunString, The client would still need to know the key, and thus anyone can still decrypt it. We went over this in the last thread.
At the end of the day, the client side code is not the important stuff when it comes to how the game works.
[QUOTE=SomePerson_;43622041]... but, this simply [b]does not make sense[/b]. People can easily load hacks without using bytecode, why limit the possibilities just because of a really low risk of someone having to load bytecode instead of regular lua hacks? (garry pls fix it the way it is meant to be? :D)[/QUOTE]
There are a handful of bugs in bytecode that allow essentially arbitrary memory access in the 5.1 VM. I would assume such bugs also exist in some form in the LuaJIT 5.1 VM, and so it would be very unsafe to allow servers to run completely unknown bytecode on a client.
Peter Cawley did quite a bit of research on this for the 5.1 VM: [url]http://www.lua.org/wshop11/Cawley.pdf[/url]
edit:
The problem with your XOR obfuscation is that say all your client files are leaked without the key but obfuscated. The key is much shorter than the source material, so brute forcing it would be very simple (especially if it had a limited character set). You could mitigate this by using a stronger cryptographic algorithm such as AES, but the weakness is still intercepting the key or the execution on the client. I don't agree with the premise of obfuscation and sending to the client post-init, since you're just wasting bandwidth, missing critical setup windows, and it's just generally inefficient.
You're not going to stop people getting your code, Lua's a scripting language. The best you can do is obfuscate it, anything else is a pointless exercise, even compiling to byte code: writing decompilers is just trivial for that.
No form of [I]"encryption"[/I] will block people from using at your code. If you use net messages, they can be captured. If the clientside code has some form of actual encryption applied to it, someone here will be able to decrypt it within hours; as there has to be a decryption method in lua as well (and from my knowledge lua is extremely limited).
It's impossible to completely secure clientside code, as long as it's still on the client it's vulnerable. I think instead of encrypting your code and hoping people won't use it, you should file for a copyright on your code/get DMCA protection and take legal action if someone uses it. This is the best way to ensure it's security, if you're that worried. Sure, I could steal Apple.com's frontend but I'll be infringing their site.
At least this way, people that legitimately need to view code for educational purposes have the ability to.
[QUOTE=Linda;43622278]You can't dump RunString or print. They're declared in C. Go try it.[/QUOTE]
[code]
local oldfenv = getfenv(1)
local t = {}
t.__index = function( tabl , key )
if key == 'RunString' then
return oldfenv['print']
end
return oldfenv
end
local new_G = setmetatable( t , {_G = oldfenv} )
setfenv(1, new_G )
[/code]
Untested but should work.
[QUOTE=Linda;43622278]You can't dump RunString or print. They're declared in C. Go try it.[/QUOTE]
I forgot about that, you are correct. Still, there are many other ways to detect it, and in the end it is still a matter of who is more of a no life..
[QUOTE=AzuiSleet;43622331]There are a handful of bugs in bytecode that allow essentially arbitrary memory access in the 5.1 VM. I would assume such bugs also exist in some form in the LuaJIT 5.1 VM, and so it would be very unsafe to allow servers to run completely unknown bytecode on a client.
Peter Cawley did quite a bit of research on this for the 5.1 VM: [url]http://www.lua.org/wshop11/Cawley.pdf[/url]
[/QUOTE]
That was an interesting read. That would make clients able to be exploited to read personal data, and other things, correct? That'd make my bytecode possibility out of the question.
[QUOTE=AzuiSleet;43622331]edit:
The problem with your XOR obfuscation is that say all your client files are leaked without the key but obfuscated. The key is much shorter than the source material, so brute forcing it would be very simple (especially if it had a limited character set). You could mitigate this by using a stronger cryptographic algorithm such as AES, but the weakness is still intercepting the key or the execution on the client. I don't agree with the premise of obfuscation and sending to the client post-init, since you're just wasting bandwidth, missing critical setup windows, and it's just generally inefficient.[/QUOTE]
Imagine having a random amount (up to however long the way you are sending data allows) of a set of 255 different characters, would you be able to forcebrute that effectively?
[QUOTE=Matt-;43622338]You're not going to stop people getting your code, Lua's a scripting language. The best you can do is obfuscate it, anything else is a pointless exercise, even compiling to byte code: writing decompilers is just trivial for that.[/QUOTE]
as long as no one releases something for that (whistles while staring at you), it will be fine for most people.
[QUOTE=SomePerson_;43622532]as long as no one releases something for that (whistles while staring at you), it will be fine for most people.[/QUOTE]
Unfortunately, bad people always exist. So relying on your trust that nobody will write a decompiler is a little silly.
[QUOTE=Matt-;43622647]Unfortunately, bad people always exist. So relying on your trust that nobody will write a decompiler is a little silly.[/QUOTE]
I'm not relying on people not to write a decompiler, I'm actually expecting people to.
I've had a file stealer for years, many many years, and many other people have had them too. The people who make them are usually smart enough [b]not to release them[/b], though.
[QUOTE=SomePerson_;43622712]I'm not relying on people not to write a decompiler, I'm actually expecting people to.
I've had a file stealer for years, many many years, and many other people have had them too. The people who make them are usually smart enough [B]not to release them[/B], though.[/QUOTE]
I guess I'm too dumb, but in all honesty the files were never ment to be hidden from the public in the first place. They've always just been a zip file.
RunString("bytecode") is possible FYI, and on top of that
If you detour RunStringEx in c++, you can catch all lua ran, decrypted, and it's completely readable.
Encrypting your cache only stops people from using a 30 line decompiler, instead, they'll need to use a 60-70 line runstringex detour
[QUOTE=zerothefallen;43622828]RunString("bytecode") is possible FYI[/QUOTE]
The only reason bytecode loading in this way doesn't work every time is because garry essentially uses strlen to get the length of the input string, which means that it's truncated after the first null byte. Bytecode loading is not disabled anywhere - it's literally only stopped by the behaviour of strlen.
Where's Acecool? I'm sure he'd be having a field day at all this shit.
Would it be possible to execute code without RunString? For instance, using patterns, to execute a string based off its contents and completely avoid predefined Lua compilation?
Regardless I find that string encryption (not just Lua files to be executed) is a valuable tool for data storage.
[QUOTE=bobbleheadbob;43623942]Where's Acecool? I'm sure he'd be having a field day at all this shit.
Would it be possible to execute code without RunString? For instance, using patterns, to execute a string based off its contents and completely avoid predefined Lua compilation?
Regardless I find that string encryption (not just Lua files to be executed) is a valuable tool for data storage.[/QUOTE]
Not possible to execute Lua without RunString.
This thread is pretty much done as zero said above, all it takes is a C detour on RunString and there is no way to stop it.
You can obfuscate your clientside Lua, but you will never be able to encrypt it. /thread
is the hip new glua thing to do encryption? why does everybody want to hide their shit so bad?
[QUOTE=anime dad;43624981]is the hip new glua thing to do encryption? why does everybody want to hide their shit so bad?[/QUOTE]
Because they don't understand how much of a waste of time it is, legal action is the much better way to secure your code if you're really that upset.
At least then you might be able to gain something out of it.
I'm never going to encrypt my code, if someone wants access to any of my source I'd just give it to them.
Anyone can view the clientside source of a website, does that mean they use it for harm all the time?
Client/Shared code is required to be networked for proper gamemode/server function (obviously), so there's really no point in hiding what you're sending them. Especially since they can either steal or remake your client side source.
All this encryption talk is probably because of that terrible "coderhire" place. If people weren't [URL="http://coderhire.com/jobs/view/3257"]shelling out 7 bucks for super simple scripts,[/URL] people wouldn't be pissed about code decompiling.
And more about that particular one, look at the copyright.
[QUOTE]The creator of the code and/or content [B]will not[/B] have rights to use, resell or redistribute the code and/or content.[/QUOTE]
Under this logic, after the person gets paid their 7 bucks, they aren't allowed to reuse the thing [I]they made.[/I]
I can understand a system for being able to pay people for their hard work.
But this?
Shit like that is highway robbery. And it's why people keep striving to encrypt code.
EDIT: Here's an even worse example with an even worse license: [url]http://coderhire.com/jobs/view/3267[/url]
[QUOTE]Full Rights - The purchaser of the code and/or content will have full rights to use, resell or redistribute the code and/or content. The creator of the code and/or content will not have any rights to use, resell or redistribute the code and/or content.[/QUOTE]
This is literally just "here's 16 bucks, your code is mine, don't you dare claim it's yours or use it again otherwise I can sue your ass."
People like this are encouraging this baseless need to encrypt the code. The people who make extreme amounts of money off of selling their cheap likely borrowed from garrysmod.org scripts want their scripts to be ~~secure and encrypted~~ to make people have to buy it from them, and not get it for free.
[QUOTE=iamgoofball;43627121]All this encryption talk is probably because of that terrible "coderhire" place. If people weren't [URL="http://coderhire.com/jobs/view/3257"]shelling out 7 bucks for super simple scripts,[/URL] people wouldn't be pissed about code decompiling.
And more about that particular one, look at the copyright.
Under this logic, after the person gets paid their 7 bucks, they aren't allowed to reuse the thing [I]they made.[/I]
I can understand a system for being able to pay people for their hard work.
But this?
Shit like that is highway robbery. And it's why people keep striving to encrypt code.
EDIT: Here's an even worse example with an even worse license: [url]http://coderhire.com/jobs/view/3267[/url]
This is literally just "here's 16 bucks, your code is mine, don't you dare claim it's yours or use it again otherwise I can sue your ass."
People like this are encouraging this baseless need to encrypt the code. The people who make extreme amounts of money off of selling their cheap likely borrowed from garrysmod.org scripts want their scripts to be ~~secure and encrypted~~ to make people have to buy it from them, and not get it for free.[/QUOTE]
You're cherry picking evidence. You've not mentioned one of the dozens upon dozens of scripts (mine included) that people spent weeks working on and wrote 100% of the code themselves. They taught themselves Lua because they were interested in the language, and interested in the game.
Sure you can point to some dudes shitty DarkRP HuD and say "This is literally the reason for all of our problems." But that's such a small facet of what coderhire facilitates that I honestly don't consider it worth mentioning.
In my humble opinion, the real debate is all within the scope of intellectual property, and the lengths that people are willing to go to defend it. I for one, do not understand why people are against the [I]option[/I] to encrypt code. If you want your code to be easily accessabile for others to learn and read from, why the hell not? It's your code, your decision. What baffles me is that some people say that because they think that way, that no one should have the choice to protect their own creation.
Granted, as many have said before, and I'm sure will say in reply to this comment, Lua is an open source scripting language. To ask for complete security within Lua would be absurd without the help of garry, and we all know how likely that's been. To me, however, the idea of intentionally squashing other people's attempts at securing the code ( a good exercise regardless of the reason; it teaches excellent use of the language when done correctly ) to me is just ridiculous.
Edit:
[QUOTE=bobbleheadbob;43623942]Where's Acecool? I'm sure he'd be having a field day at all this shit.[/QUOTE]
He was banned for getting too rowdy, along with handsome matt. I'd be interested to hear what both of them have to say when their ban durations are over.
[QUOTE=CallMePyro;43627274]
Granted, as many have said before, and I'm sure will say in reply to this comment, Lua is an open source scripting language. To ask for complete security within Lua would be absurd without the help of garry, and we all know how likely that's been. To me, however, the idea of intentionally squashing other people's attempts at securing the code ( a good exercise regardless of the reason; it teaches excellent use of the language when done correctly ) to me is just ridiculous.[/QUOTE]
People aren't necessarily "squashing people's attempts at securing code", we're showing them how simple it is to circumvent any protections put on 'encrypted' Lua. There's no point in encrypting your Lua when many experienced programmers can break the protection in under a minute.
majority of people that steal lua already know what they're doing
if you want to protect your lua, garry is going to need to do something about it.
[QUOTE=zerothefallen;43627339]majority of people that steal lua already know what they're doing
if you want to protect your lua, garry is going to need to do something about it.[/QUOTE]
Garry will probably never do anything about it unless he fixes the security exploits with bytecode that Azuisleet mentioned (which I doubt will happen).
[QUOTE=iamgoofball;43627121]... they aren't allowed to reuse the thing they made.[/QUOTE]
It's true that software likely wouldn't qualify as a work for hire (in the case of CoderHire) but if the contract includes copyright assignment then whoever posted the job very clearly does have legal copyright of the work and not the contractor. There's nothing unusual or exploitative about it.
Since I can first remember this has been a topic of discussion. It's clear you won't be able to hide your clientside code. If you don't want people to see your code don't send it to the client. Hide your server behind some module that loads bytecode. Accept payments in bitcoin. In the end it seems trivial to put so much effort into protecting some VGUI code when there's more value in entire gamemodes.
[QUOTE=iamgoofball;43627121]This is literally just "here's 16 bucks, your code is mine, don't you dare claim it's yours or use it again otherwise I can sue your ass."[/QUOTE]
Generally speaking in the real world when you commission something you sort of expect to own it.
[QUOTE=bobbleheadbob;43623942]Where's Acecool? I'm sure he'd be having a field day at all this shit.
Would it be possible to execute code without RunString? For instance, using patterns, to execute a string based off its contents and completely avoid predefined Lua compilation?
Regardless I find that string encryption (not just Lua files to be executed) is a valuable tool for data storage.[/QUOTE]
I'm not sure what you want me to add. I created a system which prevents cache from being created; similar to how this is being described. If it's coded similarly then well yeah.
What I did was rewrote the net system to handle unlimited data per message sent, added secure message signing. I also created the fileio system which lets me package data together; meaning, I can turn entire directories of files into 1 file with proper load order.
You do need RunString; but I have overridden RunString on both the client and the server. The server-side prevents anything from being executed as an exploit prevention technique. For client-side, it requires salt, pepper and other keys to run code. Those salt/pepper and hash data is based on time, and a few other details. So when the server sends it to the client to run, they have a few seconds to execute before that code is worthless. You may consider doing something similar.
The only way for them to get the inbound code is by reading packets of encrypted Lua, using a DLL to inject into GMod and hook into RunString, but as nothing is returned, they'd have to copy the code, the salt and pepper and the hash, then they'd have to figure out the mechanism of running the code to decrypt it in order to actually read it. Hopefully they'd be VAC Banned before they'd figure it out.
If you want to talk security, feel free to PM me.
Sorry, you need to Log In to post a reply to this thread.