Give us the option to obfuscate Ruby extensions

Given the fact that Ruby has powerful reflection techniques, many parts of an extension written in Ruby are readily available to a potential attacker willing to reverse-engineer the code and / or bypass certain licensing mechanisms. It’s easy to list all namespaces, find the name of classes / functions and then attempting to call them, while also enabling live tracing to inspect the names and values of local variables. This also works for signed and encrypted extensions, which I was quite surprised to see when testing on my own extension.

As a result, the Extension Warehouse should give us the option to obfuscate the entire code prior to encrypting it. The current system only deters non-experienced individuals from trying to mess with an extension (as they only see garbage in the encrypted files), however, the Ruby Console opens up many more possibilities. Even though obfuscation is not completely foolproof against a determined attacker, it should help discourage bad actors nonetheless.

Questions: Is anyone already obfuscating their Ruby extensions? If so, are you doing it yourself via a custom script or do you leverage any existing open-source library?

1 Like

And just how would Ruby be able to de-obfuscate code ?

Like all coding languages, the syntax of the code loaded by the language (Ruby) must be correct.

In 15 years of coding for SketchUp I’ve never heard of a “bad actor” making attacks upon extensions.

Really, it is cheaper to buy an extension then to waste the money (time) to poke into it using Ruby’s introspection and reflection methods.

1 Like

The obfuscation should simply map every symbol to something unreadable, like class LicenseChecker could be turned into class J_2dp3nMxZY_8KbV or whatever. The same should happen for functions and local variables, so the syntax will still comply with Ruby’s grammar and run successfully. The obfuscator just needs to parse the abstract syntax tree and replace the symbols in every scope with something unique (perhaps even using the current timestamp as a seed to randomize the replacement strings).

I’ve read about one such case on these forums where the developer mentioned that his plugin was accessed from some Chinese IP addresses. On top of that, their plugin was being sold on the Asian market using a slightly different name, so “bad actors” do exist.

Well obfuscation cannot prevent that sort of counterfeiting.

I would hope that there is some way to block the whole lot of Chinese IPs.

I just do not see this idea happening. There are near 200 open API bugs to fix that are not getting fixed.

It just occurred to me that you could write a Ruby script to obfuscate your own code before submitting it for signing and encryption.

You would need to leave the top level namespace module unchanged however. Your obfuscator should ensure that each extension submodule has a unique obfuscated identifier (so that your extensions do not clash with each other.)

1 Like

But it will certainly make it a lot harder. Someone is more likely to carry out an attack if they can find meaningful class names along the lines of ExtensionLoader, DatabaseAdapter, RemoteFileChecker etc.

Yes, I will probably end up doing just that unless I find an open-source library somewhere.

Let me add this quote from the EW signing page:

We are working hard to help protect your extension.
Sign and encrypt your extension to obtain a security certificate.

Hard-working developers deserve better tools in order to keep their intellectual property safe (or as safe as possible). Currently, it doesn’t seem impossible to understand the flow of an extension as set_trace_func lists all the method calls, local variables and their values. Randomizing all these symbols (both class / function names and instance / local variables) will help improve the security of SketchUp plugins.

Hey @costica1234 have you found some library to obfuscate Ruby code, or started to work on something on your own? I agree having obfuscation would be useful, and I’m willing to contribute to developing Ruby obfuscation (though I’m not a hardcore programmer).

I’m using a custom script that performs some basic obfuscation. However, it’s tightly coupled to the logic used in my extension and therefore requires non-trivial changes in other scenarios. I think that folks interested in obfuscation should look into careful string replacement strategies (although one should ideally traverse the Abstract Syntax Tree to perform those replacements).

1 Like