[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Protecting commercial ruby source code

Marcel Ward

11/18/2006 2:57:00 AM

On 17/11/06, Hiren Bridgmohun <hbridgmohun@nortech.co.za> wrote:
> Is there a way to obfuscate my ruby source code.
> I have come across ZenObfuscate which at about $2500.
> Does anyone know of any other options to protect ruby source code when it is
> distributed to clients?

I was thinking about this problem ealier this week and trying to come
up with a simple obfuscation-through-obscurity solution -- possible to
crack with the aid of a debugger but good enough to defeat casual
browsing of the contents of an executable.

One solution that seemed reasonably simple yet effective was to zip up
all the Ruby source code libraries you want to hide and then in your C
source, initialise the Ruby interpreter with a basic bootstrap and
intialise a hash with your obfuscated libraries.

The bootstrap then defines a new 'require' method which first looks
for an obfuscated version of the library and evals that or, if the
file was not in the hash, uses Kernel::require.

I have knocked up a proof of concept using a 'Deobfuscator' module
below. As I'm still a Ruby rookie, others may want to point out
improvements or problems with this.

module Deobfuscator
require 'zlib'

def self.add_lib(lib_name, obfuscated)
@@zipped ||= {}
@@zipped[lib_name] = obfuscated
end

def self.has_lib?(lib_name)
@@zipped ||= {}
puts "Looking for library #{lib_name} in our hash #{@@zipped.keys.inspect}"
@@zipped.has_key? lib_name
end

def self.deobfuscate(lib_name)
Zlib::Inflate.inflate(@@zipped[lib_name])
end

def dump
puts @@zipped.inspect
end
end

def require(lib_name)
if Deobfuscator::has_lib? lib_name
puts "Using Deobfuscator to deobfuscate library (#{lib_name})"
eval Deobfuscator::deobfuscate(lib_name)
else
puts "Using Kernel::require(#{lib_name})"
Kernel::require(lib_name)
end
end

TEST1 = <<ENDTEST1
def say_hello(name)
puts "Hello \#{name}! from library test1."
end
ENDTEST1

TEST2 = <<ENDTEST2
require 'test1'
say_hello "World"
ENDTEST2

Deobfuscator::add_lib("test1", Zlib::Deflate.deflate(TEST1))
Deobfuscator::add_lib("test2", Zlib::Deflate.deflate(TEST2))

require 'test2' # which in turn requires 'test1'

# => outputs the following:
# Looking for library test2 in our hash ["test2", "test1"]
# Using Deobfuscator to deobfuscate library (test2)
# Looking for library test1 in our hash ["test2", "test1"]
# Using Deobfuscator to deobfuscate library (test1)
# Hello World! from library test1.

Of course there could be more improvements to the final
implementation, such as compressing the initial bootstrap code so the
Ruby code is hidden until runtime (thereby ensuring people don't see
any 'deflate's or 'inflate's in the executable strnigs and get ideas).

Also one giveaway is that the hash keys are stored in plaintext here
for ease of viewing. You'd probably want to obfuscate those
similarly, which is easy enough.

Again, this is pretty noddy obfuscation and it's not going to stop a
hacker with a spare evening from getting hold of your code. For that
you should probably go with the commercial option as they will almost
certainly have invested time and effort on coming up with a far robust
solution.

Writing Ruby code to obfuscate a set of library files in a directory
using the same method of obfuscation as above and generate C source to
initialise the bootstrap should not be too difficult.

--
Marcel