Obfuscating Ruby Code.

K

Ken Hilton

Does anyone know of a Ruby source code obfuscator that's reliable and
readily available? If so, I'd appreciate a pointer to it (apparently, both
ruby-lang and rubygarden are down at the time of this posting so I can't
check for myself.)

Thanks in advance,

Ken.
 
M

Mark Firestone

You could just let me write the program for you. That should keep anyone
from reading it.

"Well if it makes you feel any better, he's probably doing her right now."

--------------------------------------------------------------
Website - http://www.retrobbs.org
Tradewars - telnet tradewars.retrobbs.org
BBS - http://bbs.retrobbs.org:8000
IRC - irc.retrobbs.org #main
WIKI - http://www.tpoh.org/cgi-bin/tpoh-wiki

----- Original Message -----
From: "Ken Hilton" <[email protected]>
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <[email protected]>
Sent: Tuesday, June 01, 2004 10:08 PM
Subject: Obfuscating Ruby Code.
 
K

Ken Hilton

Too funny, I expected as much ;) Seriously, I have certain customers who do
not want to purchase a source code license but since Ruby source is required
(no pun intended) to deliver a Ruby app., customers must receive the source
(and converting to C is not generally an option.) I'm actually designing an
obfuscator and will happily share it should a suitable alternative not
already exist. (And I hope your code is not so unreadable as to be
considered self-obfuscating, unless of course you planned on everything
being written in Deutsch :)

Ken.

"I want to leave this world the same way I came into it: naked, spanked and
screaming."
 
G

Gregory Millam

Received: Wed, 2 Jun 2004 10:18:39 +0900
Too funny, I expected as much ;) Seriously, I have certain customers who do
not want to purchase a source code license but since Ruby source is required
(no pun intended) to deliver a Ruby app., customers must receive the source
(and converting to C is not generally an option.) I'm actually designing an
obfuscator and will happily share it should a suitable alternative not
already exist. (And I hope your code is not so unreadable as to be
considered self-obfuscating, unless of course you planned on everything
being written in Deutsch :)

Ken.

Err ...

Obfuscate Ruby code? I'm at a loss here ... :D. Perl is inanely obfuscated by default, but Ruby?

How does obfuscating solve your problem? How is that even a problem? Just include a compiled ruby interpreter for your target platform, and have a link in your code that says "For more info about ruby and to download the interpreter, go to www.ruby-lang.org" ...

Obfuscaters serve no real use - as long as somebody can pass your code through a lexer, it's instantly unobfuscated.

- Greg
 
B

Bill Kelly

Hi, Ken,

From: "Ken Hilton said:
I'm actually designing an
obfuscator and will happily share it should a suitable alternative not
already exist.

I'm very interested in this, and would be willing to help if I
could be of any assistance.

Have you decided on an approach? I presume there must be
restrictions on certain dynamic aspects of Ruby, such as
string eval() not being able to reference any obfuscated code?



Regards,

Bill
 
B

Bill Kelly

Hi,

From: "Gregory Millam said:
How does obfuscating solve your problem? How is that even
a problem? Just include a compiled ruby interpreter for
your target platform, and have a link in your code that
says "For more info about ruby and to download the
interpreter, go to www.ruby-lang.org" ...

Obfuscaters serve no real use - as long as somebody can pass
your code through a lexer, it's instantly unobfuscated.

I imagine the obfuscation would include translation of once-
meaningful identifiers (variable names, method names, ...)
into meaningless gibberish. A lexer would not help much there.

Such an obfuscator sounds really tough to write for Ruby
though... I presume the string form of eval() would have
to be disallowed from referring to any code subject to
obfuscation...

I would be very interested in a working Ruby code obfuscator,
even given certain restrictions like that. I'm writing an
application in Ruby that will likely be heavily pirated, like
a video game, as soon as a cracked copy of it becomes
available. As with video games, which i used to do for about
9 years professionally, we're just trying to delay the time it
takes for someone to produce a cracked version. At least,
I'm presuming anyone needing a Ruby code obfuscator is probably
coming from the same situation. That's why I'd like one anyway.
I'm developing in Ruby because I want to add features faster
than the competition. (Not to mention how much fun programming
in Ruby is. :) But I've gone into writing this app in Ruby
knowing I'm going to need *some* solution to delaying the
(inevitable) appearance of a cracked version of my app. So I'm
very glad to hear Ken is working on such a technology, and
grateful he'd be willing to share it.


Regards,

Bill
 
J

jm

How about supplying a modified ruby interpreter? The only difference
between this one and the standard one is that it only reads encrypted
files that decrypt with the compiled in key or a key that in itself is
obfuscated in a file. This would mean that you don't need to supply
readable source, in fact to the end user it would look like native or
byte code. You could extend this to have the code signed or something
if you wished.

