InfoQ

News

RubyEncoder: Obfuscation and Code Protection for Ruby

Posted by Mirko Stocker on Oct 23, 2008 11:20 AM

Community
Ruby
Topics
Ruby on Rails ,
Security ,
Runtimes
Tags
Source Code ,
JRuby

RubyEncoder allows to protect Ruby and Ruby on Rails files by compiling and encrypting them. The encoded scripts are then run by RubyEncoder's loader. RubyEncoder is developed by Inovica Ltd, which also created a smiliar tool for PHP: SourceGuardian.

RubyEncoder can also be used to only partly protect a project, allowing plaintext Ruby and configuration files; or to limit an application to a certain host or only for a limited time period to create a trial version (more scenarios can be found in the RubyEncoder FAQ section).

InfoQ talked to Alexander Belonosov RubyEncoder's lead developer to learn more about the technical side of the project.

InfoQ: How does the encoding and the loading/running work? 

The Ruby source code is compiled into an intermediate internal format which is followed by encryption. The original source code does not exist in protected scripts once they are encoded. RubyEncoder Loader needs to be installed to run protected scripts. The loader is a Ruby extension which decodes the protected script and runs it. Protected scripts are platform independent which is very important and you may use protected scripts on any supported platforms. Loaders differ for OS and platforms. We support the following platforms for running RubyEncoder protected scripts - OSX, Linux, FreeBSD and we are just started Solaris x86 support. We have plans to add support for Windows and other UNIX in the nearest future.

InfoQ: The source is translated to an intermediate format. Do you have your own interpreter that runs it or do you restore the original Ruby source code? 

The original Ruby source code is never restored. We use internal intermediate format. [..] It is internal, binary, executable and never decodes back to original source code.

InfoQ: If you have your own interpreter, how does this interact with metaprogramming and other dynamic behavior of Ruby? Or are there no restrictions whatsoever? 

Currently the loader passes the internal representation of the code back to Ruby for execution. This lets us to keep maximum compatibility and a dynamic nature of the Ruby code. But we also keep looking on other methods and possibly will change or implement a new schema in next versions of our product. Anyway using of RubyEncoder protected products will be transparent to end-users and Ruby developers will get an updated and more effective encoder.

InfoQ: With the ParseTree gem, one can access the parse tree of a class or method. Is this affected by RubyEncoder? 

ParseTree is a great extension for investigating internals of Ruby, code optimisation etc. If you mean if we restrict to use ParseTree then the answer is no. But what is important to understand when you use tools like ParseTree is what you need to extract from Ruby internals and how to find it. I think it is also important to think of what is a reason for it, how much time will it take and what will be a final result :-)

InfoQ: Do you have plans to support other Ruby implementations, for example JRuby? Would it be possible to port the loader to Java to run JRuby code? 

Currently we support only standard Ruby. JRuby is great project and it is growing. Although it has a bit different market.

InfoQ: Using JRuby and compiled Ruby sources, would ByteCode obfuscation lead to the same protection that RubyEncoder provides? 

Using JRuby and compiled Ruby sources may produce a very good level of protection. But it is oriented for a Java environment. Our aim is to protect native Ruby and Ruby-on-Rails project initially and we may decide to look at enhancing or expanding the product later.

InfoQ: In what language is RubyEncoder written? Using Ruby and then self-encoded? 

No, I have nothing bad to say about Ruby meta programming :-) But RubyEncoder and the loaders are written in C.

RubyEncoder is a commercial product, there's also a 30 days trial version available.

Have you ever used such a code protection tool? What were your experiences with it?

Easily circumvented by Michael Guterl Posted Oct 24, 2008 2:02 PM
Is this a good idea? by Joshua Partogi Posted Oct 24, 2008 10:09 PM
Re: Is this a good idea? by Francois Ward Posted Oct 25, 2008 6:34 PM
Re: Is this a good idea? by Charles Nutter Posted Oct 27, 2008 5:57 PM
Re: Is this a good idea? by Oyku Gencay Posted Nov 5, 2008 5:31 AM
  1. Back to top

    Easily circumvented

    Oct 24, 2008 2:02 PM by Michael Guterl

    As Dmitry Severin points out on the ruby-talk mailing list this is easily circumvented... http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/318464

  2. Back to top

    Is this a good idea?

    Oct 24, 2008 10:09 PM by Joshua Partogi

    If you want to protect your ruby code, why not run under JRuby on production and compile it to Java bytecode instead?

  3. Back to top

    Re: Is this a good idea?

    Oct 25, 2008 6:34 PM by Francois Ward

    Because java bytecode isn't even THAT hard to -read-, nevermind decompile. Same deal in .NET. If you want people to take more than 15 minutes to go through it, you'll need to obfuscate it too.

  4. Back to top

    Re: Is this a good idea?

    Oct 27, 2008 5:57 PM by Charles Nutter

    Francois: Being able to read the bytecode is a long way from being able to convert it back into Ruby code. Some of the bytecode generated by JRuby can be converted into Java code, but there's no decompiler to bring it all the way back to Ruby. Making anything out of the decompiled Java code is nearly impossible, since it's essentially all calls to JRuby internal APIs. Compiling under JRuby provides at least as good obfuscation, and it has the added benefit of running faster than other Ruby implementations. And it's free.

  5. Back to top

    Re: Is this a good idea?

    Nov 5, 2008 5:31 AM by Oyku Gencay

    The tune of the idea of compiling ruby to JVM bytecode sonds nice. But try this with a fullblown rails app. I could not find any resource on this. As soon as you "compile" with JRuby you're out of the rubyland. None of the mainstream deployment methods took this into consideration. Even the Warbler has an compile_ruby = true option which basically does not work

Educational Content

Bindings, Platforms, and Innovation

This presentation focuses on the Internet and separating myth from fact, history from the future, and the mundane from the imaginative. Bob Frankston presents a vision of what could and should be.

Orchestrating Long Running Activities with JBoss / JBPM

This article explores the use of JBoss and jBPM to implement design solutions that effectively address the issue of orchestrating long running activities.

Neo4j - The Benefits of Graph Databases

This presentation covers the use of graph databases as an optimal solution for data that is difficult to fit in static tables, rapidly evolving data or data that has a lot of optional attributes.

Realistic about Risk: Software development with Real Options

This session introduces Real Options and shows how it can help in running your project. Real Options is a decision-making process that can be used to manage risk.

Communication Flexibility Using Bindings

This article discusses the use of bindings on services and references (including the instance of non-configured bindings) as the means to implement SCA communications in a Web and SOA environment.

Writing DSLs in Groovy

After a short introduction to DSLs, Scott Davis plays with the keyboard showing how to approach the creation of a DSL by typing working snippets of Groovy code that get executed.

Scaling Agile with C/ALM (Collaborative Application Lifecycle Management)

IBM Rational and InfoQ present, Scaling Agile with C/ALM, an eBook showing organizations how to become “finely tuned software delivery machines” by enabling team integration and scaling.

Concurrent Programming with Microsoft F#

Amanda Laucher presents a real life enterprise application written in F#. She shows actual code snippets, explaining design decisions and suggesting how to use some of the F# constructs.