Ruby code obfuscation

Körülnéztem a neten és nem igazán találok olyan megoldást, amely Ruby kódot olvashatatlanná tesz és még akár nyílt forráskódú is. Van fizetős megoldás, olyan ami C-re konvertál meg byte kódra, de nem tetszenek. Olyat szeretnék, aminek az eredménye továbbra is megetethető a standard Ruby interpreterrel. Ha valakinek maximális elrejtés kell, annek esetleg ez játszhat.

Valszeg lefejlesztem Ruby-ban. Habár sokak szerint nem ér semmit, szerintem mégis.

Lenne kedve valakinek beszállni az ötletelésbe hogy hogy lenne érdemes? A következőkre gondoltam:

- megjegyzések törlése a kódból
- változó és függvény nevek random stringre cserélése
- üres sorok törlése
- a sorok egybevonása ; jellel

Tudom hogy ezek közül sok dolog automatizáltan visszaalakítható, de nem ez a lényeg. Időbe kerül és a kód írásakor felépített struktúra elvész. Nem beszélve arról hogy a nagy nehezen visszanyert valamennyire olvasható kód továbbfejlesztése nehéz lesz. Ennyi elégséges, már ez is több mint a semmi. Azt akarom figyelembe venni, hogy ki ellen akarom védeni az odaadandó forráskódot.

Pár perc alatt ennyi jut eszembe. Ide blogolom majd a többi ötletemet.

Szerintetek?

Szerk.: bár kicsit jobban belegondolva, lehet maradok JRuby-nál és a bytecode-nál.

Hozzászólások

"- változó és függvény nevek random stringre cserélése"

Egyszerű random helyett egymásra nagyon hasonlító stringek használata? Igaz egy automatizált visszaállító megoldást ez nem annyira zavarja, de szerintem vicces. :)

Metódusparaméterek felcserélése véletlenszerűen?
Osztályok metódusainak, attribútumainak felcserélése véletlenszerűen? (Nem tudom, rubyt mennyire zavarja, ha egy osztályon belül olyan attribútumra, metódusra hivatkozol amit nagyobb sorszámú sorban deklarálsz.)
Nem csak sorok összevonása, de bizonyos korlátok között sorok véletlenszerű tördelése? (Szintén, nem tudom rubyban ez mennyire kivitelezhető.)
Random kikommentelt kódsorok beszúrása? :)
Konstansok kiemelése egy nagy map-ba, véletlenszerű kulcsokkal? (Oké, ez hat a teljesítményre.)

Szerintem a hosszabb random nevek jobban összefolynak mint az elején egyformák és a végén pár karakterben különbözők.

Az ötletek tetszenek!

Kérdés, hogy ezzel most tényleg adnék-e a szarnak egy pofont, vagy más is hasznosnak látná? Akár más nyelvhez implementálva?

Vagy maradjon a java bytekód JRuby-val előállítva?

Közben fel merült egy dolog: a lényeg, hogy 3rd party lib-ekkel gond lesz (jelen esetben mysql), tehát a JRuby-s java bytecode generálás csak standard lib-eket használó kódnál fog játszani ahogy látom. Érthető is, mert egy natív lib-et - melynek csak egy wrappere van ruby-ban - hogyan is tudna legenerálni bytecode-ként.

Vagy kellene hogy tudjon a java kód hivatkozni a külső lib-re és valamit én fordíthatok rosszul? Ez egyelőre nem tiszta.

Biztosan, de én a kód módosítása nélkül szerettem volna Java bytecode-ot generálni - ami megy is, de eddig még csak külső lib nélkül tudok fordítani.

Azt szeretném megtudni, hogy megetethetem-e a külső lib Ruby wrapper-ét JRuby-val és akkor lefordul-e a kód Java bytecode-ra úgy, hogy tudja használni a külső lib-et.

Meg is van a válasz:
https://github.com/jruby/jruby/wiki/C-Extension-Alternatives

"JRuby versions prior to 1.6 did not support Ruby C extensions, and even in 1.6 the support is still "in development" and considered experimental. As of 1.7, it has been disabled and will likely be removed."

Tehát sajnos nincs native kiterjesztés támogatás és nem is lesz, hanem ahogy feljebb írtad BaT, Java-s helyettesítő lib kell.

Talán nem is kell JRuby:

Úgy látszik hogy Ruby 2.0-tól lesz bytecode import / export.

"Ruby 1.9 runs on the YARV virtual machine and so will Ruby 2.0, but Ruby 2.0 is expected to make it simple to save pre-compiled Ruby scripts to bytecode representations and to then run these directly. Running pre-compiled bytecode will skip the parsing stage of the standard interpretation process. If you use Rubinius or JRuby you may be familiar with this concept."

Ezt még le akarom tesztelni később. Ha valaki leteszteli, írja meg működik-e az export.

Szerk.: sajnos úgy tűnik még várni kell pár minor kiadást a rendes bytecode export / import-hoz.

http://www.ruby-forum.com/topic/154854#684667

Ez a bejegyzés alapján összeraktam egy script-et, amellyel "script file.rb" módon file.rbo-t generálok. Majd ezt beadva neki "script file.rbo" módon a bytecode-ot visszatölti és futtatja.

Ehhez meg kell patch-elni az interpretert, és újrafordítani a bytecode visszatöltés engedélyezéséhez.

Sajnos nem igazán jól működik és random hibákat dobál (memória elfogy meg hasonlók). Látszik hogy nem véletlenül nem engedélyezték még a bytecode import / export-ot gyárilag.

Marad JRuby megoldásnak ha nincsenek natív libek.

Nem értem a problémát.
Nekem minden forráskódom így néz ki alapból. :)