J.

Ken said:
[...] I'm actually designing an obfuscator and will happily share it
should a suitable alternative not already exist.

I think you're on safe ground, Ken.

This thread may confirm:
www.ruby-talk.org/100469 (9 messages)


daz
 
R

Robert Klemme

Bill Kelly said:
Hi,



I imagine the obfuscation would include translation of once-
meaningful identifiers (variable names, method names, ...)
into meaningless gibberish. A lexer would not help much there.

Such an obfuscator sounds really tough to write for Ruby
though... I presume the string form of eval() would have
to be disallowed from referring to any code subject to
obfuscation...

Yes indeed. I harvest a slight doubt that this is possible in Ruby - at
least it's an order of magnitude more difficult than for other languages:
you need to take into consideration

- singleton methods
- the eval family of methods
- loaded modules
- ObjectSpace
- implicit conversions (you don't want to change the name of #to_s or
#coerce)
- dynamic mixins
- ...

This will make it very hard to decide whether a given identifier (aka
constant) can safely be replaced by an obfuscated constant and which
constant to use.
I would be very interested in a working Ruby code obfuscator,
even given certain restrictions like that. I'm writing an
application in Ruby that will likely be heavily pirated, like
a video game, as soon as a cracked copy of it becomes
available. As with video games, which i used to do for about
9 years professionally, we're just trying to delay the time it
takes for someone to produce a cracked version. At least,
I'm presuming anyone needing a Ruby code obfuscator is probably
coming from the same situation. That's why I'd like one anyway.
I'm developing in Ruby because I want to add features faster
than the competition. (Not to mention how much fun programming
in Ruby is. :) But I've gone into writing this app in Ruby
knowing I'm going to need *some* solution to delaying the
(inevitable) appearance of a cracked version of my app. So I'm
very glad to hear Ken is working on such a technology, and
grateful he'd be willing to share it.

Maybe your best bet is to encrypt all source code with a public keys and
create a compiled Ruby interpreter that decrypts code with a private key
when reading a file. That way others could use CryptRuby(TM) also. A
slight disadvantage is, that you need to keep the sources to yourself,
thus becoming the only source of compiled interpreters for that Ruby
variant...

Kind regards

robert
 
M

Michael Neumann

Does anyone know of a Ruby source code obfuscator that's reliable and
readily available? If so, I'd appreciate a pointer to it (apparently, both
ruby-lang and rubygarden are down at the time of this posting so I can't
check for myself.)

Take a look at bRuby. It can dump the interal node-tree and then load it
again (as far as I understand it). No Ruby sourcecode anymore. See also
the Exerb project.

http://bruby.sourceforge.jp/index.en.html

Regards,

Michael
 
A

Andrew Walrond

Maybe your best bet is to encrypt all source code with a public keys and
create a compiled Ruby interpreter that decrypts code with a private key
when reading a file. That way others could use CryptRuby(TM) also. A
slight disadvantage is, that you need to keep the sources to yourself,
thus becoming the only source of compiled interpreters for that Ruby
variant...

It would be childs play to extract the private key from the interpreter
though.
 
L

Lothar Scholz

Hello Michael,


MN> Take a look at bRuby. It can dump the interal node-tree and then load it
MN> again (as far as I understand it). No Ruby sourcecode anymore. See also
MN> the Exerb project.

MN> http://bruby.sourceforge.jp/index.en.html

But this is easy to reverse. It does not much more then removing the
comment lines. You can traverse the sourcecode and sometimes get a much
more readable source code - because the output routine is able to do
correct indentation. So there could be one generic tool(!!) to crack
protected ruby code and this is the main problem. The heart of copy
protection is to make the cracking process so difficult that only a
few very very skilled programmer can crack your application and need a
long time to do this.
 
M

Michael Neumann

Hello Michael,



MN> Take a look at bRuby. It can dump the interal node-tree and then load it
MN> again (as far as I understand it). No Ruby sourcecode anymore. See also
MN> the Exerb project.

MN> http://bruby.sourceforge.jp/index.en.html

But this is easy to reverse. It does not much more then removing the

Hm, I thought, a node-dump does not contain the variable names (local
variables), or at least does not require them for execution? I am
probably wrong.

Hm, sure, the method names must be stored. But one could modify the
interpreter to only store hashes of the method names, and use them to
call the methods. That might give quite good obfusciation.

Regards,

Michael
 
L

Lothar Scholz

Hello Michael,


MN> Hm, I thought, a node-dump does not contain the variable names (local
MN> variables), or at least does not require them for execution? I am
MN> probably wrong.

