With nodewrap, you can store the code as an AST:
[pbrannan@zaphod tmp]$ cat test.rb
def foo
p 1 + 1
end
foo()
[pbrannan@zaphod tmp]$ ruby -rnwobfusc test.rb > test2.rb
[pbrannan@zaphod tmp]$ cat test2.rb
require 'nodewrap'
if RUBY_VERSION != "1.8.2" then
$stderr.puts "Wrong Ruby version; please use 1.8.2"
exit 1
end
begin_nodes = Marshal.load("\004\010[\000")
n = Marshal.load("\004\010u:\020Node::BLOCK\002c\002\004\010[\ai\004*\255\r {\026i\004z\255\r [\ni\003? \010\"\ftest.rb[\aTi\004\336\255\r [\aTi\004p\255\r 0i\004>\255\r [\ni\003?0!\"\ftest.rb[\aFF:\010foo0i\004\254\255\r [\ni\003?(\021\"\ftest.rb[\aTi\004\312\255\r [\aTi\004\266\255\r :\006+i\004p\255\r [\ni\003? \030\"\ftest.rb[\aTi\004\216\255\r [\aFF0i\004\336\255\r [\ni\003?\020\n\"\ftest.rbi\000i\372[\aFFi\0044\255\r [\ni\003?\370\"\"\ftest.rbi\t[\aTi\004>\255\r 0i\004\242\255\r [\ni\003?P\021\"\ftest.rbi\006[\aTi\004\254\255\r [\aFFi\004f\255\r [\ni\003?\030\030\"\ftest.rb[\aFF0[\aTi\004z\255\r i\004*\255\r [\ni\003? \010\"\ftest.rb[\aTi\004R\255\r [\aTi\004 \255\r 0i\004\230\255\r [\ni\003?0\021\"\ftest.rb[\aTi\004\242\255\r :\006p0i\004\\\255\r [\ni\003?P\n\"\ftest.rb[\aTi\004f\255\r ;\000i\ai\004\312\255\r [\ni\003?\320\021\"\ftest.rb[\aFi\00600i\004 \255\r [\ni\003? \"\ftest.rb[\aTi\0044\255\r [\aFF0i\004\216\255\r [\ni\003?\370\022\"\ftest.rbi\a[\aTi\004\230\255\r 0i\004R\255\r [\ni\003?\370\n\"\ftest.rbi\006[\aTi\004\\\255\r 0i\004\300\255\r [\ni\003?\320\021\"\ftest.rb[\aFi\00600i\004\266\255\r [\ni\003?P\021\"\ftest.rbi\006[\aTi\004\300\255\r [\aFF")
begin_nodes.each do |node|
node.eval(self)
end
n.eval(self)
[pbrannan@zaphod tmp]$ ruby test2.rb
2
The process is still somewhat reversible, but afaik no one has written a
tool yet to do this.
I should also note that the code is still experimental, and you should test
your code thoroughly after transforming it this way.
Paul