Refaktoraltasd kisz occo indiai szjaccal. Problem solved. Es meg olcso is. Ha vannak tesztjeid, akkor lehet, hogy meg mukodni is fog. ;)

--
|8]

Szerintem cseréld a metódusneveket, adattagokat, stb. véletlenszerű kínai karakterekre :-)

Fuszenecker_Róbert

Ez zárt és fizetős és nem teljesen ugyanazt teszi. Ők szállítják az interpretert is. Pl. nincs még 1.9.3-as támogatás sem náluk ahogy olvastam, és ez is korlátot szab.

Lenne szerinted létjogosultsága a fentinek nyílt forrású megoldásként úgy, hogy a kódot csak a fent leírtak szerint módosítja és továbbra is futtatható lesz a célzott interpreter fajtán és verzión a használt 3rd party lib-ekkel együtt?

Fene tudja, szerintem nem. Eloszor is, mi lenne az igeny, amit ez kielegit? Jo nehez legyen debugolni a kodot, ha esetleg kell? En ilyen teren sosem hittem a security through obscurityben. Ha el akarjuk rejteni a forrast, akkor kodoljuk le, vagy forditsuk bytekodra, de az obfuszkacio legfeljebb csak funfaktort ad a dologhoz, semmi egyebet.

Aztan a ruby nem C, sok konstrukciot egyszeruen nem tudsz ertelmesen obfuszkalni. Nyilvan lehet ifeket inline-ositani, do blokkokat egysorositani, valtozoneveket elmaszkolni - de ez viszonylag keveset ront a kod erthetosegen, es roppant egyszeru visszakodolni is. Mig pl. C-nel ugye ott vannak a makrok is, amivel mar jol el lehet bolonditani a kodot.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Ez érdekes. Ez alapján azt várnám, hogy le tudom fordítani a Ruby kódomat Java bytecode-ra. De nem akar összejönni.


$ ls
hello.rb
$ cat hello.rb
3.times { puts "hello" }
$ jruby hello.rb
hello
hello
hello
$ jruby -S jrubyc hello.rb
$ ls
hello.rb hello.class
$ java hello
Exception in thread "main" java.lang.NoClassDefFoundError: org/jruby/ast/executable/AbstractScript
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
Caused by: java.lang.ClassNotFoundException: org.jruby.ast.executable.AbstractScript
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 13 more

Ez vajon miért lehet? A jruby.jar -t megadva -cp kapcsolóval is ugyanez a helyzet.

Sajna nem megy, nem értem miért. Igaz hogy Fedora 17-es chroot, de boot-oltam egy rendes Fedora 17-et és "yum install jruby" után is ugyanez (pedig felteszi a Java-t is nyilván).

$ java -cp /usr/share/jruby/lib/jruby.jar:. hello 
Exception in thread "main" java.lang.NoClassDefFoundError: org/jruby/util/ByteList
        at org.jruby.ast.executable.RuntimeCache.<clinit>(RuntimeCache.java:639)
        at hello.<init>(hello.rb)
        at hello.main(hello.rb)
Caused by: java.lang.ClassNotFoundException: org.jruby.util.ByteList
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 3 more

java version "1.7.0_10"
Java(TM) SE Runtime Environment (build 1.7.0_10-b18)
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)

jruby 1.7.3 (1.9.3p385) 2013-02-21 dac429b on Java HotSpot(TM) 64-Bit Server VM 1.7.0_10-b18 [linux-amd64]

De nekem az a tippem, hogy neked valami stripped jruby.jar-od van, nem fullos.

Nagyon ajanlom, hogy ismerkedj meg az RVM-mel, sokkal jobb, mint a disztribek altal szallitott mindenfele rubykkal szivni.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Hogy obfuszkalt legyen? :-) De tenyleg, nezz utana, mit jelent a szo.

Van neki ertelme, mert szokott olyan igeny felmerulni, hogy ne legyen konnyen modosithato a kod, bar ettol meg letjogosultsaga nemigen van - de ez viszont mar egy masik tema.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. 

Felhozom a témámat, hátha azóta valakinek lett ötlete a fenti kérdésemre.

http://stackoverflow.com/questions/2123437/ruby-obfuscator
Itt rögtön az első választ láttad már?
Mintha nem tartaná jó ötletnek az eljárást.
Ha igaza van (nekem úgy tűnik, igen), akkor maradna az egyetlen út: valami bytecode-ra fordító eszköz, de ahogy elnézem az előzményeket, nálad a java-s nem működik, mással meg eddig nem találkoztam. :(

Aki tudja, csinálja, aki nem tudja, tanítja... Hm... igazgatónak talán még jó lennék. :)

A valtozonevek atirasa pl. mar problema lehet, foleg, ha egy Rails approl van szo, ahol a view-ban is le kell kovetni az atnevezeseket, ahol amugy - latszolag - nincs kontextus, hogy melyik valtozo honnet jon.

A komment kikapas szinten problema lehet, peldaul a javascript kodokbol ha kikapod az osszes kommentet, akkor Rails alkalmazas eseteben hirtelen az egesz asset pipeline eltorik. Ott mondjuk van sajat obfuscation.

De egyebkent nem is ertem, miert van erre szukseg. Vagy megbizunk abban, akinek kiadjuk a kodot, vagy nem. Ha nagyon vedeni akarjuk a kodot, akkor szet kell szervezni gemekbe, es akkor csak annak a gemnek a kodjat adod oda, amivel epp foglalkoznia kell a kulsosnek.

A support requestekhez meg kell egy checksumot kerni az approl, ha nem stimmel, akkor lehet visszadobalni, hogy belenyultak a kodba, you are alone.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.