Look at "node.h". The nodes store ID values which are atoms (integers
that represent strings in a unique way). But there is no garantee that
one atom name integer as in the next ruby.exe start. And of course
they depend on the "require" order of the different source files.

MN> Hm, sure, the method names must be stored. But one could modify the
MN> interpreter to only store hashes of the method names, and use them to
MN> call the methods. That might give quite good obfusciation.

There is no possible mapping for this. Hashes are not unique. You must
store the string in one way or the other. As long as you can look at
the source every person with 1 year C experience can reverse this.
 
M

Michael Neumann

Hello Michael,



MN> Hm, I thought, a node-dump does not contain the variable names (local
MN> variables), or at least does not require them for execution? I am
MN> probably wrong.

Look at "node.h". The nodes store ID values which are atoms (integers
that represent strings in a unique way). But there is no garantee that
one atom name integer as in the next ruby.exe start. And of course
they depend on the "require" order of the different source files.

MN> Hm, sure, the method names must be stored. But one could modify the
MN> interpreter to only store hashes of the method names, and use them to
MN> call the methods. That might give quite good obfusciation.

There is no possible mapping for this. Hashes are not unique. You must
store the string in one way or the other. As long as you can look at
the source every person with 1 year C experience can reverse this.

Hm, but you could replace all "method_name" methods with
"obfuscated_method_name" (e.g. using a SHA1 hash function) and if you
know all method names a priori, then you could use a perfect hash. Or
if there should be a collision, then fall back using plain method names.

Obfusciating method names should be doable, and without knowing the real
names, it's much harder to read.

Regards,

Michael
 
G

Guest

Hi,

Wouldn't it be possible to convert the ruby code to C code? Each ruby
class etc. can also be written in C with different syntax, so a 1:1
conversion should be possible, not? Once it is C code you can compile it
just like any ordinary program.

Regards,

Peter
 
R

Robert Klemme

Andrew Walrond said:
It would be childs play to extract the private key from the interpreter
though.

You may be right. While there's no absolute security, certainly some
effort could be made to hide it appropriately. I'm not too familiar with
current technologies in that area, but I have the impression one could do
much bettern than declaring a char array with the key in it...

Did I overlook something?

robert
 
L

Lothar Scholz

Hello Michael,

MN> Hm, but you could replace all "method_name" methods with
MN> "obfuscated_method_name" (e.g. using a SHA1 hash function) and if you
MN> know all method names a priori, then you could use a perfect hash. Or
MN> if there should be a collision, then fall back using plain method names.

The main problem comes with the dynamic nature of ruby. Other people
already mentioned some of this. The node tree only gives you a nice
readable syntax representation, but it does not solve any of the
problems.

Of couse if you have a "clean" program then it shouldn't be so difficult, but
writing a generic obfuscator is an almost impossible way. For example
look at "tk.rb" - its a really ugly ruby code using all kind of tricks
that are possible with an interpreted ruby.

So to repeat myself the best way is to add some kind of decryption
into the ruby.exe and make the modified ruby source code as closed
source.
 
L

Lothar Scholz

Hello Robert,

RK> You may be right. While there's no absolute security, certainly some
RK> effort could be made to hide it appropriately. I'm not too familiar with
RK> current technologies in that area, but I have the impression one could do
RK> much bettern than declaring a char array with the key in it...

But you must provide the decryption code. And whatever you do, you only
need to add one print stratement at the right position to dump the encryption
key. And if this position is known, the cracker got it.

The key to good software protection is completely based on hiding
this right position. For example protection shields like Armadillo,
decode individuell memory pages on the fly so that crackers can't dump
the code and deassemble it easily.

If matz does not change the license to BSD, maybe it is possible to
obfuscate the ruby c source code after adding something like this.
Shuffling the order of functions (which results in different compiled
binaries) and provide different ruby.exe with different downloads - for
example build 100 different installer packages and randomly select one
of them for downloads. So even a working patch would only work with
about 1/100 of the downloads. Making it really frustrating for
crackers to get this. Remember that 95% of the crackers do it for
getting fame in the community, not for getting money or doing reverse
engineering of your wisdom and knowledge.
 
G

Gregory Millam

Received: Wed, 2 Jun 2004 21:42:14 +0900
But you must provide the decryption code. And whatever you do, you only
need to add one print stratement at the right position to dump the encryption
key. And if this position is known, the cracker got it.

Why even bother modifying the ruby source?

Create a C extension that defines a "myrequire", or redefines require so that it loads the provided ruby script after passing it through your proprietary decrypting code. Then call ruby with ruby -r mydecrypter.so -e "myrequire 'main.crb'" (crb = encrypted ruby?). The C extension doesn't need to be GPL, as it's not a part of the ruby interpreter, just a compiled .so that's loaded at run time. No need to provide the code for that.

- Greg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top