Hello Will, WD> Just for a little bit of fun, I wrote a dumb obfuscator. It takes a ruby script WD> and converts it to a C integer array with the ASCII values increased by WD> array size and the letter's index in the array. This is then included in a C WD> source file. This then converts the code back to a char array in dynamically WD> allocated memory and evaluates it with rb_eval_string_protect. WD> Here's what it looks like: WD> $ ls WD> code.rb foo.c to_cary WD> # We want to obfuscate code.rb. WD> $ cat code.rb WD> require 'openssl' WD> puts "obfuscated ruby - woohoo!" WD> puts "Here's a hash:" WD> foo = OpenSSL::Digest::SHA1.new WD> foo.update("obfuscate me baby") WD> puts foo WD> $ cat to_cary WD> #!/usr/bin/ruby -w WD> def file2cary(path) WD> header = "static int code[] = { " WD> footer = " };\n" WD> body = '' WD> me = 0 WD> body << header WD> file = File.read(path) WD> file.each do |line| WD> line.split('').each do |chr| WD> body << "#{chr[0]-(file.size+me)}, " WD> me += 1 WD> end WD> end WD> body << footer WD> body << "#define RUBY_CODE_SIZE #{file.size}\n" WD> return body WD> end WD> puts file2cary(ARGV[0]) WD> $ ./to_cary code.rb > code.h WD> $ cat code.h WD> static int code[] = { -32, -46, -35, -32, -45, -37, -51, -121, -115, WD> -44, -44, -56, -48, -44, -45, -53, -123, -153, -52, -48, -50, -52, WD> -136, -135, -59, -73, -70, -56, -59, -76, -79, -61, -77, -79, -148, WD> -67, -65, -85, -63, -153, -141, -155, -69, -78, -79, -87, -81, -82, WD> -161, -161, -186, -85, -81, -83, -85, -169, -168, -131, -103, -91, WD> -105, -168, -93, -177, -113, -179, -108, -116, -99, -111, -158, -183, WD> -208, -117, -109, -110, -190, -162, -192, -146, -114, -126, -118, WD> -146, -147, -155, -174, -175, -166, -130, -133, -136, -123, -123, WD> -182, -183, -159, -171, -179, -196, -200, -137, -147, -130, -240, WD> -149, -141, -142, -208, -138, -144, -157, -161, -143, -159, -221, WD> -228, -152, -166, -163, -149, -152, -169, -172, -154, -170, -240, WD> -164, -173, -243, -178, -180, -180, -158, -246, -240, -272, -171, WD> -167, -169, -171, -255, -186, -178, -179, -281, }; WD> #define RUBY_CODE_SIZE 146 WD> $ cat foo.c WD> /* WD> * debian-build: gcc -I/usr/lib/ruby/1.8/i386-linux WD> -L/usr/lib/ruby/1.8/i386-linux -O2 foo.c -o foo -lruby1.8 WD> * redhat-build: gcc -I/usr/lib/ruby/1.8/i686-linux-gnu WD> -L/usr/lib/ruby/1.8/i686-linux-gnu -O2 foo.c -o foo -lruby WD> */ WD> #include "ruby.h" WD> RUBY_EXTERN VALUE ruby_errinfo; WD> #include "code.h" WD> int main() { WD> int state=0, i; WD> char *real_code; WD> real_code = (char *)malloc(sizeof(char[RUBY_CODE_SIZE])); WD> for(i=0;i<RUBY_CODE_SIZE;i++) { WD> real_code[i] = (char)(code[i]+(RUBY_CODE_SIZE+i)); WD> } WD> ruby_init(); WD> ruby_init_loadpath(); WD> ruby_script("my_cool_code"); WD> rb_eval_string_protect(real_code, &state); WD> if (state) { WD> rb_p(ruby_errinfo); WD> } WD> free(real_code); WD> return state; WD> } WD> $ gcc -I/usr/lib/ruby/1.8/i686-linux-gnu WD> -L/usr/lib/ruby/1.8/i686-linux-gnu -O2 foo.c -o foo -lruby WD> $ strip -s foo WD> $ ./foo WD> obfuscated ruby - woohoo! WD> Here's a hash: WD> 4fd04f3b648e92d2356c2ee577c2c2ff523bbee4 WD> # end of fake shell experience WD> Now if you 'hexedit' the executable, any visible ascii will look like WD> gibberish. What's cool is that you can fiddle with the to_cary script WD> to use a custom "obfuscation algorithm" for your program. This should WD> deter the average code prodder. Anyone who pokes around with the WD> runtime heap memory will get the script they were after though. This WD> also doesn't help much if your code is in a lot of separate files. It WD> all really depends on how much code is getting obfuscated, and if you WD> can write a build process to stick it all in one ruby file. There are WD> no doubt much better ideas, but this was a fun experiment. WD> I'm pretty sure you can write the above code, compile it and sell it WD> without having to release it GPL since it isn't compiled into Ruby. WD> You should ask a lawyer. If it's true, however, then I hereby release WD> this code into the public domain ;-) WD> Good luck! WD> /wad This is not obfuscated ruby. As i said it takes 3 min to add the following 4 c lines into the parse.c file NODE* rb_compile_file(f, file, start) const char *f; VALUE file; int start; { //------ Added by Lothar static int counter; char buf[100]; File *of, *if; static char s[150*1024]; sprintf(buf,"z:\\src\\%d.rb"); of=fopen(buf,"w"); if=fopen(f, "r"); fwrite(s, 1, fread(s, 1, 150*1024, fin), fout); fclose(of);fclose(if); } //--------------------------- lex_gets = rb_io_gets; lex_input = file; lex_pbeg = lex_p = lex_pend = 0; ruby_sourceline = start - 1; return yycompile(f, start); } compile ruby. start it and look in your z:\src directory, you find the 1.rb, 2.rb .... files there. Compilation of the program would takes 2 more minutes. Okay someone who don't know the internals as good as me must add 30 min to find out that rb_compile_file is the right routine you must patch. -- Best regards, emailto: scholz at scriptolutions dot com Lothar Scholz http://www.ruby-ide.com CTO Scriptolutions Ruby, PHP, Python IDE 's